|
|
@@ -1,483 +1,483 @@
|
|
|
-<?php
|
|
|
-/**
|
|
|
- * Zend Framework
|
|
|
- *
|
|
|
- * LICENSE
|
|
|
- *
|
|
|
- * This source file is subject to the new BSD license that is bundled
|
|
|
- * with this package in the file LICENSE.txt.
|
|
|
- * It is also available through the world-wide-web at this URL:
|
|
|
- * http://framework.zend.com/license/new-bsd
|
|
|
- * If you did not receive a copy of the license and are unable to
|
|
|
- * obtain it through the world-wide-web, please send an email
|
|
|
- * to license@zend.com so we can send you a copy immediately.
|
|
|
- *
|
|
|
- * @category Zend
|
|
|
- * @package Zend_Service
|
|
|
- * @subpackage Amazon_S3
|
|
|
- * @copyright Copyright (c) 2005-2008, Zend Technologies USA Inc. (http://www.zend.com)
|
|
|
- * @license http://framework.zend.com/license/new-bsd New BSD License
|
|
|
- * @version $Id: S3.php 9786 2008-06-24 23:50:25Z jplock $
|
|
|
- */
|
|
|
-
|
|
|
-/**
|
|
|
- * @see Zend_Service_Amazon_S3
|
|
|
- */
|
|
|
-require_once 'Zend/Service/Amazon/S3.php';
|
|
|
-
|
|
|
-/**
|
|
|
- * Amazon S3 PHP stream wrapper
|
|
|
- *
|
|
|
- * @category Zend
|
|
|
- * @package Zend_Service
|
|
|
- * @subpackage Amazon_S3
|
|
|
- * @copyright Copyright (c) 2005-2008, Zend Technologies USA Inc. (http://www.zend.com)
|
|
|
- * @license http://framework.zend.com/license/new-bsd New BSD License
|
|
|
- */
|
|
|
-class Zend_Service_Amazon_S3_Stream
|
|
|
-{
|
|
|
- /**
|
|
|
- * @var boolean Write the buffer on fflush()?
|
|
|
- */
|
|
|
- private $_writeBuffer = false;
|
|
|
-
|
|
|
- /**
|
|
|
- * @var integer Current read/write position
|
|
|
- */
|
|
|
- private $_position = 0;
|
|
|
-
|
|
|
- /**
|
|
|
- * @var integer Total size of the object as returned by S3 (Content-length)
|
|
|
- */
|
|
|
- private $_objectSize = 0;
|
|
|
-
|
|
|
- /**
|
|
|
- * @var string File name to interact with
|
|
|
- */
|
|
|
- private $_objectName = null;
|
|
|
-
|
|
|
- /**
|
|
|
- * @var string Current read/write buffer
|
|
|
- */
|
|
|
- private $_objectBuffer = null;
|
|
|
-
|
|
|
- /**
|
|
|
- * @var array Available buckets
|
|
|
- */
|
|
|
- private $_bucketList = array();
|
|
|
-
|
|
|
- /**
|
|
|
- * @var Zend_Service_Amazon_S3
|
|
|
- */
|
|
|
- private $_s3 = null;
|
|
|
-
|
|
|
- /**
|
|
|
- * Retrieve client for this stream type
|
|
|
- *
|
|
|
- * @param string $path
|
|
|
- * @return Zend_Service_Amazon_S3
|
|
|
- */
|
|
|
- protected function _getS3Client($path)
|
|
|
- {
|
|
|
- if ($this->_s3 === null) {
|
|
|
- $url = explode(':', $path);
|
|
|
-
|
|
|
- if (!$url) {
|
|
|
- /**
|
|
|
- * @see Zend_Service_Amazon_S3_Exception
|
|
|
- */
|
|
|
- require_once 'Zend/Service/Amazon/S3/Exception.php';
|
|
|
- throw new Zend_Service_Amazon_S3_Exception("Unable to parse URL $path");
|
|
|
- }
|
|
|
-
|
|
|
- $this->_s3 = Zend_Service_Amazon_S3::getWrapperClient($url[0]);
|
|
|
- if (!$this->_s3) {
|
|
|
- /**
|
|
|
- * @see Zend_Service_Amazon_S3_Exception
|
|
|
- */
|
|
|
- require_once 'Zend/Service/Amazon/S3/Exception.php';
|
|
|
- throw new Zend_Service_Amazon_S3_Exception("Unknown client for wrapper {$url[0]}");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return $this->_s3;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Extract object name from URL
|
|
|
- *
|
|
|
- * @param string $path
|
|
|
- * @return string
|
|
|
- */
|
|
|
- protected function _getNamePart($path)
|
|
|
- {
|
|
|
- $url = parse_url($path);
|
|
|
- if ($url['host']) {
|
|
|
- return $url['path'] ? $url['host'].$url['path'] : $url['host'];
|
|
|
- }
|
|
|
-
|
|
|
- return '';
|
|
|
- }
|
|
|
- /**
|
|
|
- * Open the stream
|
|
|
- *
|
|
|
- * @param string $path
|
|
|
- * @param string $mode
|
|
|
- * @param integer $options
|
|
|
- * @param string $opened_path
|
|
|
- * @return boolean
|
|
|
- */
|
|
|
- public function stream_open($path, $mode, $options, $opened_path)
|
|
|
- {
|
|
|
- $name = $this->_getNamePart($path);
|
|
|
- // If we open the file for writing, just return true. Create the object
|
|
|
- // on fflush call
|
|
|
- if (strpbrk($mode, 'wax')) {
|
|
|
- $this->_objectName = $name;
|
|
|
- $this->_objectBuffer = null;
|
|
|
- $this->_objectSize = 0;
|
|
|
- $this->_position = 0;
|
|
|
- $this->_writeBuffer = true;
|
|
|
- $this->_getS3Client($path);
|
|
|
- return true;
|
|
|
- }
|
|
|
- else {
|
|
|
- // Otherwise, just see if the file exists or not
|
|
|
- $info = $this->_getS3Client($path)->getInfo($name);
|
|
|
- if ($info) {
|
|
|
- $this->_objectName = $name;
|
|
|
- $this->_objectBuffer = null;
|
|
|
- $this->_objectSize = $info['size'];
|
|
|
- $this->_position = 0;
|
|
|
- $this->_writeBuffer = false;
|
|
|
- $this->_getS3Client($path);
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Close the stream
|
|
|
- *
|
|
|
- * @return void
|
|
|
- */
|
|
|
- public function stream_close()
|
|
|
- {
|
|
|
- $this->_objectName = null;
|
|
|
- $this->_objectBuffer = null;
|
|
|
- $this->_objectSize = 0;
|
|
|
- $this->_position = 0;
|
|
|
- $this->_writeBuffer = false;
|
|
|
- unset($this->_s3);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Read from the stream
|
|
|
- *
|
|
|
- * @param integer $count
|
|
|
- * @return string
|
|
|
- */
|
|
|
- public function stream_read($count)
|
|
|
- {
|
|
|
- if (!$this->_objectName) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- $range_start = $this->_position;
|
|
|
- $range_end = $this->_position+$count;
|
|
|
-
|
|
|
- // Only fetch more data from S3 if we haven't fetched any data yet (postion=0)
|
|
|
- // OR, the range end position is greater than the size of the current object
|
|
|
- // buffer AND if the range end position is less than or equal to the object's
|
|
|
- // size returned by S3
|
|
|
- if (($this->_position == 0) || (($range_end > strlen($this->_objectBuffer)) && ($range_end <= $this->_objectSize))) {
|
|
|
-
|
|
|
- $headers = array(
|
|
|
- 'Range' => "$range_start-$range_end"
|
|
|
- );
|
|
|
-
|
|
|
- $response = $this->_s3->_makeRequest('GET', $this->_objectName, null, $headers);
|
|
|
-
|
|
|
- if ($response->getStatus() == 200) {
|
|
|
- $this->_objectBuffer .= $response->getBody();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- $data = substr($this->_objectBuffer, $this->_position, $count);
|
|
|
- $this->_position += strlen($data);
|
|
|
- return $data;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Write to the stream
|
|
|
- *
|
|
|
- * @param string $data
|
|
|
- * @return integer
|
|
|
- */
|
|
|
- public function stream_write($data)
|
|
|
- {
|
|
|
- if (!$this->_objectName) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
- $len = strlen($data);
|
|
|
- $this->_objectBuffer .= $data;
|
|
|
- $this->_objectSize += $len;
|
|
|
- // TODO: handle current position for writing!
|
|
|
- return $len;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * End of the stream?
|
|
|
- *
|
|
|
- * @return boolean
|
|
|
- */
|
|
|
- public function stream_eof()
|
|
|
- {
|
|
|
- if (!$this->_objectName) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- return ($this->_position >= $this->_objectSize);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * What is the current read/write position of the stream
|
|
|
- *
|
|
|
- * @return integer
|
|
|
- */
|
|
|
- public function stream_tell()
|
|
|
- {
|
|
|
- return $this->_position;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Update the read/write position of the stream
|
|
|
- *
|
|
|
- * @param integer $offset
|
|
|
- * @param integer $whence
|
|
|
- * @return boolean
|
|
|
- */
|
|
|
- public function stream_seek($offset, $whence)
|
|
|
- {
|
|
|
- if (!$this->_objectName) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- switch ($whence) {
|
|
|
- case SEEK_CUR:
|
|
|
- // Set position to current location plus $offset
|
|
|
- $new_pos = $this->_position + $offset;
|
|
|
- break;
|
|
|
- case SEEK_END:
|
|
|
- // Set position to end-of-file plus $offset
|
|
|
- $new_pos = $this->_objectSize + $offset;
|
|
|
- break;
|
|
|
- case SEEK_SET:
|
|
|
- default:
|
|
|
- // Set position equal to $offset
|
|
|
- $new_pos = $offset;
|
|
|
- break;
|
|
|
- }
|
|
|
- $ret = ($new_pos >= 0 && $new_pos <= $this->_objectSize);
|
|
|
- if ($ret) {
|
|
|
- $this->_position = $new_pos;
|
|
|
- }
|
|
|
- return $ret;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Flush current cached stream data to storage
|
|
|
- *
|
|
|
- * @return boolean
|
|
|
- */
|
|
|
- public function stream_flush()
|
|
|
- {
|
|
|
- // If the stream wasn't opened for writing, just return false
|
|
|
- if (!$this->_writeBuffer) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- $ret = $this->_s3->putObject($this->_objectName, $this->_objectBuffer);
|
|
|
-
|
|
|
- $this->_objectBuffer = null;
|
|
|
-
|
|
|
- return $ret;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Returns data array of stream variables
|
|
|
- *
|
|
|
- * @return array
|
|
|
- */
|
|
|
- public function stream_stat()
|
|
|
- {
|
|
|
- if (!$this->_objectName) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- $stat = array();
|
|
|
- $stat['dev'] = 0;
|
|
|
- $stat['ino'] = 0;
|
|
|
- $stat['mode'] = 0;
|
|
|
- $stat['nlink'] = 0;
|
|
|
- $stat['uid'] = 0;
|
|
|
- $stat['gid'] = 0;
|
|
|
- $stat['rdev'] = 0;
|
|
|
- $stat['size'] = 0;
|
|
|
- $stat['atime'] = 0;
|
|
|
- $stat['mtime'] = 0;
|
|
|
- $stat['ctime'] = 0;
|
|
|
- $stat['blksize'] = 0;
|
|
|
- $stat['blocks'] = 0;
|
|
|
-
|
|
|
- $info = $this->_s3->getInfo($this->_objectName);
|
|
|
- if (!empty($info)) {
|
|
|
- $stat['size'] = $info['size'];
|
|
|
- $stat['atime'] = time();
|
|
|
- $stat['mtime'] = $info['mtime'];
|
|
|
- }
|
|
|
-
|
|
|
- return $stat;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Attempt to delete the item
|
|
|
- *
|
|
|
- * @param string $path
|
|
|
- * @return boolean
|
|
|
- */
|
|
|
- public function unlink($path)
|
|
|
- {
|
|
|
- return $this->_getS3Client($path)->removeObject($this->_getNamePart($path));
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Attempt to rename the item
|
|
|
- *
|
|
|
- * @param string $path_from
|
|
|
- * @param string $path_to
|
|
|
- * @return boolean False
|
|
|
- */
|
|
|
- public function rename($path_from, $path_to)
|
|
|
- {
|
|
|
- // TODO: Renaming isn't supported, always return false
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Create a new directory
|
|
|
- *
|
|
|
- * @param string $path
|
|
|
- * @param integer $mode
|
|
|
- * @param integer $options
|
|
|
- * @return boolean
|
|
|
- */
|
|
|
- public function mkdir($path, $mode, $options)
|
|
|
- {
|
|
|
- return $this->_getS3Client($path)->createBucket(parse_url($path, PHP_URL_HOST));
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Remove a directory
|
|
|
- *
|
|
|
- * @param string $path
|
|
|
- * @param integer $options
|
|
|
- * @return boolean
|
|
|
- */
|
|
|
- public function rmdir($path, $options)
|
|
|
- {
|
|
|
- return $this->_getS3Client($path)->removeBucket(parse_url($path, PHP_URL_HOST));
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Attempt to open a directory
|
|
|
- *
|
|
|
- * @param string $path
|
|
|
- * @param integer $options
|
|
|
- * @return boolean
|
|
|
- */
|
|
|
- public function dir_opendir($path, $options)
|
|
|
- {
|
|
|
-
|
|
|
- if (preg_match('@^([a-z0-9+.]|-)+://$@', $path)) {
|
|
|
- $this->_bucketList = $this->_getS3Client($path)->getBuckets();
|
|
|
- }
|
|
|
- else {
|
|
|
- $url = parse_url($path);
|
|
|
- $this->_bucketList = $this->_getS3Client($path)->getObjectsByBucket($url["host"]);
|
|
|
- }
|
|
|
-
|
|
|
- return ($this->_bucketList !== false);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Return array of URL variables
|
|
|
- *
|
|
|
- * @param string $path
|
|
|
- * @param integer $flags
|
|
|
- * @return array
|
|
|
- */
|
|
|
- public function url_stat($path, $flags)
|
|
|
- {
|
|
|
- $stat = array();
|
|
|
- $stat['dev'] = 0;
|
|
|
- $stat['ino'] = 0;
|
|
|
- $stat['mode'] = 0;
|
|
|
- $stat['nlink'] = 0;
|
|
|
- $stat['uid'] = 0;
|
|
|
- $stat['gid'] = 0;
|
|
|
- $stat['rdev'] = 0;
|
|
|
- $stat['size'] = 0;
|
|
|
- $stat['atime'] = 0;
|
|
|
- $stat['mtime'] = 0;
|
|
|
- $stat['ctime'] = 0;
|
|
|
- $stat['blksize'] = 0;
|
|
|
- $stat['blocks'] = 0;
|
|
|
-
|
|
|
- $info = $this->_getS3Client($path)->getInfo($this->_getNamePart($path));
|
|
|
- if (!empty($info)) {
|
|
|
- $stat['size'] = $info['size'];
|
|
|
- $stat['atime'] = time();
|
|
|
- $stat['mtime'] = $info['mtime'];
|
|
|
- }
|
|
|
-
|
|
|
- return $stat;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Return the next filename in the directory
|
|
|
- *
|
|
|
- * @return string
|
|
|
- */
|
|
|
- public function dir_readdir()
|
|
|
- {
|
|
|
- $object = current($this->_bucketList);
|
|
|
- if ($object !== false) {
|
|
|
- next($this->_bucketList);
|
|
|
- }
|
|
|
- return $object;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Reset the directory pointer
|
|
|
- *
|
|
|
- * @return boolean True
|
|
|
- */
|
|
|
- public function dir_rewinddir()
|
|
|
- {
|
|
|
- reset($this->_bucketList);
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Close a directory
|
|
|
- *
|
|
|
- * @return boolean True
|
|
|
- */
|
|
|
- public function dir_closedir()
|
|
|
- {
|
|
|
- $this->_bucketList = array();
|
|
|
- return true;
|
|
|
- }
|
|
|
-}
|
|
|
+<?php
|
|
|
+/**
|
|
|
+ * Zend Framework
|
|
|
+ *
|
|
|
+ * LICENSE
|
|
|
+ *
|
|
|
+ * This source file is subject to the new BSD license that is bundled
|
|
|
+ * with this package in the file LICENSE.txt.
|
|
|
+ * It is also available through the world-wide-web at this URL:
|
|
|
+ * http://framework.zend.com/license/new-bsd
|
|
|
+ * If you did not receive a copy of the license and are unable to
|
|
|
+ * obtain it through the world-wide-web, please send an email
|
|
|
+ * to license@zend.com so we can send you a copy immediately.
|
|
|
+ *
|
|
|
+ * @category Zend
|
|
|
+ * @package Zend_Service
|
|
|
+ * @subpackage Amazon_S3
|
|
|
+ * @copyright Copyright (c) 2005-2008, Zend Technologies USA Inc. (http://www.zend.com)
|
|
|
+ * @license http://framework.zend.com/license/new-bsd New BSD License
|
|
|
+ * @version $Id: S3.php 9786 2008-06-24 23:50:25Z jplock $
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @see Zend_Service_Amazon_S3
|
|
|
+ */
|
|
|
+require_once 'Zend/Service/Amazon/S3.php';
|
|
|
+
|
|
|
+/**
|
|
|
+ * Amazon S3 PHP stream wrapper
|
|
|
+ *
|
|
|
+ * @category Zend
|
|
|
+ * @package Zend_Service
|
|
|
+ * @subpackage Amazon_S3
|
|
|
+ * @copyright Copyright (c) 2005-2008, Zend Technologies USA Inc. (http://www.zend.com)
|
|
|
+ * @license http://framework.zend.com/license/new-bsd New BSD License
|
|
|
+ */
|
|
|
+class Zend_Service_Amazon_S3_Stream
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * @var boolean Write the buffer on fflush()?
|
|
|
+ */
|
|
|
+ private $_writeBuffer = false;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @var integer Current read/write position
|
|
|
+ */
|
|
|
+ private $_position = 0;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @var integer Total size of the object as returned by S3 (Content-length)
|
|
|
+ */
|
|
|
+ private $_objectSize = 0;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @var string File name to interact with
|
|
|
+ */
|
|
|
+ private $_objectName = null;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @var string Current read/write buffer
|
|
|
+ */
|
|
|
+ private $_objectBuffer = null;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @var array Available buckets
|
|
|
+ */
|
|
|
+ private $_bucketList = array();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @var Zend_Service_Amazon_S3
|
|
|
+ */
|
|
|
+ private $_s3 = null;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Retrieve client for this stream type
|
|
|
+ *
|
|
|
+ * @param string $path
|
|
|
+ * @return Zend_Service_Amazon_S3
|
|
|
+ */
|
|
|
+ protected function _getS3Client($path)
|
|
|
+ {
|
|
|
+ if ($this->_s3 === null) {
|
|
|
+ $url = explode(':', $path);
|
|
|
+
|
|
|
+ if (!$url) {
|
|
|
+ /**
|
|
|
+ * @see Zend_Service_Amazon_S3_Exception
|
|
|
+ */
|
|
|
+ require_once 'Zend/Service/Amazon/S3/Exception.php';
|
|
|
+ throw new Zend_Service_Amazon_S3_Exception("Unable to parse URL $path");
|
|
|
+ }
|
|
|
+
|
|
|
+ $this->_s3 = Zend_Service_Amazon_S3::getWrapperClient($url[0]);
|
|
|
+ if (!$this->_s3) {
|
|
|
+ /**
|
|
|
+ * @see Zend_Service_Amazon_S3_Exception
|
|
|
+ */
|
|
|
+ require_once 'Zend/Service/Amazon/S3/Exception.php';
|
|
|
+ throw new Zend_Service_Amazon_S3_Exception("Unknown client for wrapper {$url[0]}");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return $this->_s3;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Extract object name from URL
|
|
|
+ *
|
|
|
+ * @param string $path
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ protected function _getNamePart($path)
|
|
|
+ {
|
|
|
+ $url = parse_url($path);
|
|
|
+ if ($url['host']) {
|
|
|
+ return $url['path'] ? $url['host'].$url['path'] : $url['host'];
|
|
|
+ }
|
|
|
+
|
|
|
+ return '';
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * Open the stream
|
|
|
+ *
|
|
|
+ * @param string $path
|
|
|
+ * @param string $mode
|
|
|
+ * @param integer $options
|
|
|
+ * @param string $opened_path
|
|
|
+ * @return boolean
|
|
|
+ */
|
|
|
+ public function stream_open($path, $mode, $options, $opened_path)
|
|
|
+ {
|
|
|
+ $name = $this->_getNamePart($path);
|
|
|
+ // If we open the file for writing, just return true. Create the object
|
|
|
+ // on fflush call
|
|
|
+ if (strpbrk($mode, 'wax')) {
|
|
|
+ $this->_objectName = $name;
|
|
|
+ $this->_objectBuffer = null;
|
|
|
+ $this->_objectSize = 0;
|
|
|
+ $this->_position = 0;
|
|
|
+ $this->_writeBuffer = true;
|
|
|
+ $this->_getS3Client($path);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ // Otherwise, just see if the file exists or not
|
|
|
+ $info = $this->_getS3Client($path)->getInfo($name);
|
|
|
+ if ($info) {
|
|
|
+ $this->_objectName = $name;
|
|
|
+ $this->_objectBuffer = null;
|
|
|
+ $this->_objectSize = $info['size'];
|
|
|
+ $this->_position = 0;
|
|
|
+ $this->_writeBuffer = false;
|
|
|
+ $this->_getS3Client($path);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Close the stream
|
|
|
+ *
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function stream_close()
|
|
|
+ {
|
|
|
+ $this->_objectName = null;
|
|
|
+ $this->_objectBuffer = null;
|
|
|
+ $this->_objectSize = 0;
|
|
|
+ $this->_position = 0;
|
|
|
+ $this->_writeBuffer = false;
|
|
|
+ unset($this->_s3);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Read from the stream
|
|
|
+ *
|
|
|
+ * @param integer $count
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ public function stream_read($count)
|
|
|
+ {
|
|
|
+ if (!$this->_objectName) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ $range_start = $this->_position;
|
|
|
+ $range_end = $this->_position+$count;
|
|
|
+
|
|
|
+ // Only fetch more data from S3 if we haven't fetched any data yet (postion=0)
|
|
|
+ // OR, the range end position is greater than the size of the current object
|
|
|
+ // buffer AND if the range end position is less than or equal to the object's
|
|
|
+ // size returned by S3
|
|
|
+ if (($this->_position == 0) || (($range_end > strlen($this->_objectBuffer)) && ($range_end <= $this->_objectSize))) {
|
|
|
+
|
|
|
+ $headers = array(
|
|
|
+ 'Range' => "$range_start-$range_end"
|
|
|
+ );
|
|
|
+
|
|
|
+ $response = $this->_s3->_makeRequest('GET', $this->_objectName, null, $headers);
|
|
|
+
|
|
|
+ if ($response->getStatus() == 200) {
|
|
|
+ $this->_objectBuffer .= $response->getBody();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $data = substr($this->_objectBuffer, $this->_position, $count);
|
|
|
+ $this->_position += strlen($data);
|
|
|
+ return $data;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Write to the stream
|
|
|
+ *
|
|
|
+ * @param string $data
|
|
|
+ * @return integer
|
|
|
+ */
|
|
|
+ public function stream_write($data)
|
|
|
+ {
|
|
|
+ if (!$this->_objectName) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ $len = strlen($data);
|
|
|
+ $this->_objectBuffer .= $data;
|
|
|
+ $this->_objectSize += $len;
|
|
|
+ // TODO: handle current position for writing!
|
|
|
+ return $len;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * End of the stream?
|
|
|
+ *
|
|
|
+ * @return boolean
|
|
|
+ */
|
|
|
+ public function stream_eof()
|
|
|
+ {
|
|
|
+ if (!$this->_objectName) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ($this->_position >= $this->_objectSize);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * What is the current read/write position of the stream
|
|
|
+ *
|
|
|
+ * @return integer
|
|
|
+ */
|
|
|
+ public function stream_tell()
|
|
|
+ {
|
|
|
+ return $this->_position;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Update the read/write position of the stream
|
|
|
+ *
|
|
|
+ * @param integer $offset
|
|
|
+ * @param integer $whence
|
|
|
+ * @return boolean
|
|
|
+ */
|
|
|
+ public function stream_seek($offset, $whence)
|
|
|
+ {
|
|
|
+ if (!$this->_objectName) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch ($whence) {
|
|
|
+ case SEEK_CUR:
|
|
|
+ // Set position to current location plus $offset
|
|
|
+ $new_pos = $this->_position + $offset;
|
|
|
+ break;
|
|
|
+ case SEEK_END:
|
|
|
+ // Set position to end-of-file plus $offset
|
|
|
+ $new_pos = $this->_objectSize + $offset;
|
|
|
+ break;
|
|
|
+ case SEEK_SET:
|
|
|
+ default:
|
|
|
+ // Set position equal to $offset
|
|
|
+ $new_pos = $offset;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ $ret = ($new_pos >= 0 && $new_pos <= $this->_objectSize);
|
|
|
+ if ($ret) {
|
|
|
+ $this->_position = $new_pos;
|
|
|
+ }
|
|
|
+ return $ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Flush current cached stream data to storage
|
|
|
+ *
|
|
|
+ * @return boolean
|
|
|
+ */
|
|
|
+ public function stream_flush()
|
|
|
+ {
|
|
|
+ // If the stream wasn't opened for writing, just return false
|
|
|
+ if (!$this->_writeBuffer) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ $ret = $this->_s3->putObject($this->_objectName, $this->_objectBuffer);
|
|
|
+
|
|
|
+ $this->_objectBuffer = null;
|
|
|
+
|
|
|
+ return $ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Returns data array of stream variables
|
|
|
+ *
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ public function stream_stat()
|
|
|
+ {
|
|
|
+ if (!$this->_objectName) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ $stat = array();
|
|
|
+ $stat['dev'] = 0;
|
|
|
+ $stat['ino'] = 0;
|
|
|
+ $stat['mode'] = 0;
|
|
|
+ $stat['nlink'] = 0;
|
|
|
+ $stat['uid'] = 0;
|
|
|
+ $stat['gid'] = 0;
|
|
|
+ $stat['rdev'] = 0;
|
|
|
+ $stat['size'] = 0;
|
|
|
+ $stat['atime'] = 0;
|
|
|
+ $stat['mtime'] = 0;
|
|
|
+ $stat['ctime'] = 0;
|
|
|
+ $stat['blksize'] = 0;
|
|
|
+ $stat['blocks'] = 0;
|
|
|
+
|
|
|
+ $info = $this->_s3->getInfo($this->_objectName);
|
|
|
+ if (!empty($info)) {
|
|
|
+ $stat['size'] = $info['size'];
|
|
|
+ $stat['atime'] = time();
|
|
|
+ $stat['mtime'] = $info['mtime'];
|
|
|
+ }
|
|
|
+
|
|
|
+ return $stat;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Attempt to delete the item
|
|
|
+ *
|
|
|
+ * @param string $path
|
|
|
+ * @return boolean
|
|
|
+ */
|
|
|
+ public function unlink($path)
|
|
|
+ {
|
|
|
+ return $this->_getS3Client($path)->removeObject($this->_getNamePart($path));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Attempt to rename the item
|
|
|
+ *
|
|
|
+ * @param string $path_from
|
|
|
+ * @param string $path_to
|
|
|
+ * @return boolean False
|
|
|
+ */
|
|
|
+ public function rename($path_from, $path_to)
|
|
|
+ {
|
|
|
+ // TODO: Renaming isn't supported, always return false
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Create a new directory
|
|
|
+ *
|
|
|
+ * @param string $path
|
|
|
+ * @param integer $mode
|
|
|
+ * @param integer $options
|
|
|
+ * @return boolean
|
|
|
+ */
|
|
|
+ public function mkdir($path, $mode, $options)
|
|
|
+ {
|
|
|
+ return $this->_getS3Client($path)->createBucket(parse_url($path, PHP_URL_HOST));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Remove a directory
|
|
|
+ *
|
|
|
+ * @param string $path
|
|
|
+ * @param integer $options
|
|
|
+ * @return boolean
|
|
|
+ */
|
|
|
+ public function rmdir($path, $options)
|
|
|
+ {
|
|
|
+ return $this->_getS3Client($path)->removeBucket(parse_url($path, PHP_URL_HOST));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Attempt to open a directory
|
|
|
+ *
|
|
|
+ * @param string $path
|
|
|
+ * @param integer $options
|
|
|
+ * @return boolean
|
|
|
+ */
|
|
|
+ public function dir_opendir($path, $options)
|
|
|
+ {
|
|
|
+
|
|
|
+ if (preg_match('@^([a-z0-9+.]|-)+://$@', $path)) {
|
|
|
+ $this->_bucketList = $this->_getS3Client($path)->getBuckets();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $url = parse_url($path);
|
|
|
+ $this->_bucketList = $this->_getS3Client($path)->getObjectsByBucket($url["host"]);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ($this->_bucketList !== false);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return array of URL variables
|
|
|
+ *
|
|
|
+ * @param string $path
|
|
|
+ * @param integer $flags
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ public function url_stat($path, $flags)
|
|
|
+ {
|
|
|
+ $stat = array();
|
|
|
+ $stat['dev'] = 0;
|
|
|
+ $stat['ino'] = 0;
|
|
|
+ $stat['mode'] = 0;
|
|
|
+ $stat['nlink'] = 0;
|
|
|
+ $stat['uid'] = 0;
|
|
|
+ $stat['gid'] = 0;
|
|
|
+ $stat['rdev'] = 0;
|
|
|
+ $stat['size'] = 0;
|
|
|
+ $stat['atime'] = 0;
|
|
|
+ $stat['mtime'] = 0;
|
|
|
+ $stat['ctime'] = 0;
|
|
|
+ $stat['blksize'] = 0;
|
|
|
+ $stat['blocks'] = 0;
|
|
|
+
|
|
|
+ $info = $this->_getS3Client($path)->getInfo($this->_getNamePart($path));
|
|
|
+ if (!empty($info)) {
|
|
|
+ $stat['size'] = $info['size'];
|
|
|
+ $stat['atime'] = time();
|
|
|
+ $stat['mtime'] = $info['mtime'];
|
|
|
+ }
|
|
|
+
|
|
|
+ return $stat;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Return the next filename in the directory
|
|
|
+ *
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ public function dir_readdir()
|
|
|
+ {
|
|
|
+ $object = current($this->_bucketList);
|
|
|
+ if ($object !== false) {
|
|
|
+ next($this->_bucketList);
|
|
|
+ }
|
|
|
+ return $object;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Reset the directory pointer
|
|
|
+ *
|
|
|
+ * @return boolean True
|
|
|
+ */
|
|
|
+ public function dir_rewinddir()
|
|
|
+ {
|
|
|
+ reset($this->_bucketList);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Close a directory
|
|
|
+ *
|
|
|
+ * @return boolean True
|
|
|
+ */
|
|
|
+ public function dir_closedir()
|
|
|
+ {
|
|
|
+ $this->_bucketList = array();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+}
|