add SWIFT (openstack object storage) storage backend
This commit is contained in:
parent
aceda02887
commit
9a707e10bf
|
@ -0,0 +1,3 @@
|
||||||
|
*.swp
|
||||||
|
*~
|
||||||
|
tests/output.log
|
|
@ -0,0 +1,11 @@
|
||||||
|
Current maintainer:
|
||||||
|
Conrad Weidenkeller <conrad.weidenkeller@rackspace.com>
|
||||||
|
|
||||||
|
Previous maintainer:
|
||||||
|
Eric "EJ" Johnson <ej@racklabs.com>
|
||||||
|
Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk>
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
Paul Kehrer
|
||||||
|
Ben Arwin
|
||||||
|
Jordan Callicoat
|
|
@ -0,0 +1,27 @@
|
||||||
|
Unless otherwise noted, all files are released under the MIT license,
|
||||||
|
exceptions contain licensing information in them.
|
||||||
|
|
||||||
|
Copyright (C) 2008 Rackspace US, Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of Rackspace US, Inc. shall not
|
||||||
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
|
in this Software without prior written authorization from Rackspace US, Inc.
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
1.7.10 Conrad Weidenkeller <conrad.weidenkeller@rackspace.com>
|
||||||
|
* Added Streaming URI Functionality
|
||||||
|
|
||||||
|
1.7.9 Conrad Weidenkeller <conrad.weidenkeller@rackspace.com>
|
||||||
|
* Added Manifest file support for Large Objects
|
||||||
|
|
||||||
|
1.7.8 Conrad Weidenkeller <conrad.weidenkeller@rackspace.com>
|
||||||
|
* Added CDN SSL URI Stuff
|
||||||
|
|
||||||
|
1.7.7 Conrad Weidenkeller <conrad.weidenkeller@rackspace.com>
|
||||||
|
* Added CDN Purge Functionality
|
||||||
|
|
||||||
|
1.7.6 - Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk>
|
||||||
|
* Add Cloud UK Support (conrad.weidenkeller).
|
||||||
|
|
||||||
|
1.7.5 - Conrad Weidenkeller <conrad.weidenkeller@rackspace.com>
|
||||||
|
* Added the ability to list only currently enabled CDN containers
|
||||||
|
* Added curl timeout to CF_Http
|
||||||
|
* Fixed some logic errors in some if statements.
|
||||||
|
|
||||||
|
1.7.4 - Conrad Weidenkeller <conrad.weidenkeller@rackspace.com>
|
||||||
|
* Added Manual SSL support for MacOSX users
|
||||||
|
|
||||||
|
1.7.3 - Conrad Weidenkeller <conrad.weidenkeller@rackspace.com>
|
||||||
|
* Fixed a Small Bug where some users were seeing response bodies for PUTs
|
||||||
|
|
||||||
|
1.7.1 - Conrad Weidenkeller <conrad.weidenkeller@rackspace.com>
|
||||||
|
* Added Support for Auth Token Caching.
|
||||||
|
|
||||||
|
1.7.0 - Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk>
|
||||||
|
* Adjust api auth to rackspacecloud not mosso (mshuler).
|
||||||
|
|
||||||
|
1.6.2 - Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk>
|
||||||
|
* Add a close method to close all the current connection.
|
||||||
|
* Fix when container_name is named 0.
|
||||||
|
|
||||||
|
1.6.1 - Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk>
|
||||||
|
* Fix setting etag on objects.
|
||||||
|
* Fix throwing proper exception when an invalid etag has been set.
|
||||||
|
* Fix throwing proper exception when no content type has been set.
|
||||||
|
|
||||||
|
1.6.0 - Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk>
|
||||||
|
* Add CDN ACL restriction by referrer feature.
|
||||||
|
* Add CDN ACL restriction by User Agent feature.
|
||||||
|
* Add documentation for log_retention method.
|
||||||
|
* Return True if log_retention as succeeded.
|
||||||
|
* Invalid the PHP stats cache before getting filesize.
|
||||||
|
|
||||||
|
1.5.1 - Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk> - 20091020
|
||||||
|
* If the environement variable RACKSPACE_SERVICENET is defined then force to
|
||||||
|
connect via rakcspace servicenet.
|
||||||
|
|
||||||
|
1.5.0 - Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk> - 20091015
|
||||||
|
* Add the option servicenet to connection to use Rackspace service net
|
||||||
|
instead of public network.
|
||||||
|
|
||||||
|
1.4.0 - Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk> - 20090808
|
||||||
|
|
||||||
|
* Add the ability to store the container log.
|
||||||
|
|
||||||
|
1.3.2 - Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk> - 20090606
|
||||||
|
|
||||||
|
* Change the Unit Tests to phpunit.
|
||||||
|
* Automatically set the updated CA bundle when on the windows OS.
|
||||||
|
* More simplification of the mimetype detection and support for PHP 5.3.
|
||||||
|
* Fix documentation information about the ttl for cached object.
|
||||||
|
* Use the hash library to compute MD5 for streams instead of storing the
|
||||||
|
stream in memory.
|
||||||
|
* Fix CF_Connection::get_containers to display the container name properly.
|
||||||
|
|
||||||
|
1.3.1 - <ej@racklabs.com> - 20090325
|
||||||
|
|
||||||
|
* Simplify use of FileInfo, remove packaged MIME/Magic file
|
||||||
|
* Throw Exception if no Content-Type is set
|
||||||
|
* Fix bug with tracking bytes transferred
|
||||||
|
* Support/tested on Windows XP (PHP v5.2.9)
|
||||||
|
|
||||||
|
1.3.0 - <ej@racklabs.com> - 20090311
|
||||||
|
|
||||||
|
* Support for list operations in JSON/XML
|
||||||
|
* Added support for FileInfo automatic Content-Type/MIME detection
|
||||||
|
* Workaround for cURL's old CA bundle with CF_Connection->ssl_use_cabundle()
|
||||||
|
* Supports limit/marker on Account and Container lists
|
||||||
|
* Support "pathname" traversal on Container lists
|
||||||
|
* Helper function on Container to create directory marker Objects
|
||||||
|
* Support for chunked transfer on PUT requests
|
||||||
|
|
||||||
|
1.2.3 - <ej@racklabs.com> - 20081210
|
||||||
|
|
||||||
|
* Improved in-line comments and generated HTML docs
|
||||||
|
* Callbacks for read/write progress on CF_Connection class
|
||||||
|
* Fixed minor bugs
|
||||||
|
* Started this Changelog
|
|
@ -0,0 +1,73 @@
|
||||||
|
;; PHP Cloud Files API
|
||||||
|
;; ========================================================================
|
||||||
|
;; This package contains the PHP API for the Cloud Files storage system.
|
||||||
|
;;
|
||||||
|
;; Please see http://www.rackspacecloud.com/ for more information regarding the
|
||||||
|
;; Cloud Files storage system.
|
||||||
|
;;
|
||||||
|
;; Install
|
||||||
|
;; ------------------------------------------------------------------------
|
||||||
|
;; Extract this archive and make sure the source code files are in your
|
||||||
|
;; PHP "include path". To use the API in your source code, just make
|
||||||
|
;; sure to include/require the "cloudfiles.php" script.
|
||||||
|
;;
|
||||||
|
;; Requirements
|
||||||
|
;; ------------------------------------------------------------------------
|
||||||
|
;; [mandatory] PHP version 5.x (developed against 5.2.0)
|
||||||
|
;; [mandatory] PHP's cURL module
|
||||||
|
;; [mandatory] PHP enabled with mbstring (multi-byte string) support
|
||||||
|
;; [suggested] PEAR FileInfo module (for Content-Type detection)
|
||||||
|
;;
|
||||||
|
;; Examples
|
||||||
|
;; ------------------------------------------------------------------------
|
||||||
|
;; For sample code, please see the tests and API docs.
|
||||||
|
;;
|
||||||
|
;; Docs
|
||||||
|
;; ------------------------------------------------------------------------
|
||||||
|
;; The included documentation was generated directly from the source
|
||||||
|
;; code files using the PHPDocumentor tool.
|
||||||
|
;;
|
||||||
|
;; This README file is actually the PHPDocumentor INI configuration file.
|
||||||
|
;; The following packages were installed via PEAR to generate the HTML
|
||||||
|
;; API documentation.
|
||||||
|
;;
|
||||||
|
;; * PEAR 1.4.11 (stable)
|
||||||
|
;; * PhpDocumentor 1.4.2 (stable)
|
||||||
|
;; * XML_Beautifier 1.2.0 (stable)
|
||||||
|
;; * XML_Parser 1.3.1 (stable)
|
||||||
|
;; * XML_Util 1.2.0 (stable)
|
||||||
|
;;
|
||||||
|
;; To re-generate the API docs, make sure the above software is
|
||||||
|
;; available and run:
|
||||||
|
;; rm -rf docs && phpdoc -c phpdoc.ini
|
||||||
|
;;
|
||||||
|
;; Tests
|
||||||
|
;; ------------------------------------------------------------------------
|
||||||
|
;; The tests are based on phpunit and are run with PHPUnit 3.3.17
|
||||||
|
;; please follow the instructions on :
|
||||||
|
;;
|
||||||
|
;; http://www.phpunit.de/manual/current/en/installation.html
|
||||||
|
;;
|
||||||
|
;; to install PHPUnit. When installed just run the command phpunit on
|
||||||
|
;; the top of the directory and it will launch the tests.
|
||||||
|
;;
|
||||||
|
;; The tests/Comprehensive.php is not enabled by default since
|
||||||
|
;; generating big files. If you want to run it you need to go in the
|
||||||
|
;; tests directory and run with phpunit Comprehensive.php
|
||||||
|
;;
|
||||||
|
;; ========================================================================
|
||||||
|
;; The lines below here are the configuration settings for re-generating
|
||||||
|
;; the PHP API documentation.
|
||||||
|
;;
|
||||||
|
[Parse Data]
|
||||||
|
title = php-cloudfiles
|
||||||
|
hidden = false
|
||||||
|
parseprivate = off
|
||||||
|
javadocdesc = off
|
||||||
|
defaultpackagename = php-cloudfiles
|
||||||
|
defaultcategoryname = php-cloudfiles
|
||||||
|
target = docs
|
||||||
|
directory = .
|
||||||
|
ignore = share/,examples/,tests/,.git/,.gitignore,*.ini,*.swp
|
||||||
|
output=HTML:Smarty:PHP
|
||||||
|
readmeinstallchangelog = README,COPYING,AUTHORS,Changelog
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Custom Exceptions for the CloudFiles API
|
||||||
|
*
|
||||||
|
* Requres PHP 5.x (for Exceptions and OO syntax)
|
||||||
|
*
|
||||||
|
* See COPYING for license information.
|
||||||
|
*
|
||||||
|
* @author Eric "EJ" Johnson <ej@racklabs.com>
|
||||||
|
* @copyright Copyright (c) 2008, Rackspace US, Inc.
|
||||||
|
* @package php-cloudfiles-exceptions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom Exceptions for the CloudFiles API
|
||||||
|
* @package php-cloudfiles-exceptions
|
||||||
|
*/
|
||||||
|
class SyntaxException extends Exception { }
|
||||||
|
class AuthenticationException extends Exception { }
|
||||||
|
class InvalidResponseException extends Exception { }
|
||||||
|
class NonEmptyContainerException extends Exception { }
|
||||||
|
class NoSuchObjectException extends Exception { }
|
||||||
|
class NoSuchContainerException extends Exception { }
|
||||||
|
class NoSuchAccountException extends Exception { }
|
||||||
|
class MisMatchedChecksumException extends Exception { }
|
||||||
|
class IOException extends Exception { }
|
||||||
|
class CDNNotEnabledException extends Exception { }
|
||||||
|
class BadContentTypeException extends Exception { }
|
||||||
|
class InvalidUTF8Exception extends Exception { }
|
||||||
|
class ConnectionNotOpenException extends Exception { }
|
||||||
|
|
||||||
|
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* tab-width: 4
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* c-hanging-comment-ender-p: nil
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
|
?>
|
File diff suppressed because it is too large
Load Diff
|
@ -9,3 +9,4 @@
|
||||||
OC::$CLASSPATH['OC_Filestorage_FTP']='apps/files_external/lib/ftp.php';
|
OC::$CLASSPATH['OC_Filestorage_FTP']='apps/files_external/lib/ftp.php';
|
||||||
OC::$CLASSPATH['OC_Filestorage_DAV']='apps/files_external/lib/webdav.php';
|
OC::$CLASSPATH['OC_Filestorage_DAV']='apps/files_external/lib/webdav.php';
|
||||||
OC::$CLASSPATH['OC_Filestorage_Google']='apps/files_external/lib/google.php';
|
OC::$CLASSPATH['OC_Filestorage_Google']='apps/files_external/lib/google.php';
|
||||||
|
OC::$CLASSPATH['OC_Filestorage_SWIFT']='apps/files_external/lib/swift.php';
|
||||||
|
|
|
@ -0,0 +1,488 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once('php-cloudfiles/cloudfiles.php');
|
||||||
|
|
||||||
|
class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
|
||||||
|
private $host;
|
||||||
|
private $root;
|
||||||
|
private $user;
|
||||||
|
private $token;
|
||||||
|
private $secure;
|
||||||
|
/**
|
||||||
|
* @var CF_Authentication auth
|
||||||
|
*/
|
||||||
|
private $auth;
|
||||||
|
/**
|
||||||
|
* @var CF_Connection conn
|
||||||
|
*/
|
||||||
|
private $conn;
|
||||||
|
/**
|
||||||
|
* @var CF_Container rootContainer
|
||||||
|
*/
|
||||||
|
private $rootContainer;
|
||||||
|
|
||||||
|
private static $tempFiles=array();
|
||||||
|
|
||||||
|
const SUBCONTAINER_FILE='.subcontainers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* translate directory path to container name
|
||||||
|
* @param string path
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function getContainerName($path){
|
||||||
|
$path=trim($this->root.$path,'/');
|
||||||
|
return md5($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get container by path
|
||||||
|
* @param string path
|
||||||
|
* @return CF_Container
|
||||||
|
*/
|
||||||
|
private function getContainer($path){
|
||||||
|
if($path=='' or $path=='/'){
|
||||||
|
return $this->rootContainer;
|
||||||
|
}
|
||||||
|
try{
|
||||||
|
$container=$this->conn->get_container($this->getContainerName($path));
|
||||||
|
return $container;
|
||||||
|
}catch(NoSuchContainerException $e){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create container
|
||||||
|
* @param string path
|
||||||
|
* @return CF_Container
|
||||||
|
*/
|
||||||
|
private function createContainer($path){
|
||||||
|
if($path=='' or $path=='/'){
|
||||||
|
return $this->conn->create_container($this->getContainerName($path));
|
||||||
|
}
|
||||||
|
$parent=dirname($path);
|
||||||
|
if($parent=='' or $parent=='/'){
|
||||||
|
$parentContainer=$this->rootContainer;
|
||||||
|
}else{
|
||||||
|
if(!$this->containerExists($parent)){
|
||||||
|
$parentContainer=$this->createContainer($parent);
|
||||||
|
}else{
|
||||||
|
$parentContainer=$this->getContainer($parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->addSubContainer($parentContainer,basename($path));
|
||||||
|
return $this->conn->create_container($this->getContainerName($path));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get object by path
|
||||||
|
* @param string path
|
||||||
|
* @return CF_Object
|
||||||
|
*/
|
||||||
|
private function getObject($path){
|
||||||
|
$container=$this->getContainer(dirname($path));
|
||||||
|
if(is_null($container)){
|
||||||
|
return null;
|
||||||
|
}else{
|
||||||
|
try{
|
||||||
|
$obj=$container->get_object(basename($path));
|
||||||
|
return $obj;
|
||||||
|
}catch(NoSuchObjectException $e){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the names of all objects in a container
|
||||||
|
* @param CF_Container
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getObjects($container){
|
||||||
|
if(is_null($container)){
|
||||||
|
return array();
|
||||||
|
}else{
|
||||||
|
$files=$container->get_objects();
|
||||||
|
foreach($files as &$file){
|
||||||
|
$file=$file->name;
|
||||||
|
}
|
||||||
|
return $files;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create object
|
||||||
|
* @param string path
|
||||||
|
* @return CF_Object
|
||||||
|
*/
|
||||||
|
private function createObject($path){
|
||||||
|
$container=$this->getContainer(dirname($path));
|
||||||
|
if(!is_null($container)){
|
||||||
|
$container=$this->createContainer($path);
|
||||||
|
}
|
||||||
|
return $container->create_object(basename($path));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check if an object exists
|
||||||
|
* @param string
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function objectExists($path){
|
||||||
|
return !is_null($this->getObject($path));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check if container for path exists
|
||||||
|
* @param string path
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function containerExists($path){
|
||||||
|
return !is_null($this->getContainer($path));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the list of emulated sub containers
|
||||||
|
* @param CF_Container container
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getSubContainers($container){
|
||||||
|
$tmpFile=OC_Helper::tmpFile();
|
||||||
|
$obj=$this->getSubContainerFile($container);
|
||||||
|
try{
|
||||||
|
$obj->save_to_filename($tmpFile);
|
||||||
|
}catch(Exception $e){
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
$obj->save_to_filename($tmpFile);
|
||||||
|
$containers=file($tmpFile);
|
||||||
|
unlink($tmpFile);
|
||||||
|
foreach($containers as &$sub){
|
||||||
|
$sub=trim($sub);
|
||||||
|
}
|
||||||
|
return $containers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add an emulated sub container
|
||||||
|
* @param CF_Container container
|
||||||
|
* @param string name
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function addSubContainer($container,$name){
|
||||||
|
if(!$name){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$tmpFile=OC_Helper::tmpFile();
|
||||||
|
$obj=$this->getSubContainerFile($container);
|
||||||
|
try{
|
||||||
|
$obj->save_to_filename($tmpFile);
|
||||||
|
$containers=file($tmpFile);
|
||||||
|
foreach($containers as &$sub){
|
||||||
|
$sub=trim($sub);
|
||||||
|
}
|
||||||
|
if(array_search($name,$containers)!==false){
|
||||||
|
unlink($tmpFile);
|
||||||
|
return false;
|
||||||
|
}else{
|
||||||
|
$fh=fopen($tmpFile,'a');
|
||||||
|
fwrite($fh,$name."\n");
|
||||||
|
}
|
||||||
|
}catch(Exception $e){
|
||||||
|
$containers=array();
|
||||||
|
file_put_contents($tmpFile,$name."\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
$obj->load_from_filename($tmpFile);
|
||||||
|
unlink($tmpFile);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remove an emulated sub container
|
||||||
|
* @param CF_Container container
|
||||||
|
* @param string name
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function removeSubContainer($container,$name){
|
||||||
|
if(!$name){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$tmpFile=OC_Helper::tmpFile();
|
||||||
|
$obj=$this->getSubContainerFile($container);
|
||||||
|
try{
|
||||||
|
$obj->save_to_filename($tmpFile);
|
||||||
|
$containers=file($tmpFile);
|
||||||
|
}catch(Exception $e){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
foreach($containers as &$sub){
|
||||||
|
$sub=trim($sub);
|
||||||
|
}
|
||||||
|
$i=array_search($name,$containers);
|
||||||
|
if($i===false){
|
||||||
|
unlink($tmpFile);
|
||||||
|
return false;
|
||||||
|
}else{
|
||||||
|
unset($containers[$i]);
|
||||||
|
file_put_contents($tmpFile,implode("\n",$containers)."\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
$obj->load_from_filename($tmpFile);
|
||||||
|
unlink($tmpFile);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ensure a subcontainer file exists and return it's object
|
||||||
|
* @param CF_Container container
|
||||||
|
* @return CF_Object
|
||||||
|
*/
|
||||||
|
private function getSubContainerFile($container){
|
||||||
|
try{
|
||||||
|
return $container->get_object(self::SUBCONTAINER_FILE);
|
||||||
|
}catch(NoSuchObjectException $e){
|
||||||
|
return $container->create_object(self::SUBCONTAINER_FILE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __construct($params){
|
||||||
|
$this->token=$params['token'];
|
||||||
|
$this->host=$params['host'];
|
||||||
|
$this->user=$params['user'];
|
||||||
|
$this->root=isset($params['root'])?$params['root']:'/';
|
||||||
|
$this->secure=isset($params['secure'])?(bool)$params['secure']:true;
|
||||||
|
if(substr($this->root,0,1)!='/'){
|
||||||
|
$this->root='/'.$this->root;
|
||||||
|
}
|
||||||
|
$this->auth = new CF_Authentication($this->user, $this->token, null, $this->host);
|
||||||
|
$this->auth->authenticate();
|
||||||
|
|
||||||
|
$this->conn = new CF_Connection($this->auth);
|
||||||
|
|
||||||
|
if(!$this->containerExists($this->root)){
|
||||||
|
$this->rootContainer=$this->createContainer('/');
|
||||||
|
}else{
|
||||||
|
$this->rootContainer=$this->getContainer('/');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function mkdir($path){
|
||||||
|
if($this->containerExists($path)){
|
||||||
|
return false;
|
||||||
|
}else{
|
||||||
|
$this->createContainer($path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rmdir($path){
|
||||||
|
if(!$this->containerExists($path)){
|
||||||
|
return false;
|
||||||
|
}else{
|
||||||
|
$this->emptyContainer($path);
|
||||||
|
if($path!='' and $path!='/'){
|
||||||
|
$parentContainer=$this->getContainer(dirname($path));
|
||||||
|
$this->removeSubContainer($parentContainer,basename($path));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->conn->delete_container($this->getContainerName($path));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function emptyContainer($path){
|
||||||
|
$container=$this->getContainer($path);
|
||||||
|
if(is_null($container)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$subContainers=$this->getSubContainers($container);
|
||||||
|
foreach($subContainers as $sub){
|
||||||
|
if($sub){
|
||||||
|
$this->emptyContainer($path.'/'.$sub);
|
||||||
|
$this->conn->delete_container($this->getContainerName($path.'/'.$sub));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$objects=$this->getObjects($container);
|
||||||
|
foreach($objects as $object){
|
||||||
|
$container->delete_object($object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function opendir($path){
|
||||||
|
$container=$this->getContainer($path);
|
||||||
|
$files=$this->getObjects($container);
|
||||||
|
$i=array_search(self::SUBCONTAINER_FILE,$files);
|
||||||
|
if($i!==false){
|
||||||
|
unset($files[$i]);
|
||||||
|
}
|
||||||
|
$subContainers=$this->getSubContainers($container);
|
||||||
|
$files=array_merge($files,$subContainers);
|
||||||
|
$id=$this->getContainerName($path);
|
||||||
|
OC_FakeDirStream::$dirs[$id]=$files;
|
||||||
|
return opendir('fakedir://'.$id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function filetype($path){
|
||||||
|
if($this->containerExists($path)){
|
||||||
|
return 'dir';
|
||||||
|
}else{
|
||||||
|
return 'file';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function is_readable($path){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function is_writable($path){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function file_exists($path){
|
||||||
|
if($this->is_dir($path)){
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
return $this->objectExists($path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function file_get_contents($path){
|
||||||
|
$obj=$this->getObject($path);
|
||||||
|
if(is_null($obj)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $obj->read();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function file_put_contents($path,$content){
|
||||||
|
$obj=$this->getObject($path);
|
||||||
|
if(is_null($obj)){
|
||||||
|
$container=$this->getContainer(dirname($path));
|
||||||
|
if(is_null($container)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$obj=$container->create_object(basename($path));
|
||||||
|
}
|
||||||
|
return $obj->write($content);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function unlink($path){
|
||||||
|
if($this->objectExists($path)){
|
||||||
|
$container=$this->getContainer(dirname($path));
|
||||||
|
$container->delete_object(basename($path));
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fopen($path,$mode){
|
||||||
|
$obj=$this->getObject($path);
|
||||||
|
if(is_null($obj)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch($mode){
|
||||||
|
case 'r':
|
||||||
|
case 'rb':
|
||||||
|
$fp = fopen('php://temp', 'r+');
|
||||||
|
$obj->stream($fp);
|
||||||
|
|
||||||
|
rewind($fp);
|
||||||
|
return $fp;
|
||||||
|
case 'w':
|
||||||
|
case 'wb':
|
||||||
|
case 'a':
|
||||||
|
case 'ab':
|
||||||
|
case 'r+':
|
||||||
|
case 'w+':
|
||||||
|
case 'wb+':
|
||||||
|
case 'a+':
|
||||||
|
case 'x':
|
||||||
|
case 'x+':
|
||||||
|
case 'c':
|
||||||
|
case 'c+':
|
||||||
|
$tmpFile=$this->getTmpFile($path);
|
||||||
|
OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this,'writeBack');
|
||||||
|
self::$tempFiles[$tmpFile]=$path;
|
||||||
|
return fopen('close://'.$tmpFile,$mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function writeBack($tmpFile){
|
||||||
|
if(isset(self::$tempFiles[$tmpFile])){
|
||||||
|
$this->fromTmpFile($tmpFile,self::$tempFiles[$tmpFile]);
|
||||||
|
unlink($tmpFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function free_space($path){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function touch($path,$mtime=null){
|
||||||
|
if(!is_null($mtime)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$obj=$this->getObject($path);
|
||||||
|
if(is_null($obj)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$fp = fopen('php://temp', 'r+');
|
||||||
|
$obj->stream($fp);
|
||||||
|
rewind($fp);
|
||||||
|
$obj->write($fp);
|
||||||
|
fclose($fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rename($path1,$path2){
|
||||||
|
$sourceContainer=$this->getContainer(dirname($path1));
|
||||||
|
$targetContainer=$this->getContainer(dirname($path2));
|
||||||
|
return $sourceContainer->move_object_to(basename($path1),$targetContainer,basename($path2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function copy($path1,$path2){
|
||||||
|
$sourceContainer=$this->getContainer(dirname($path1));
|
||||||
|
$targetContainer=$this->getContainer(dirname($path2));
|
||||||
|
return $sourceContainer->copy_object_to(basename($path1),$targetContainer,basename($path2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stat($path){
|
||||||
|
$obj=$this->getObject($path);
|
||||||
|
if(is_null($obj)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return array(
|
||||||
|
'mtime'=>strtotime($obj->last_modified),
|
||||||
|
'size'=>$obj->content_length,
|
||||||
|
'ctime'=>-1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getTmpFile($path){
|
||||||
|
$obj=$this->getObject($path);
|
||||||
|
if(!is_null($obj)){
|
||||||
|
$tmpFile=OC_Helper::tmpFile();
|
||||||
|
$obj->save_to_filename($tmpFile);
|
||||||
|
return $tmpFile;
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function fromTmpFile($tmpFile,$path){
|
||||||
|
$obj=$this->getObject($path);
|
||||||
|
if(is_null($obj)){
|
||||||
|
$obj=$this->createObject($path);
|
||||||
|
}
|
||||||
|
$obj->load_from_filename($tmpFile);
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,5 +21,12 @@ return array(
|
||||||
'token'=>'test',
|
'token'=>'test',
|
||||||
'token_secret'=>'test',
|
'token_secret'=>'test',
|
||||||
'root'=>'/google',
|
'root'=>'/google',
|
||||||
)
|
),
|
||||||
|
'swift'=>array(
|
||||||
|
'run'=>true,
|
||||||
|
'user'=>'test:tester',
|
||||||
|
'token'=>'testing',
|
||||||
|
'host'=>'localhost:8080/auth',
|
||||||
|
'root'=>'/',
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$config=include('apps/files_external/tests/config.php');
|
||||||
|
if(!is_array($config) or !isset($config['swift']) or !$config['swift']['run']){
|
||||||
|
abstract class Test_Filestorage_SWIFT extends Test_FileStorage{}
|
||||||
|
return;
|
||||||
|
}else{
|
||||||
|
class Test_Filestorage_SWIFT extends Test_FileStorage {
|
||||||
|
private $config;
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
public function setUp(){
|
||||||
|
$id=uniqid();
|
||||||
|
$this->config=include('apps/files_external/tests/config.php');
|
||||||
|
$this->config['swift']['root'].='/'.$id;//make sure we have an new empty folder to work in
|
||||||
|
$this->instance=new OC_Filestorage_SWIFT($this->config['swift']);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function tearDown(){
|
||||||
|
$this->instance->rmdir('');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue