/packages/zendframework/s3.php
[return to app]1
<?php
2 set_include_path(get_include_path() . PATH_SEPARATOR . get::$config->packagesPath() . 'zendframework');
3
4 require 'uri.php';
5 require 'http.php';
6
7 /**
8 * Zend Framework Amazon S3 class isolated from ZF dependencies to work in Vork
9 *
10 * LICENSE
11 *
12 * This source file is subject to the new BSD license that is bundled
13 * with this package in the file LICENSE.txt.
14 * It is also available through the world-wide-web at this URL:
15 * http://framework.zend.com/license/new-bsd
16 * If you did not receive a copy of the license and are unable to
17 * obtain it through the world-wide-web, please send an email
18 * to license@zend.com so we can send you a copy immediately.
19 *
20 * @category Zend
21 * @package Zend_Service
22 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
23 * @license http://framework.zend.com/license/new-bsd New BSD License
24 * @version $Id: Abstract.php 20096 2010-01-06 02:05:09Z bkarwin $
25 */
26 abstract class Zend_Service_Abstract {
27 /**
28 * HTTP Client used to query all web services
29 *
30 * @var Zend_Http_Client
31 */
32 protected static $_httpClient = null;
33
34 /**
35 * Sets the HTTP client object to use for retrieving the feeds. If none
36 * is set, the default Zend_Http_Client will be used.
37 *
38 * @param Zend_Http_Client $httpClient
39 */
40 final public static function setHttpClient(Zend_Http_Client $httpClient) {
41 self::$_httpClient = $httpClient;
42 }
43
44 /**
45 * Gets the HTTP client object.
46 *
47 * @return Zend_Http_Client
48 */
49 final public static function getHttpClient() {
50 if (!self::$_httpClient instanceof Zend_Http_Client) {
51 self::$_httpClient = new Zend_Http_Client();
52 }
53
54 return self::$_httpClient;
55 }
56 }
57
58 /**
59 * Abstract Amazon class that handles the credentials for any of the Web Services that
60 * Amazon offers
61 *
62 * @category Zend
63 * @package Zend_Service
64 * @subpackage Amazon
65 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
66 * @license http://framework.zend.com/license/new-bsd New BSD License
67 * @version $Id: Abstract.php 20096 2010-01-06 02:05:09Z bkarwin $
68 */
69 abstract class Zend_Service_Amazon_Abstract extends Zend_Service_Abstract {
70 /**
71 * @var string Amazon Access Key
72 */
73 protected static $_defaultAccessKey = null;
74
75 /**
76 * @var string Amazon Secret Key
77 */
78 protected static $_defaultSecretKey = null;
79
80 /**
81 * @var string Amazon Secret Key
82 */
83 protected $_secretKey;
84
85 /**
86 * @var string Amazon Access Key
87 */
88 protected $_accessKey;
89
90
91 /**
92 * Set the keys to use when accessing SQS.
93 *
94 * @param string $access_key Set the default Access Key
95 * @param string $secret_key Set the default Secret Key
96 * @return void
97 */
98 public static function setKeys($accessKey, $secretKey) {
99 self::$_defaultAccessKey = $accessKey;
100 self::$_defaultSecretKey = $secretKey;
101 }
102
103 /**
104 * Create Amazon client.
105 *
106 * @param string $access_key Override the default Access Key
107 * @param string $secret_key Override the default Secret Key
108 * @return void
109 */
110 public function __construct($accessKey = null, $secretKey = null) {
111 if(!$accessKey) {
112 $accessKey = self::$_defaultAccessKey;
113 }
114 if(!$secretKey) {
115 $secretKey = self::$_defaultSecretKey;
116 }
117
118 if(!$accessKey || !$secretKey) {
119 if (!class_exists('Zend_Exception')) require 'exception.php';
120 throw new Zend_Service_Amazon_Exception("AWS keys were not supplied");
121 }
122 $this->_accessKey = $accessKey;
123 $this->_secretKey = $secretKey;
124 }
125
126
127
128 /**
129 * Method to fetch the Access Key
130 *
131 * @return string
132 */
133 protected function _getAccessKey() {
134 return $this->_accessKey;
135 }
136
137 /**
138 * Method to fetch the Secret AWS Key
139 *
140 * @return string
141 */
142 protected function _getSecretKey() {
143 return $this->_secretKey;
144 }
145 }
146
147 /**
148 * @see Zend_Crypt_Hmac
149 */
150 require 'hmac.php';
151
152 /**
153 * Amazon S3 PHP connection class
154 *
155 * @category Zend
156 * @package Zend_Service
157 * @subpackage Amazon_S3
158 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
159 * @license http://framework.zend.com/license/new-bsd New BSD License
160 * @see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/
161 * @version $Id: S3.php 20096 2010-01-06 02:05:09Z bkarwin $
162 */
163 class Zend_Service_Amazon_S3 extends Zend_Service_Amazon_Abstract {
164 /**
165 * Store for stream wrapper clients
166 *
167 * @var array
168 */
169 protected static $_wrapperClients = array();
170
171 /**
172 * Endpoint for the service
173 *
174 * @var Zend_Uri_Http
175 */
176 protected $_endpoint;
177
178 const S3_ENDPOINT = 's3.amazonaws.com';
179
180 const S3_ACL_PRIVATE = 'private';
181 const S3_ACL_PUBLIC_READ = 'public-read';
182 const S3_ACL_PUBLIC_WRITE = 'public-read-write';
183 const S3_ACL_AUTH_READ = 'authenticated-read';
184
185 const S3_REQUESTPAY_HEADER = 'x-amz-request-payer';
186 const S3_ACL_HEADER = 'x-amz-acl';
187 const S3_CONTENT_TYPE_HEADER = 'Content-Type';
188
189 /**
190 * Set S3 endpoint to use
191 *
192 * @param string|Zend_Uri_Http $endpoint
193 * @return Zend_Service_Amazon_S3
194 */
195 public function setEndpoint($endpoint) {
196 if (!($endpoint instanceof Zend_Uri_Http)) {
197 $endpoint = Zend_Uri::factory($endpoint);
198 }
199 if (!$endpoint->valid()) {
200 /**
201 * @see Zend_Service_Amazon_S3_Exception
202 */
203 if (!class_exists('Zend_Exception')) require 'exception.php';
204 throw new Zend_Service_Amazon_S3_Exception('Invalid endpoint supplied');
205 }
206 $this->_endpoint = $endpoint;
207 return $this;
208 }
209
210 /**
211 * Get current S3 endpoint
212 *
213 * @return Zend_Uri_Http
214 */
215 public function getEndpoint() {
216 return $this->_endpoint;
217 }
218
219 /**
220 * Constructor
221 *
222 * @param string $accessKey
223 * @param string $secretKey
224 * @param string $region
225 */
226 public function __construct($accessKey = null, $secretKey = null, $region = null) {
227 parent::__construct($accessKey, $secretKey, $region);
228
229 $this->setEndpoint('http://'.self::S3_ENDPOINT);
230 }
231
232 /**
233 * Verify if the bucket name is valid
234 *
235 * @param string $bucket
236 * @return boolean
237 */
238 public function _validBucketName($bucket) {
239 $len = strlen($bucket);
240 if ($len < 3 || $len > 255) {
241 /**
242 * @see Zend_Service_Amazon_S3_Exception
243 */
244 if (!class_exists('Zend_Exception')) require 'exception.php';
245 throw new Zend_Service_Amazon_S3_Exception("Bucket name \"$bucket\" must be between 3 and 255
characters long");
246 }
247
248 if (preg_match('/[^a-z0-9\._-]/', $bucket)) {
249 /**
250 * @see Zend_Service_Amazon_S3_Exception
251 */
252 if (!class_exists('Zend_Exception')) require 'exception.php';
253 throw new Zend_Service_Amazon_S3_Exception("Bucket name \"$bucket\" contains invalid characters");
254 }
255
256 if (preg_match('/(\d){1,3}\.(\d){1,3}\.(\d){1,3}\.(\d){1,3}/', $bucket)) {
257 /**
258 * @see Zend_Service_Amazon_S3_Exception
259 */
260 if (!class_exists('Zend_Exception')) require 'exception.php';
261 throw new Zend_Service_Amazon_S3_Exception("Bucket name \"$bucket\" cannot be an IP address");
262 }
263 return true;
264 }
265
266 /**
267 * Add a new bucket
268 *
269 * @param string $bucket
270 * @return boolean
271 */
272 public function createBucket($bucket, $location = null) {
273 $this->_validBucketName($bucket);
274
275 if($location) {
276 $data = '<CreateBucketConfiguration><LocationConstraint>' . $location
277 . '</LocationConstraint></CreateBucketConfiguration>';
278 }
279 else {
280 $data = null;
281 }
282 $response = $this->_makeRequest('PUT', $bucket, null, array(), $data);
283
284 return ($response->getStatus() == 200);
285 }
286
287 /**
288 * Checks if a given bucket name is available
289 *
290 * @param string $bucket
291 * @return boolean
292 */
293 public function isBucketAvailable($bucket) {
294 $response = $this->_makeRequest('HEAD', $bucket, array('max-keys' => 0));
295
296 return ($response->getStatus() != 404);
297 }
298
299 /**
300 * Checks if a given object exists
301 *
302 * @param string $object
303 * @return boolean
304 */
305 public function isObjectAvailable($object) {
306 $response = $this->_makeRequest('HEAD', $object);
307
308 return ($response->getStatus() == 200);
309 }
310
311 /**
312 * Remove a given bucket. All objects in the bucket must be removed prior
313 * to removing the bucket.
314 *
315 * @param string $bucket
316 * @return boolean
317 */
318 public function removeBucket($bucket) {
319 $response = $this->_makeRequest('DELETE', $bucket);
320
321 // Look for a 204 No Content response
322 return ($response->getStatus() == 204);
323 }
324
325 /**
326 * Get metadata information for a given object
327 *
328 * @param string $object
329 * @return array|false
330 */
331 public function getInfo($object) {
332 $info = array();
333
334 $object = $this->_fixupObjectName($object);
335 $response = $this->_makeRequest('HEAD', $object);
336
337 if ($response->getStatus() == 200) {
338 $info['type'] = $response->getHeader('Content-type');
339 $info['size'] = $response->getHeader('Content-length');
340 $info['mtime'] = strtotime($response->getHeader('Last-modified'));
341 $info['etag'] = $response->getHeader('ETag');
342 }
343 else {
344 return false;
345 }
346
347 return $info;
348 }
349
350 /**
351 * List the S3 buckets
352 *
353 * @return array|false
354 */
355 public function getBuckets() {
356 $response = $this->_makeRequest('GET');
357
358 if ($response->getStatus() != 200) {
359 return false;
360 }
361
362 $xml = new SimpleXMLElement($response->getBody());
363
364 $buckets = array();
365 foreach ($xml->Buckets->Bucket as $bucket) {
366 $buckets[] = (string)$bucket->Name;
367 }
368
369 return $buckets;
370 }
371
372 /**
373 * Remove all objects in the bucket.
374 *
375 * @param string $bucket
376 * @return boolean
377 */
378 public function cleanBucket($bucket) {
379 $objects = $this->getObjectsByBucket($bucket);
380 if (!$objects) {
381 return false;
382 }
383
384 foreach ($objects as $object) {
385 $this->removeObject("$bucket/$object");
386 }
387 return true;
388 }
389
390 /**
391 * List the objects in a bucket.
392 *
393 * Provides the list of object keys that are contained in the bucket. Valid params include the following.
394 * prefix - Limits the response to keys which begin with the indicated prefix. You can use prefixes to
separate a
395 * bucket into different sets of keys in a way similar to how a file system uses folders.
396 * marker - Indicates where in the bucket to begin listing. The list will only include keys that occur
397 * lexicographically after marker. This is convenient for pagination: To get the next page of results use the
398 * last key of the current page as the marker.
399 * max-keys - The maximum number of keys you'd like to see in the response body. The server might return
fewer
400 * than this many keys, but will not return more.
401 * delimiter - Causes keys that contain the same string between the prefix and the first occurrence of the
402 * delimiter to be rolled up into a single result element in the CommonPrefixes collection. These rolled-up
keys
403 * are not returned elsewhere in the response.
404 *
405 * @param string $bucket
406 * @param array $params S3 GET Bucket Paramater
407 * @return array|false
408 */
409 public function getObjectsByBucket($bucket, $params = array()) {
410 $response = $this->_makeRequest('GET', $bucket, $params);
411
412 if ($response->getStatus() != 200) {
413 return false;
414 }
415
416 $xml = new SimpleXMLElement($response->getBody());
417
418 $objects = array();
419 if (isset($xml->Contents)) {
420 foreach ($xml->Contents as $contents) {
421 foreach ($contents->Key as $object) {
422 $objects[] = (string)$object;
423 }
424 }
425 }
426
427 return $objects;
428 }
429
430 /**
431 * Make sure the object name is valid
432 *
433 * @param string $object
434 * @return string
435 */
436 protected function _fixupObjectName($object) {
437 $nameparts = explode('/', $object);
438
439 $this->_validBucketName($nameparts[0]);
440
441 $firstpart = array_shift($nameparts);
442 if (count($nameparts) == 0) {
443 return $firstpart;
444 }
445
446 return $firstpart.'/'.join('/', array_map('rawurlencode', $nameparts));
447 }
448
449 /**
450 * Get an object
451 *
452 * @param string $object
453 * @param bool $paidobject This is "requestor pays" object
454 * @return string|false
455 */
456 public function getObject($object, $paidobject = false) {
457 $object = $this->_fixupObjectName($object);
458 if ($paidobject) {
459 $response = $this->_makeRequest('GET', $object, null, array(self::S3_REQUESTPAY_HEADER =>
'requester'));
460 }
461 else {
462 $response = $this->_makeRequest('GET', $object);
463 }
464
465 if ($response->getStatus() != 200) {
466 return false;
467 }
468
469 return $response->getBody();
470 }
471
472 /**
473 * Get an object using streaming
474 *
475 * Can use either provided filename for storage or create a temp file if none provided.
476 *
477 * @param string $object Object path
478 * @param string $streamfile File to write the stream to
479 * @param bool $paidobject This is "requestor pays" object
480 * @return Zend_Http_Response_Stream|false
481 */
482 public function getObjectStream($object, $streamfile = null, $paidobject = false) {
483 $object = $this->_fixupObjectName($object);
484 self::getHttpClient()->setStream($streamfile?$streamfile:true);
485 if ($paidobject) {
486 $response = $this->_makeRequest('GET', $object, null, array(self::S3_REQUESTPAY_HEADER =>
'requester'));
487 }
488 else {
489 $response = $this->_makeRequest('GET', $object);
490 }
491 self::getHttpClient()->setStream(null);
492
493 if ($response->getStatus() != 200 || !($response instanceof Zend_Http_Response_Stream)) {
494 return false;
495 }
496
497 return $response;
498 }
499
500 /**
501 * Upload an object by a PHP string
502 *
503 * @param string $object Object name
504 * @param string|resource $data Object data (can be string or stream)
505 * @param array $meta Metadata
506 * @return boolean
507 */
508 public function putObject($object, $data, $meta = null) {
509 $object = $this->_fixupObjectName($object);
510 $headers = (is_array($meta)) ? $meta : array();
511
512 if(!is_resource($data)) {
513 $headers['Content-MD5'] = base64_encode(md5($data, true));
514 }
515 $headers['Expect'] = '100-continue';
516
517 if (!isset($headers[self::S3_CONTENT_TYPE_HEADER])) {
518 $headers[self::S3_CONTENT_TYPE_HEADER] = self::getMimeType($object);
519 }
520
521 $response = $this->_makeRequest('PUT', $object, null, $headers, $data);
522
523 // Check the MD5 Etag returned by S3 against and MD5 of the buffer
524 if ($response->getStatus() == 200) {
525 // It is escaped by double quotes for some reason
526 $etag = str_replace('"', '', $response->getHeader('Etag'));
527
528 if (is_resource($data) || $etag == md5($data)) {
529 return true;
530 }
531 }
532
533 return false;
534 }
535
536 /**
537 * Put file to S3 as object
538 *
539 * @param string $path File name
540 * @param string $object Object name
541 * @param array $meta Metadata
542 * @return boolean
543 */
544 public function putFile($path, $object, $meta = null) {
545 $data = @file_get_contents($path);
546 if ($data === false) {
547 /**
548 * @see Zend_Service_Amazon_S3_Exception
549 */
550 if (!class_exists('Zend_Exception')) require 'exception.php';
551 throw new Zend_Service_Amazon_S3_Exception("Cannot read file $path");
552 }
553
554 if (!is_array($meta)) {
555 $meta = array();
556 }
557
558 if (!isset($meta[self::S3_CONTENT_TYPE_HEADER])) {
559 $meta[self::S3_CONTENT_TYPE_HEADER] = self::getMimeType($path);
560 }
561
562 return $this->putObject($object, $data, $meta);
563 }
564
565 /**
566 * Put file to S3 as object, using streaming
567 *
568 * @param string $path File name
569 * @param string $object Object name
570 * @param array $meta Metadata
571 * @return boolean
572 */
573 public function putFileStream($path, $object, $meta = null) {
574 $data = @fopen($path, "rb");
575 if ($data === false) {
576 /**
577 * @see Zend_Service_Amazon_S3_Exception
578 */
579 if (!class_exists('Zend_Exception')) require 'exception.php';
580 throw new Zend_Service_Amazon_S3_Exception("Cannot open file $path");
581 }
582
583 if (!is_array($meta)) {
584 $meta = array();
585 }
586
587 if (!isset($meta[self::S3_CONTENT_TYPE_HEADER])) {
588 $meta[self::S3_CONTENT_TYPE_HEADER] = self::getMimeType($path);
589 }
590
591 if(!isset($meta['Content-MD5'])) {
592 $headers['Content-MD5'] = base64_encode(md5_file($path, true));
593 }
594
595 return $this->putObject($object, $data, $meta);
596 }
597
598 /**
599 * Remove a given object
600 *
601 * @param string $object
602 * @return boolean
603 */
604 public function removeObject($object) {
605 $object = $this->_fixupObjectName($object);
606 $response = $this->_makeRequest('DELETE', $object);
607
608 // Look for a 204 No Content response
609 return ($response->getStatus() == 204);
610 }
611
612 /**
613 * Make a request to Amazon S3
614 *
615 * @param string $method Request method
616 * @param string $path Path to requested object
617 * @param array $params Request parameters
618 * @param array $headers HTTP headers
619 * @param string|resource $data Request data
620 * @return Zend_Http_Response
621 */
622 public function _makeRequest($method, $path = '', $params = null, $headers = array(), $data = null) {
623 $retry_count = 0;
624
625 if (!is_array($headers)) {
626 $headers = array($headers);
627 }
628
629 $headers['Date'] = gmdate(DATE_RFC1123, time());
630
631 if(is_resource($data) && $method != 'PUT') {
632 /**
633 * @see Zend_Service_Amazon_S3_Exception
634 */
635 if (!class_exists('Zend_Exception')) require 'exception.php';
636 throw new Zend_Service_Amazon_S3_Exception("Only PUT request supports stream data");
637 }
638
639 // build the end point out
640 $parts = explode('/', $path, 2);
641 $endpoint = clone($this->_endpoint);
642 if ($parts[0]) {
643 // prepend bucket name to the hostname
644 $endpoint->setHost($parts[0].'.'.$endpoint->getHost());
645 }
646 if (!empty($parts[1])) {
647 $endpoint->setPath('/'.$parts[1]);
648 }
649 else {
650 $endpoint->setPath('/');
651 if ($parts[0]) {
652 $path = $parts[0].'/';
653 }
654 }
655
656 self::addSignature($method, $path, $headers);
657
658 $client = self::getHttpClient();
659
660 $client->resetParameters();
661 $client->setUri($endpoint);
662 $client->setAuth(false);
663 // Work around buglet in HTTP client - it doesn't clean headers
664 // Remove when ZHC is fixed
665 $client->setHeaders(array('Content-MD5' => null,
666 'Expect' => null,
667 'Range' => null,
668 'x-amz-acl' => null));
669
670 $client->setHeaders($headers);
671
672 if (is_array($params)) {
673 foreach ($params as $name => $value) {
674 $client->setParameterGet($name, $value);
675 }
676 }
677
678 if (($method == 'PUT') && ($data !== null)) {
679 if (!isset($headers['Content-type'])) {
680 $headers['Content-type'] = self::getMimeType($path);
681 }
682 $client->setRawData($data, $headers['Content-type']);
683 }
684 do {
685 $retry = false;
686
687 $response = $client->request($method);
688 $response_code = $response->getStatus();
689
690 // Some 5xx errors are expected, so retry automatically
691 if ($response_code >= 500 && $response_code < 600 && $retry_count <= 5) {
692 $retry = true;
693 $retry_count++;
694 sleep($retry_count / 4 * $retry_count);
695 }
696 else if ($response_code == 307) {
697 // Need to redirect, new S3 endpoint given
698 // This should never happen as Zend_Http_Client will redirect automatically
699 }
700 else if ($response_code == 100) {
701 // echo 'OK to Continue';
702 }
703 } while ($retry);
704
705 return $response;
706 }
707
708 /**
709 * Add the S3 Authorization signature to the request headers
710 *
711 * @param string $method
712 * @param string $path
713 * @param array &$headers
714 * @return string
715 */
716 protected function addSignature($method, $path, &$headers) {
717 if (!is_array($headers)) {
718 $headers = array($headers);
719 }
720
721 $type = $md5 = $date = '';
722
723 // Search for the Content-type, Content-MD5 and Date headers
724 foreach ($headers as $key => $val) {
725 if (strcasecmp($key, 'content-type') == 0) {
726 $type = $val;
727 }
728 else if (strcasecmp($key, 'content-md5') == 0) {
729 $md5 = $val;
730 }
731 else if (strcasecmp($key, 'date') == 0) {
732 $date = $val;
733 }
734 }
735
736 // If we have an x-amz-date header, use that instead of the normal Date
737 if (isset($headers['x-amz-date']) && isset($date)) {
738 $date = '';
739 }
740
741 $sig_str = "$method\n$md5\n$type\n$date\n";
742 // For x-amz- headers, combine like keys, lowercase them, sort them
743 // alphabetically and remove excess spaces around values
744 $amz_headers = array();
745 foreach ($headers as $key => $val) {
746 $key = strtolower($key);
747 if (substr($key, 0, 6) == 'x-amz-') {
748 if (is_array($val)) {
749 $amz_headers[$key] = $val;
750 }
751 else {
752 $amz_headers[$key][] = preg_replace('/\s+/', ' ', $val);
753 }
754 }
755 }
756 if (!empty($amz_headers)) {
757 ksort($amz_headers);
758 foreach ($amz_headers as $key => $val) {
759 $sig_str .= $key.':'.implode(',', $val)."\n";
760 }
761 }
762
763 $sig_str .= '/'.parse_url($path, PHP_URL_PATH);
764 if (strpos($path, '?location') !== false) {
765 $sig_str .= '?location';
766 }
767 else if (strpos($path, '?acl') !== false) {
768 $sig_str .= '?acl';
769 }
770 else if (strpos($path, '?torrent') !== false) {
771 $sig_str .= '?torrent';
772 }
773
774 $signature = base64_encode(Zend_Crypt_Hmac::compute($this->_getSecretKey(), 'sha1', utf8_encode($sig_str),
Zend_Crypt_Hmac::BINARY));
775 $headers['Authorization'] = 'AWS '.$this->_getAccessKey().':'.$signature;
776
777 return $sig_str;
778 }
779
780 /**
781 * Attempt to get the content-type of a file based on the extension
782 *
783 * @param string $path
784 * @return string
785 */
786 public static function getMimeType($path) {
787 $ext = substr(strrchr($path, '.'), 1);
788
789 if(!$ext) {
790 // shortcut
791 return 'binary/octet-stream';
792 }
793
794 switch (strtolower($ext)) {
795 case 'xls':
796 $content_type = 'application/excel';
797 break;
798 case 'hqx':
799 $content_type = 'application/macbinhex40';
800 break;
801 case 'doc':
802 case 'dot':
803 case 'wrd':
804 $content_type = 'application/msword';
805 break;
806 case 'pdf':
807 $content_type = 'application/pdf';
808 break;
809 case 'pgp':
810 $content_type = 'application/pgp';
811 break;
812 case 'ps':
813 case 'eps':
814 case 'ai':
815 $content_type = 'application/postscript';
816 break;
817 case 'ppt':
818 $content_type = 'application/powerpoint';
819 break;
820 case 'rtf':
821 $content_type = 'application/rtf';
822 break;
823 case 'tgz':
824 case 'gtar':
825 $content_type = 'application/x-gtar';
826 break;
827 case 'gz':
828 $content_type = 'application/x-gzip';
829 break;
830 case 'php':
831 case 'php3':
832 case 'php4':
833 $content_type = 'application/x-httpd-php';
834 break;
835 case 'js':
836 $content_type = 'application/x-javascript';
837 break;
838 case 'ppd':
839 case 'psd':
840 $content_type = 'application/x-photoshop';
841 break;
842 case 'swf':
843 case 'swc':
844 case 'rf':
845 $content_type = 'application/x-shockwave-flash';
846 break;
847 case 'tar':
848 $content_type = 'application/x-tar';
849 break;
850 case 'zip':
851 $content_type = 'application/zip';
852 break;
853 case 'mid':
854 case 'midi':
855 case 'kar':
856 $content_type = 'audio/midi';
857 break;
858 case 'mp2':
859 case 'mp3':
860 case 'mpga':
861 $content_type = 'audio/mpeg';
862 break;
863 case 'ra':
864 $content_type = 'audio/x-realaudio';
865 break;
866 case 'wav':
867 $content_type = 'audio/wav';
868 break;
869 case 'bmp':
870 $content_type = 'image/bitmap';
871 break;
872 case 'gif':
873 $content_type = 'image/gif';
874 break;
875 case 'iff':
876 $content_type = 'image/iff';
877 break;
878 case 'jb2':
879 $content_type = 'image/jb2';
880 break;
881 case 'jpg':
882 case 'jpe':
883 case 'jpeg':
884 $content_type = 'image/jpeg';
885 break;
886 case 'jpx':
887 $content_type = 'image/jpx';
888 break;
889 case 'png':
890 $content_type = 'image/png';
891 break;
892 case 'tif':
893 case 'tiff':
894 $content_type = 'image/tiff';
895 break;
896 case 'wbmp':
897 $content_type = 'image/vnd.wap.wbmp';
898 break;
899 case 'xbm':
900 $content_type = 'image/xbm';
901 break;
902 case 'css':
903 $content_type = 'text/css';
904 break;
905 case 'txt':
906 $content_type = 'text/plain';
907 break;
908 case 'htm':
909 case 'html':
910 $content_type = 'text/html';
911 break;
912 case 'xml':
913 $content_type = 'text/xml';
914 break;
915 case 'xsl':
916 $content_type = 'text/xsl';
917 break;
918 case 'mpg':
919 case 'mpe':
920 case 'mpeg':
921 $content_type = 'video/mpeg';
922 break;
923 case 'qt':
924 case 'mov':
925 $content_type = 'video/quicktime';
926 break;
927 case 'avi':
928 $content_type = 'video/x-ms-video';
929 break;
930 case 'eml':
931 $content_type = 'message/rfc822';
932 break;
933 default:
934 $content_type = 'binary/octet-stream';
935 break;
936 }
937
938 return $content_type;
939 }
940
941 /**
942 * Register this object as stream wrapper client
943 *
944 * @param string $name
945 * @return Zend_Service_Amazon_S3
946 */
947 public function registerAsClient($name) {
948 self::$_wrapperClients[$name] = $this;
949 return $this;
950 }
951
952 /**
953 * Unregister this object as stream wrapper client
954 *
955 * @param string $name
956 * @return Zend_Service_Amazon_S3
957 */
958 public function unregisterAsClient($name) {
959 unset(self::$_wrapperClients[$name]);
960 return $this;
961 }
962
963 /**
964 * Get wrapper client for stream type
965 *
966 * @param string $name
967 * @return Zend_Service_Amazon_S3
968 */
969 public static function getWrapperClient($name) {
970 return self::$_wrapperClients[$name];
971 }
972
973 /**
974 * Register this object as stream wrapper
975 *
976 * @param string $name
977 * @return Zend_Service_Amazon_S3
978 */
979 public function registerStreamWrapper($name = 's3') {
980 /**
981 * @see Zend_Service_Amazon_S3_Stream
982 */
983 if (!class_exists('Zend_Service_Amazon_S3_Stream')) {
984 require 'stream.php';
985 }
986
987 stream_register_wrapper($name, 'Zend_Service_Amazon_S3_Stream');
988 $this->registerAsClient($name);
989 }
990
991 /**
992 * Unregister this object as stream wrapper
993 *
994 * @param string $name
995 * @return Zend_Service_Amazon_S3
996 */
997 public function unregisterStreamWrapper($name = 's3') {
998 stream_wrapper_unregister($name);
999 $this->unregisterAsClient($name);
1000 }
1001 }