/apps/files_external/lib/amazons3.php
PHP | 245 lines | 193 code | 23 blank | 29 comment | 59 complexity | 5258a0e7b9b084f38bdf0e0d9fb59dbe MD5 | raw file
Possible License(s): AGPL-3.0, AGPL-1.0, MPL-2.0-no-copyleft-exception
- <?php
- /**
- * ownCloud
- *
- * @author Michael Gapczynski
- * @copyright 2012 Michael Gapczynski mtgap@owncloud.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU Affero General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
- require_once 'aws-sdk/sdk.class.php';
- class OC_Filestorage_AmazonS3 extends OC_Filestorage_Common {
- private $s3;
- private $bucket;
- private $objects = array();
- private static $tempFiles = array();
- // TODO options: storage class, encryption server side, encrypt before upload?
- public function __construct($params) {
- $this->s3 = new AmazonS3(array('key' => $params['key'], 'secret' => $params['secret']));
- $this->bucket = $params['bucket'];
- }
- private function getObject($path) {
- if (array_key_exists($path, $this->objects)) {
- return $this->objects[$path];
- } else {
- $response = $this->s3->get_object_metadata($this->bucket, $path);
- if ($response) {
- $this->objects[$path] = $response;
- return $response;
- // This object could be a folder, a '/' must be at the end of the path
- } else if (substr($path, -1) != '/') {
- $response = $this->s3->get_object_metadata($this->bucket, $path.'/');
- if ($response) {
- $this->objects[$path] = $response;
- return $response;
- }
- }
- }
- return false;
- }
- public function mkdir($path) {
- // Folders in Amazon S3 are 0 byte objects with a '/' at the end of the name
- if (substr($path, -1) != '/') {
- $path .= '/';
- }
- $response = $this->s3->create_object($this->bucket, $path, array('body' => ''));
- return $response->isOK();
- }
- public function rmdir($path) {
- if (substr($path, -1) != '/') {
- $path .= '/';
- }
- return $this->unlink($path);
- }
- public function opendir($path) {
- if ($path == '' || $path == '/') {
- // Use the '/' delimiter to only fetch objects inside the folder
- $opt = array('delimiter' => '/');
- } else {
- if (substr($path, -1) != '/') {
- $path .= '/';
- }
- $opt = array('delimiter' => '/', 'prefix' => $path);
- }
- $response = $this->s3->list_objects($this->bucket, $opt);
- if ($response->isOK()) {
- $files = array();
- foreach ($response->body->Contents as $object) {
- // The folder being opened also shows up in the list of objects, don't add it to the files
- if ($object->Key != $path) {
- $files[] = basename($object->Key);
- }
- }
- // Sub folders show up as CommonPrefixes
- foreach ($response->body->CommonPrefixes as $object) {
- $files[] = basename($object->Prefix);
- }
- OC_FakeDirStream::$dirs['amazons3'.$path] = $files;
- return opendir('fakedir://amazons3'.$path);
- }
- return false;
- }
- public function stat($path) {
- if ($path == '' || $path == '/') {
- $stat['size'] = $this->s3->get_bucket_filesize($this->bucket);
- $stat['atime'] = time();
- $stat['mtime'] = $stat['atime'];
- $stat['ctime'] = $stat['atime'];
- } else {
- $object = $this->getObject($path);
- if ($object) {
- $stat['size'] = $object['Size'];
- $stat['atime'] = time();
- $stat['mtime'] = strtotime($object['LastModified']);
- $stat['ctime'] = $stat['mtime'];
- }
- }
- if (isset($stat)) {
- return $stat;
- }
- return false;
- }
- public function filetype($path) {
- if ($path == '' || $path == '/') {
- return 'dir';
- } else {
- $object = $this->getObject($path);
- if ($object) {
- // Amazon S3 doesn't have typical folders, this is an alternative method to detect a folder
- if (substr($object['Key'], -1) == '/' && $object['Size'] == 0) {
- return 'dir';
- } else {
- return 'file';
- }
- }
- }
- return false;
- }
- public function isReadable($path) {
- // TODO Check acl and determine who grantee is
- return true;
- }
- public function isUpdatable($path) {
- // TODO Check acl and determine who grantee is
- return true;
- }
- public function file_exists($path) {
- if ($this->filetype($path) == 'dir' && substr($path, -1) != '/') {
- $path .= '/';
- }
- return $this->s3->if_object_exists($this->bucket, $path);
- }
- public function unlink($path) {
- $response = $this->s3->delete_object($this->bucket, $path);
- return $response->isOK();
- }
- public function fopen($path, $mode) {
- switch ($mode) {
- case 'r':
- case 'rb':
- $tmpFile = OC_Helper::tmpFile();
- $handle = fopen($tmpFile, 'w');
- $response = $this->s3->get_object($this->bucket, $path, array('fileDownload' => $handle));
- if ($response->isOK()) {
- return fopen($tmpFile, 'r');
- }
- break;
- case 'w':
- case 'wb':
- case 'a':
- case 'ab':
- case 'r+':
- case 'w+':
- case 'wb+':
- case 'a+':
- case 'x':
- case 'x+':
- case 'c':
- case 'c+':
- if (strrpos($path, '.') !== false) {
- $ext = substr($path, strrpos($path, '.'));
- } else {
- $ext = '';
- }
- $tmpFile = OC_Helper::tmpFile($ext);
- OC_CloseStreamWrapper::$callBacks[$tmpFile] = array($this, 'writeBack');
- if ($this->file_exists($path)) {
- $source = $this->fopen($path, 'r');
- file_put_contents($tmpFile, $source);
- }
- self::$tempFiles[$tmpFile] = $path;
- return fopen('close://'.$tmpFile, $mode);
- }
- return false;
- }
- public function writeBack($tmpFile) {
- if (isset(self::$tempFiles[$tmpFile])) {
- $handle = fopen($tmpFile, 'r');
- $response = $this->s3->create_object($this->bucket,
- self::$tempFiles[$tmpFile],
- array('fileUpload' => $handle));
- if ($response->isOK()) {
- unlink($tmpFile);
- }
- }
- }
- public function getMimeType($path) {
- if ($this->filetype($path) == 'dir') {
- return 'httpd/unix-directory';
- } else {
- $object = $this->getObject($path);
- if ($object) {
- return $object['ContentType'];
- }
- }
- return false;
- }
- public function free_space($path) {
- // Infinite?
- return false;
- }
- public function touch($path, $mtime = null) {
- if (is_null($mtime)) {
- $mtime = time();
- }
- if ($this->filetype($path) == 'dir' && substr($path, -1) != '/') {
- $path .= '/';
- }
- $response = $this->s3->update_object($this->bucket, $path, array('meta' => array('LastModified' => $mtime)));
- return $response->isOK();
- }
- }