123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732 |
- <?php
- /**
- * @file
- *
- * elFinder driver for Amazon S3 (SOAP) filesystem.
- *
- * @author Dmitry (dio) Levashov,
- * @author Alexey Sukhotin
- * */
- class elFinderVolumeS3 extends elFinderVolumeDriver {
- protected $driverId = 's3s';
-
- protected $s3;
-
- public function __construct() {
- $opts = array(
- 'accesskey' => '',
- 'secretkey' => '',
- 'bucket' => '',
- 'tmpPath' => '',
- );
- $this->options = array_merge($this->options, $opts);
- $this->options['mimeDetect'] = 'internal';
- }
-
-
- protected function init() {
- if (!$this->options['accesskey']
- || !$this->options['secretkey']
- || !$this->options['bucket']) {
- return $this->setError('Required options undefined.');
- }
-
- $this->s3 = new S3SoapClient($this->options['accesskey'], $this->options['secretkey']);
-
- $this->root = $this->options['path'];
-
- $this->rootName = 's3';
-
- return true;
- }
-
- protected function configure() {
- parent::configure();
- if (!empty($this->options['tmpPath'])) {
- if ((is_dir($this->options['tmpPath']) || @mkdir($this->options['tmpPath'])) && is_writable($this->options['tmpPath'])) {
- $this->tmpPath = $this->options['tmpPath'];
- }
- }
- $this->mimeDetect = 'internal';
- }
-
- /**
- * Return parent directory path
- *
- * @param string $path file path
- * @return string
- * @author Dmitry (dio) Levashov
- **/
- protected function _dirname($path) {
-
- $newpath = preg_replace("/\/$/", "", $path);
- $dn = substr($path, 0, strrpos($newpath, '/')) ;
-
- if (substr($dn, 0, 1) != '/') {
- $dn = "/$dn";
- }
-
- return $dn;
- }
- /**
- * Return file name
- *
- * @param string $path file path
- * @return string
- * @author Dmitry (dio) Levashov
- **/
- protected function _basename($path) {
- return basename($path);
- }
-
-
- /**
- * Join dir name and file name and return full path.
- * Some drivers (db) use int as path - so we give to concat path to driver itself
- *
- * @param string $dir dir path
- * @param string $name file name
- * @return string
- * @author Dmitry (dio) Levashov
- **/
- protected function _joinPath($dir, $name) {
- return $dir.DIRECTORY_SEPARATOR.$name;
- }
-
- /**
- * Return normalized path, this works the same as os.path.normpath() in Python
- *
- * @param string $path path
- * @return string
- * @author Troex Nevelin
- **/
- protected function _normpath($path) {
- $tmp = preg_replace("/^\//", "", $path);
- $tmp = preg_replace("/\/\//", "/", $tmp);
- $tmp = preg_replace("/\/$/", "", $tmp);
- return $tmp;
- }
- /**
- * Return file path related to root dir
- *
- * @param string $path file path
- * @return string
- * @author Dmitry (dio) Levashov
- **/
- protected function _relpath($path) {
-
-
- $newpath = $path;
-
-
- if (substr($path, 0, 1) != '/') {
- $newpath = "/$newpath";
- }
-
- $newpath = preg_replace("/\/$/", "", $newpath);
-
- $ret = ($newpath == $this->root) ? '' : substr($newpath, strlen($this->root)+1);
-
- return $ret;
- }
-
- /**
- * Convert path related to root dir into real path
- *
- * @param string $path file path
- * @return string
- * @author Dmitry (dio) Levashov
- **/
- protected function _abspath($path) {
- return $path == $this->separator ? $this->root : $this->root.$this->separator.$path;
- }
-
- /**
- * Return fake path started from root dir
- *
- * @param string $path file path
- * @return string
- * @author Dmitry (dio) Levashov
- **/
- protected function _path($path) {
- return $this->rootName.($path == $this->root ? '' : $this->separator.$this->_relpath($path));
- }
-
- /**
- * Return true if $path is children of $parent
- *
- * @param string $path path to check
- * @param string $parent parent path
- * @return bool
- * @author Dmitry (dio) Levashov
- **/
- protected function _inpath($path, $parent) {
- return $path == $parent || strpos($path, $parent.'/') === 0;
- }
-
- /**
- * Converting array of objects with name and value properties to
- * array[key] = value
- * @param array $metadata source array
- * @return array
- * @author Alexey Sukhotin
- **/
- protected function metaobj2array($metadata) {
- $arr = array();
-
- if (is_array($metadata)) {
- foreach ($metadata as $meta) {
- $arr[$meta->Name] = $meta->Value;
- }
- } else {
- $arr[$metadata->Name] = $metadata->Value;
- }
- return $arr;
- }
-
- /**
- * Return stat for given path.
- * Stat contains following fields:
- * - (int) size file size in b. required
- * - (int) ts file modification time in unix time. required
- * - (string) mime mimetype. required for folders, others - optionally
- * - (bool) read read permissions. required
- * - (bool) write write permissions. required
- * - (bool) locked is object locked. optionally
- * - (bool) hidden is object hidden. optionally
- * - (string) alias for symlinks - link target path relative to root path. optionally
- * - (string) target for symlinks - link target path. optionally
- *
- * If file does not exists - returns empty array or false.
- *
- * @param string $path file path
- * @return array|false
- * @author Dmitry (dio) Levashov,
- * @author Alexey Sukhotin
- **/
- protected function _stat($path) {
-
- $stat = array(
- 'size' => 0,
- 'ts' => time(),
- 'read' => true,
- 'write' => true,
- 'locked' => false,
- 'hidden' => false,
- 'mime' => 'directory',
- );
-
-
- if ($this->root == $path) {
- return $stat;
- }
- $np = $this->_normpath($path);
-
- try {
- $obj = $this->s3->GetObject(array('Bucket' => $this->options['bucket'], 'Key' => $np , 'GetMetadata' => true, 'InlineData' => false, 'GetData' => false));
- } catch (Exception $e) {
-
- }
-
- if (!isset($obj) || ($obj->GetObjectResponse->Status->Code != 200)) {
- $np .= '/';
- try {
- $obj = $this->s3->GetObject(array('Bucket' => $this->options['bucket'], 'Key' => $np , 'GetMetadata' => true, 'InlineData' => false, 'GetData' => false));
- } catch (Exception $e) {
-
- }
- }
-
- if (!(isset($obj) && $obj->GetObjectResponse->Status->Code == 200)) {
- return array();
- }
-
- $mime = '';
-
- $metadata = $this->metaobj2array($obj->GetObjectResponse->Metadata);
-
- $mime = $metadata['Content-Type'];
-
- if (!empty($mime)) {
- $stat['mime'] = ($mime == 'binary/octet-stream') ? 'directory' : $mime;
- }
-
- if (isset($obj->GetObjectResponse->LastModified)) {
- $stat['ts'] = strtotime($obj->GetObjectResponse->LastModified);
- }
-
- try {
- $files = $this->s3->ListBucket(array('Bucket' => $this->options['bucket'], 'Prefix' => $np, 'Delimiter' => '/'))->ListBucketResponse->Contents;
- } catch (Exception $e) {
-
- }
-
- if (!is_array($files)) {
- $files = array($files);
- }
-
- foreach ($files as $file) {
- if ($file->Key == $np) {
- $stat['size'] = $file->Size;
- }
- }
- return $stat;
- }
-
-
- /***************** file stat ********************/
-
- /**
- * Return true if path is dir and has at least one childs directory
- *
- * @param string $path dir path
- * @return bool
- * @author Alexey Sukhotin
- **/
- protected function _subdirs($path) {
- $stat = $this->_stat($path);
-
- if ($stat['mime'] == 'directory') {
- $files = $this->_scandir($path);
- foreach ($files as $file) {
- $fstat = $this->_stat($file);
- if ($fstat['mime'] == 'directory') {
- return true;
- }
- }
-
- }
-
- return false;
- }
-
- /**
- * Return object width and height
- * Ususaly used for images, but can be realize for video etc...
- *
- * @param string $path file path
- * @param string $mime file mime type
- * @return string
- * @author Dmitry (dio) Levashov
- **/
- protected function _dimensions($path, $mime) {
- return false;
- }
-
- /******************** file/dir content *********************/
- /**
- * Return files list in directory
- *
- * @param string $path dir path
- * @return array
- * @author Dmitry (dio) Levashov,
- * @author Alexey Sukhotin
- **/
- protected function _scandir($path) {
-
- $s3path = preg_replace("/^\//", "", $path) . '/';
-
- $files = $this->s3->ListBucket(array('Bucket' => $this->options['bucket'], 'delimiter' => '/', 'Prefix' => $s3path))->ListBucketResponse->Contents;
-
- $finalfiles = array();
-
- foreach ($files as $file) {
- if (preg_match("|^" . $s3path . "[^/]*/?$|", $file->Key)) {
- $fname = preg_replace("/\/$/", "", $file->Key);
- $fname = $file->Key;
-
- if ($fname != preg_replace("/\/$/", "", $s3path)) {
-
- }
-
- $finalfiles[] = $fname;
- }
- }
-
- sort($finalfiles);
- return $finalfiles;
- }
-
- /**
- * Return temporary file path for required file
- *
- * @param string $path file path
- * @return string
- * @author Dmitry (dio) Levashov
- **/
- protected function tmpname($path) {
- return $this->tmpPath.DIRECTORY_SEPARATOR.md5($path);
- }
-
- /**
- * Open file and return file pointer
- *
- * @param string $path file path
- * @param bool $write open file for writing
- * @return resource|false
- * @author Dmitry (dio) Levashov,
- * @author Alexey Sukhotin
- **/
- protected function _fopen($path, $mode="rb") {
-
- $tn = $this->tmpname($path);
-
- $fp = $this->tmbPath
- ? @fopen($tn, 'w+')
- : @tmpfile();
-
- if ($fp) {
- try {
- $obj = $this->s3->GetObject(array('Bucket' => $this->options['bucket'], 'Key' => $this->_normpath($path) , 'GetMetadata' => true, 'InlineData' => true, 'GetData' => true));
- } catch (Exception $e) {
-
- }
-
- $mime = '';
-
- $metadata = $this->metaobj2array($obj->GetObjectResponse->Metadata);
- fwrite($fp, $obj->GetObjectResponse->Data);
- rewind($fp);
- return $fp;
- }
-
- return false;
- }
-
- /**
- * Close opened file
- *
- * @param resource $fp file pointer
- * @param string $path file path
- * @return bool
- * @author Dmitry (dio) Levashov
- **/
- protected function _fclose($fp, $path='') {
- @fclose($fp);
- if ($path) {
- @unlink($this->tmpname($path));
- }
- }
-
- /******************** file/dir manipulations *************************/
-
- /**
- * Create dir and return created dir path or false on failed
- *
- * @param string $path parent dir path
- * @param string $name new directory name
- * @return string|bool
- * @author Dmitry (dio) Levashov,
- * @author Alexey Sukhotin
- **/
- protected function _mkdir($path, $name) {
-
- $newkey = $this->_normpath($path);
- $newkey = preg_replace("/\/$/", "", $newkey);
- $newkey = "$newkey/$name/";
- try {
- $obj = $this->s3->PutObjectInline(array('Bucket' => $this->options['bucket'], 'Key' => $newkey , 'ContentLength' => 0, 'Data' => ''));
- } catch (Exception $e) {
-
- }
-
- if (isset($obj)) {
- return "$path/$name";
- }
-
- return false;
- }
-
- /**
- * Create file and return it's path or false on failed
- *
- * @param string $path parent dir path
- * @param string $name new file name
- * @return string|bool
- * @author Dmitry (dio) Levashov,
- * @author Alexey Sukhotin
- **/
- protected function _mkfile($path, $name) {
- $newkey = $this->_normpath($path);
- $newkey = preg_replace("/\/$/", "", $newkey);
- $newkey = "$newkey/$name";
- try {
- $obj = $this->s3->PutObjectInline(array('Bucket' => $this->options['bucket'], 'Key' => $newkey , 'ContentLength' => 0, 'Data' => '', 'Metadata' => array(array('Name' => 'Content-Type', 'Value' => 'text/plain'))));
- } catch (Exception $e) {
-
- }
-
- if (isset($obj)) {
- return "$path/$name";
- }
-
- return false;
- }
-
- /**
- * Create symlink
- *
- * @param string $source file to link to
- * @param string $targetDir folder to create link in
- * @param string $name symlink name
- * @return bool
- * @author Dmitry (dio) Levashov
- **/
- protected function _symlink($source, $targetDir, $name) {
- return false;
- }
-
- /**
- * Copy file into another file (only inside one volume)
- *
- * @param string $source source file path
- * @param string $target target dir path
- * @param string $name file name
- * @return bool
- * @author Dmitry (dio) Levashov
- **/
- protected function _copy($source, $targetDir, $name) {
- return false;
- }
-
- /**
- * Move file into another parent dir.
- * Return new file path or false.
- *
- * @param string $source source file path
- * @param string $target target dir path
- * @param string $name file name
- * @return string|bool
- * @author Dmitry (dio) Levashov
- **/
- protected function _move($source, $targetDir, $name) {
- return false;
- }
-
- /**
- * Remove file
- *
- * @param string $path file path
- * @return bool
- * @author Dmitry (dio) Levashov
- **/
- protected function _unlink($path) {
-
- $newkey = $this->_normpath($path);
- $newkey = preg_replace("/\/$/", "", $newkey);
- try {
- $obj = $this->s3->DeleteObject(array('Bucket' => $this->options['bucket'], 'Key' => $newkey));
- } catch (Exception $e) {
-
- }
-
- /*$fp = fopen('/tmp/eltest.txt','a+');
-
- fwrite($fp, 'key='.$newkey);*/
-
- if (is_object($obj)) {
- //fwrite($fp, 'obj='.var_export($obj,true));
-
- if (isset($obj->DeleteObjectResponse->Code)) {
- $rc = $obj->DeleteObjectResponse->Code;
-
- if (substr($rc, 0, 1) == '2') {
- return true;
- }
- }
- }
-
- //fclose($fp);
-
- return false;
- }
- /**
- * Remove dir
- *
- * @param string $path dir path
- * @return bool
- * @author Dmitry (dio) Levashov
- **/
- protected function _rmdir($path) {
- return $this->_unlink($path . '/');
- }
- /**
- * Create new file and write into it from file pointer.
- * Return new file path or false on error.
- *
- * @param resource $fp file pointer
- * @param string $dir target dir path
- * @param string $name file name
- * @return bool|string
- * @author Dmitry (dio) Levashov
- **/
- protected function _save($fp, $dir, $name, $mime, $w, $h) {
- return false;
- }
-
- /**
- * Get file contents
- *
- * @param string $path file path
- * @return string|false
- * @author Dmitry (dio) Levashov
- **/
- protected function _getContents($path) {
- return false;
- }
-
- /**
- * Write a string to a file
- *
- * @param string $path file path
- * @param string $content new file content
- * @return bool
- * @author Dmitry (dio) Levashov
- **/
- protected function _filePutContents($path, $content) {
- return false;
- }
- /**
- * Extract files from archive
- *
- * @param string $path file path
- * @param array $arc archiver options
- * @return bool
- * @author Dmitry (dio) Levashov,
- * @author Alexey Sukhotin
- **/
- protected function _extract($path, $arc) {
- return false;
- }
- /**
- * Create archive and return its path
- *
- * @param string $dir target dir
- * @param array $files files names list
- * @param string $name archive name
- * @param array $arc archiver options
- * @return string|bool
- * @author Dmitry (dio) Levashov,
- * @author Alexey Sukhotin
- **/
- protected function _archive($dir, $files, $name, $arc) {
- return false;
- }
- /**
- * Detect available archivers
- *
- * @return void
- * @author Dmitry (dio) Levashov,
- * @author Alexey Sukhotin
- **/
- protected function _checkArchivers() {
-
- }
- }
- /**
- * SoapClient extension with Amazon S3 WSDL and request signing support
- *
- * @author Alexey Sukhotin
- **/
- class S3SoapClient extends SoapClient {
- private $accesskey = '';
- private $secretkey = '';
- public $client = NULL;
-
- public function __construct($key = '', $secret = '') {
- $this->accesskey = $key;
- $this->secretkey = $secret;
- parent::__construct('http://s3.amazonaws.com/doc/2006-03-01/AmazonS3.wsdl');
- }
-
-
- /**
- * Method call wrapper which adding S3 signature and default arguments to all S3 operations
- *
- * @author Alexey Sukhotin
- **/
- public function __call($method, $arguments) {
-
- /* Getting list of S3 web service functions which requires signing */
- $funcs = $this->__getFunctions();
-
- $funcnames = array();
-
- foreach ($funcs as $func) {
- preg_match("/\S+\s+([^\)]+)\(/", $func, $m);
-
- if (isset($m[1])) {
- $funcnames[] = $m[1];
- }
- }
-
- /* adding signature to arguments */
- if (in_array("{$method}", $funcnames)) {
-
- if (is_array($arguments[0])) {
- $arguments[0] = array_merge($arguments[0], $this->sign("{$method}"));
- } else {
- $arguments[0] = $this->sign("{$method}");
- }
- }
-
- /*$fp = fopen('/tmp/s3debug.txt', 'a+');
- fwrite($fp, 'method='."{$method}". ' timestamp='.date('Y-m-d H:i:s').' args='.var_export($arguments,true) . "\n");
- fclose($fp);*/
- return parent::__call($method, $arguments);
- }
- /**
- * Generating signature and timestamp for specified S3 operation
- *
- * @param string $operation S3 operation name
- * @return array
- * @author Alexey Sukhotin
- **/
- protected function sign($operation) {
-
- $params = array(
- 'AWSAccessKeyId' => $this->accesskey,
- 'Timestamp' => gmdate('Y-m-d\TH:i:s.000\Z'),
- );
- $sign_str = 'AmazonS3' . $operation . $params['Timestamp'];
-
- $params['Signature'] = base64_encode(hash_hmac('sha1', $sign_str, $this->secretkey, TRUE));
-
- return $params;
- }
-
- }
- ?>
|