Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorGeorg Ehrke <dev@georgswebsite.de>2012-04-22 00:12:31 +0400
committerGeorg Ehrke <dev@georgswebsite.de>2012-04-22 00:12:31 +0400
commite29ae46609f42a03ade20c7f935e2cded84db51f (patch)
treeb896f79353e792c5d34d7dc8dc9220c49bbfd6df /apps
parentcf492a96496920c42f3ad384f5ca0886a5323c72 (diff)
parent6bfe2289be05e9f54272a86a0f957ec41ef32e28 (diff)
fix merge conflicts
Diffstat (limited to 'apps')
-rw-r--r--apps/calendar/ajax/import/import.php134
-rw-r--r--apps/calendar/export.php4
-rw-r--r--apps/files_encryption/lib/crypt.php55
-rw-r--r--apps/files_encryption/lib/cryptstream.php38
-rw-r--r--apps/files_encryption/lib/proxy.php7
-rw-r--r--apps/files_encryption/tests/encryption.php42
-rw-r--r--apps/files_encryption/tests/stream.php56
-rw-r--r--apps/files_external/appinfo/app.php1
-rw-r--r--apps/files_external/lib/swift.php516
-rw-r--r--apps/files_external/tests/config.php9
-rw-r--r--apps/files_external/tests/swift.php32
11 files changed, 779 insertions, 115 deletions
diff --git a/apps/calendar/ajax/import/import.php b/apps/calendar/ajax/import/import.php
index d0bdab4f0d5..4d5e7340aef 100644
--- a/apps/calendar/ajax/import/import.php
+++ b/apps/calendar/ajax/import/import.php
@@ -7,11 +7,12 @@
*/
//check for calendar rights or create new one
ob_start();
-require_once('../../../../lib/base.php');
+require_once ('../../../../lib/base.php');
OC_JSON::checkLoggedIn();
OC_Util::checkAppEnabled('calendar');
-$nl = "\n\r";
-$progressfile = OC::$APPSROOT . '/apps/calendar/import_tmp/' . md5(session_id()) . '.txt';
+$nl="\r\n";
+$comps = array('VEVENT'=>true, 'VTODO'=>true, 'VJOURNAL'=>true);
+$progressfile = 'import_tmp/' . md5(session_id()) . '.txt';
if(is_writable('import_tmp/')){
$progressfopen = fopen($progressfile, 'w');
fwrite($progressfopen, '10');
@@ -29,85 +30,94 @@ if($_POST['method'] == 'new'){
}
$id = $_POST['id'];
}
-//analyse the calendar file
if(is_writable('import_tmp/')){
$progressfopen = fopen($progressfile, 'w');
fwrite($progressfopen, '20');
fclose($progressfopen);
}
-$searchfor = array('VEVENT', 'VTODO', 'VJOURNAL');
-$parts = $searchfor;
-$filearr = explode($nl, $file);
-$inelement = false;
-$parts = array();
+// normalize the newlines
+$file = str_replace(array("\r","\n\n"), array("\n","\n"), $file);
+$lines = explode("\n", $file);
+unset($file);
+if(is_writable('import_tmp/')){
+ $progressfopen = fopen($progressfile, 'w');
+ fwrite($progressfopen, '30');
+ fclose($progressfopen);
+}
+// analyze the file, group components by uid, and keep refs to originating calendar object
+// $cals is array calendar objects, keys are 1st line# $cal, ie array( $cal => $caldata )
+// $caldata is array( 'first' => 1st component line#, 'last' => last comp line#, 'end' => end line# )
+// $caldata is used to create prefix/suffix strings when building import text
+// $uids is array of component arrays, keys are $uid, ie array( $uid => array( $beginlineno => $component ) )
+// $component is array( 'end' => end line#, 'cal'=> $cal )
+$comp=$uid=$cal=false;
+$cals=$uids=array();
$i = 0;
-foreach($filearr as $line){
- foreach($searchfor as $search){
- if(substr_count($line, $search) == 1){
- list($attr, $val) = explode(':', $line);
- if($attr == 'BEGIN'){
- $parts[]['begin'] = $i;
- $inelement = true;
+foreach($lines as $line) {
+
+ if(strpos($line, ':')!==false) {
+ list($attr, $val) = explode(':', strtoupper($line));
+ if ($attr == 'BEGIN' && $val == 'VCALENDAR') {
+ $cal = $i;
+ $cals[$cal] = array('first'=>$i,'last'=>$i,'end'=>$i);
+ } elseif ($attr =='BEGIN' && $cal!==false && isset($comps[$val])) {
+ $comp = $val;
+ $beginNo = $i;
+ } elseif ($attr == 'END' && $cal!==false && $val == 'VCALENDAR') {
+ if($comp!==false) {
+ unset($cals[$cal]); // corrupt calendar, unset it
+ } else {
+ $cals[$cal]['end'] = $i;
+ }
+ $comp=$uid=$cal=false; // reset calendar
+ } elseif ($attr == 'END' && $comp!==false && $val == $comp) {
+ if(! $uid) {
+ $uid = OC_Calendar_Object::createUID();
}
- if($attr == 'END'){
- $parts[count($parts) - 1]['end'] = $i;
- $inelement = false;
+ $uids[$uid][$beginNo] = array('end'=>$i, 'cal'=>$cal);
+ if ($cals[$cal]['first'] == $cal) {
+ $cals[$cal]['first'] = $beginNo;
}
+ $cals[$cal]['last'] = $i;
+ $comp=$uid=false; // reset component
+ } elseif ($attr =="UID" && $comp!==false) {
+ list($attr, $uid) = explode(':', $line);
}
}
$i++;
}
-//import the calendar
+// import the calendar
if(is_writable('import_tmp/')){
$progressfopen = fopen($progressfile, 'w');
- fwrite($progressfopen, '40');
+ fwrite($progressfopen, '60');
fclose($progressfopen);
}
-$start = '';
-for ($i = 0; $i < $parts[0]['begin']; $i++) {
- if($i == 0){
- $start = $filearr[0];
- }else{
- $start .= $nl . $filearr[$i];
- }
-}
-$end = '';
-for($i = $parts[count($parts) - 1]['end'] + 1;$i <= count($filearr) - 1; $i++){
- if($i == $parts[count($parts) - 1]['end'] + 1){
- $end = $filearr[$parts[count($parts) - 1]['end'] + 1];
- }else{
- $end .= $nl . $filearr[$i];
- }
-}
-if(is_writable('import_tmp/')){
- $progressfopen = fopen($progressfile, 'w');
- fwrite($progressfopen, '50');
- fclose($progressfopen);
-}
-$importready = array();
-foreach($parts as $part){
- for($i = $part['begin']; $i <= $part['end'];$i++){
- if($i == $part['begin']){
- $content = $filearr[$i];
- }else{
- $content .= $nl . $filearr[$i];
+foreach($uids as $uid) {
+
+ $prefix=$suffix=$content=array();
+ foreach($uid as $begin=>$details) {
+
+ $cal = $details['cal'];
+ if(!isset($cals[$cal])) {
+ continue; // from corrupt/incomplete calendar
+ }
+ $cdata = $cals[$cal];
+ // if we have multiple components from different calendar objects,
+ // we should really merge their elements (enhancement?) -- 1st one wins for now.
+ if(! count($prefix)) {
+ $prefix = array_slice($lines, $cal, $cdata['first'] - $cal);
}
+ if(! count($suffix)) {
+ $suffix = array_slice($lines, $cdata['last']+1, $cdata['end'] - $cdata['last']);
+ }
+ $content = array_merge($content, array_slice($lines, $begin, $details['end'] - $begin + 1));
}
- $importready[] = $start . $nl . $content . $nl . $end;
-}
-if(is_writable('import_tmp/')){
- $progressfopen = fopen($progressfile, 'w');
- fwrite($progressfopen, '70');
- fclose($progressfopen);
-}
-if(count($parts) == 1){
- OC_Calendar_Object::add($id, $file);
-}else{
- foreach($importready as $import){
+ if(count($content)) {
+ $import = join($nl, array_merge($prefix, $content, $suffix)) . $nl;
OC_Calendar_Object::add($id, $import);
}
}
-//done the import
+// finished import
if(is_writable('import_tmp/')){
$progressfopen = fopen($progressfile, 'w');
fwrite($progressfopen, '100');
@@ -117,4 +127,4 @@ sleep(3);
if(is_writable('import_tmp/')){
unlink($progressfile);
}
-OC_JSON::success();
+OC_JSON::success(); \ No newline at end of file
diff --git a/apps/calendar/export.php b/apps/calendar/export.php
index e4caa1bde75..95cba03906f 100644
--- a/apps/calendar/export.php
+++ b/apps/calendar/export.php
@@ -11,7 +11,7 @@ OC_Util::checkLoggedIn();
OC_Util::checkAppEnabled('calendar');
$cal = isset($_GET['calid']) ? $_GET['calid'] : NULL;
$event = isset($_GET['eventid']) ? $_GET['eventid'] : NULL;
-$nl = "\n\r";
+$nl = "\r\n";
if(isset($cal)){
$calendar = OC_Calendar_App::getCalendar($cal, true);
$calobjects = OC_Calendar_Object::all($cal);
@@ -28,4 +28,4 @@ if(isset($cal)){
header('Content-Disposition: inline; filename=' . $data['summary'] . '.ics');
echo $data['calendardata'];
}
-?> \ No newline at end of file
+?>
diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php
index 246d4f672db..8cf9451c63c 100644
--- a/apps/files_encryption/lib/crypt.php
+++ b/apps/files_encryption/lib/crypt.php
@@ -119,7 +119,7 @@ class OC_Crypt {
*/
public static function encrypt( $content, $key='') {
$bf = self::getBlowfish($key);
- return($bf->encrypt($content));
+ return $bf->encrypt($content);
}
/**
@@ -132,61 +132,62 @@ class OC_Crypt {
*/
public static function decrypt( $content, $key='') {
$bf = self::getBlowfish($key);
- return($bf->decrypt($content));
+ $data=$bf->decrypt($content);
+ return rtrim($data, "\0");
}
/**
* @brief encryption of a file
- * @param $filename
- * @param $key the encryption key
+ * @param string $source
+ * @param string $target
+ * @param string $key the decryption key
*
* This function encrypts a file
*/
- public static function encryptfile( $filename, $key) {
- $handleread = fopen($filename, "rb");
- if($handleread<>FALSE) {
- $handlewrite = fopen($filename.OC_Crypt::$encription_extension, "wb");
+ public static function encryptFile( $source, $target, $key='') {
+ $handleread = fopen($source, "rb");
+ if($handleread!=FALSE) {
+ $handlewrite = fopen($target, "wb");
while (!feof($handleread)) {
$content = fread($handleread, 8192);
$enccontent=OC_CRYPT::encrypt( $content, $key);
fwrite($handlewrite, $enccontent);
}
fclose($handlewrite);
- unlink($filename);
+ fclose($handleread);
}
- fclose($handleread);
}
- /**
- * @brief decryption of a file
- * @param $filename
- * @param $key the decryption key
- *
- * This function decrypts a file
- */
- public static function decryptfile( $filename, $key) {
- $handleread = fopen($filename.OC_Crypt::$encription_extension, "rb");
- if($handleread<>FALSE) {
- $handlewrite = fopen($filename, "wb");
+ /**
+ * @brief decryption of a file
+ * @param string $source
+ * @param string $target
+ * @param string $key the decryption key
+ *
+ * This function decrypts a file
+ */
+ public static function decryptFile( $source, $target, $key='') {
+ $handleread = fopen($source, "rb");
+ if($handleread!=FALSE) {
+ $handlewrite = fopen($target, "wb");
while (!feof($handleread)) {
$content = fread($handleread, 8192);
$enccontent=OC_CRYPT::decrypt( $content, $key);
fwrite($handlewrite, $enccontent);
}
fclose($handlewrite);
- unlink($filename.OC_Crypt::$encription_extension);
+ fclose($handleread);
}
- fclose($handleread);
}
/**
* encrypt data in 8192b sized blocks
*/
- public static function blockEncrypt($data){
+ public static function blockEncrypt($data, $key=''){
$result='';
while(strlen($data)){
- $result=self::encrypt(substr($data,0,8192));
+ $result.=self::encrypt(substr($data,0,8192),$key);
$data=substr($data,8192);
}
return $result;
@@ -195,10 +196,10 @@ class OC_Crypt {
/**
* decrypt data in 8192b sized blocks
*/
- public static function blockDecrypt($data){
+ public static function blockDecrypt($data, $key=''){
$result='';
while(strlen($data)){
- $result=self::decrypt(substr($data,0,8192));
+ $result.=self::decrypt(substr($data,0,8192),$key);
$data=substr($data,8192);
}
return $result;
diff --git a/apps/files_encryption/lib/cryptstream.php b/apps/files_encryption/lib/cryptstream.php
index 86583096f1d..21fa38e4b59 100644
--- a/apps/files_encryption/lib/cryptstream.php
+++ b/apps/files_encryption/lib/cryptstream.php
@@ -64,29 +64,19 @@ class OC_CryptStream{
}
public function stream_read($count){
- $pos=0;
- $currentPos=ftell($this->source);
- $offset=$currentPos%8192;
- $result='';
- if($offset>0){
- if($this->meta['seekable']){
- fseek($this->source,-$offset,SEEK_CUR);//if seeking isnt supported the internal read buffer will be used
- }else{
- $pos=strlen($this->readBuffer);
- $result=$this->readBuffer;
- }
+ //$count will always be 8192 https://bugs.php.net/bug.php?id=21641
+ //This makes this function a lot simpler but will breake everything the moment it's fixed
+ if($count!=8192){
+ OC_Log::write('files_encryption','php bug 21641 no longer holds, decryption will not work',OC_Log::FATAL);
+ die();
}
- while($count>$pos){
- $data=fread($this->source,8192);
- $pos+=8192;
- if(strlen($data)){
- $result.=OC_Crypt::decrypt($data);
- }
- }
- if(!$this->meta['seekable']){
- $this->readBuffer=substr($result,$count);
+ $data=fread($this->source,8192);
+ if(strlen($data)){
+ $result=OC_Crypt::decrypt($data);
+ }else{
+ $result='';
}
- return substr($result,0,$count);
+ return $result;
}
public function stream_write($data){
@@ -107,8 +97,10 @@ class OC_CryptStream{
$oldPos=ftell($this->source);
$encryptedBlock=fread($this->source,8192);
fseek($this->source,$oldPos);
- $block=OC_Crypt::decrypt($encryptedBlock);
- $data.=substr($block,strlen($data));
+ if($encryptedBlock){
+ $block=OC_Crypt::decrypt($encryptedBlock);
+ $data.=substr($block,strlen($data));
+ }
}
$encrypted=OC_Crypt::encrypt(substr($data,0,8192));
fwrite($this->source,$encrypted);
diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php
index c68df06f9fa..a0de411a7b6 100644
--- a/apps/files_encryption/lib/proxy.php
+++ b/apps/files_encryption/lib/proxy.php
@@ -28,6 +28,7 @@
class OC_FileProxy_Encryption extends OC_FileProxy{
private static $blackList=null; //mimetypes blacklisted from encryption
private static $metaData=array(); //metadata cache
+ private static $enableEncryption=null;
/**
* check if a file should be encrypted during write
@@ -35,6 +36,12 @@ class OC_FileProxy_Encryption extends OC_FileProxy{
* @return bool
*/
private static function shouldEncrypt($path){
+ if(is_null($this->enableEncryption)){
+ $this->enableEncryption=(OC_Appconfig::getValue('files_encryption','enabled','true')=='true');
+ }
+ if(!$this->enableEncryption){
+ return false;
+ }
if(is_null(self::$blackList)){
self::$blackList=explode(',',OC_Appconfig::getValue('files_encryption','type_blacklist','jpg,png,jpeg,avi,mpg,mpeg,mkv,mp3,oga,ogv,ogg'));
}
diff --git a/apps/files_encryption/tests/encryption.php b/apps/files_encryption/tests/encryption.php
new file mode 100644
index 00000000000..13093256717
--- /dev/null
+++ b/apps/files_encryption/tests/encryption.php
@@ -0,0 +1,42 @@
+<?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.
+ */
+
+class Test_Encryption extends UnitTestCase {
+ function testEncryption(){
+ $key=uniqid();
+ $file=OC::$SERVERROOT.'/3rdparty/MDB2.php';
+ $source=file_get_contents($file); //nice large text file
+ $encrypted=OC_Crypt::encrypt($source,$key);
+ $decrypted=OC_Crypt::decrypt($encrypted,$key);
+ $this->assertNotEqual($encrypted,$source);
+ $this->assertEqual($decrypted,$source);
+
+ $chunk=substr($source,0,8192);
+ $encrypted=OC_Crypt::encrypt($chunk,$key);
+ $this->assertEqual(strlen($chunk),strlen($encrypted));
+ $decrypted=OC_Crypt::decrypt($encrypted,$key);
+ $this->assertEqual($decrypted,$chunk);
+
+ $encrypted=OC_Crypt::blockEncrypt($source,$key);
+ $decrypted=OC_Crypt::blockDecrypt($encrypted,$key);
+ $this->assertNotEqual($encrypted,$source);
+ $this->assertEqual($decrypted,$source);
+
+ $tmpFileEncrypted=OC_Helper::tmpFile();
+ OC_Crypt::encryptfile($file,$tmpFileEncrypted,$key);
+ $encrypted=file_get_contents($tmpFileEncrypted);
+ $decrypted=OC_Crypt::blockDecrypt($encrypted,$key);
+ $this->assertNotEqual($encrypted,$source);
+ $this->assertEqual($decrypted,$source);
+
+ $tmpFileDecrypted=OC_Helper::tmpFile();
+ OC_Crypt::decryptfile($tmpFileEncrypted,$tmpFileDecrypted,$key);
+ $decrypted=file_get_contents($tmpFileDecrypted);
+ $this->assertEqual($decrypted,$source);
+ }
+}
diff --git a/apps/files_encryption/tests/stream.php b/apps/files_encryption/tests/stream.php
new file mode 100644
index 00000000000..578b091a36c
--- /dev/null
+++ b/apps/files_encryption/tests/stream.php
@@ -0,0 +1,56 @@
+<?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.
+ */
+
+class Test_CryptStream extends UnitTestCase {
+ private $tmpFiles=array();
+
+ function testStream(){
+ $stream=$this->getStream('test1','w');
+ fwrite($stream,'foobar');
+ fclose($stream);
+
+ $stream=$this->getStream('test1','r');
+ $data=fread($stream,6);
+ fclose($stream);
+ $this->assertEqual('foobar',$data);
+
+ $file=OC::$SERVERROOT.'/3rdparty/MDB2.php';
+ $source=fopen($file,'r');
+ $target=$this->getStream('test2','w');
+ OC_Helper::streamCopy($source,$target);
+ fclose($target);
+ fclose($source);
+
+ $stream=$this->getStream('test2','r');
+ $data=stream_get_contents($stream);
+ $original=file_get_contents($file);
+ $this->assertEqual(strlen($original),strlen($data));
+ $this->assertEqual($original,$data);
+ }
+
+ /**
+ * get a cryptstream to a temporary file
+ * @param string $id
+ * @param string $mode
+ * @return resource
+ */
+ function getStream($id,$mode){
+ if($id===''){
+ $id=uniqid();
+ }
+ if(!isset($this->tmpFiles[$id])){
+ $file=OC_Helper::tmpFile();
+ $this->tmpFiles[$id]=$file;
+ }else{
+ $file=$this->tmpFiles[$id];
+ }
+ $stream=fopen($file,$mode);
+ OC_CryptStream::$sourceStreams[$id]=array('path'=>'dummy','stream'=>$stream);
+ return fopen('crypt://streams/'.$id,$mode);
+ }
+}
diff --git a/apps/files_external/appinfo/app.php b/apps/files_external/appinfo/app.php
index 95770b44b75..784ed032d47 100644
--- a/apps/files_external/appinfo/app.php
+++ b/apps/files_external/appinfo/app.php
@@ -9,3 +9,4 @@
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_Google']='apps/files_external/lib/google.php';
+OC::$CLASSPATH['OC_Filestorage_SWIFT']='apps/files_external/lib/swift.php';
diff --git a/apps/files_external/lib/swift.php b/apps/files_external/lib/swift.php
new file mode 100644
index 00000000000..e53eb1ff3b6
--- /dev/null
+++ b/apps/files_external/lib/swift.php
@@ -0,0 +1,516 @@
+<?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));
+ }
+ $this->resetMTime($obj);
+ 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){
+ $obj=$this->getObject($path);
+ if(is_null($obj)){
+ return false;
+ }
+ if(is_null($mtime)){
+ $mtime=time();
+ }
+
+ //emulate setting mtime with metadata
+ $obj->metadata['Mtime']=$mtime;
+ $obj->sync_metadata();
+ }
+
+ public function rename($path1,$path2){
+ $sourceContainer=$this->getContainer(dirname($path1));
+ $targetContainer=$this->getContainer(dirname($path2));
+ $result=$sourceContainer->move_object_to(basename($path1),$targetContainer,basename($path2));
+ if($result){
+ $targetObj=$this->getObject($path2);
+ $this->resetMTime($targetObj);
+ }
+ return $result;
+ }
+
+ public function copy($path1,$path2){
+ $sourceContainer=$this->getContainer(dirname($path1));
+ $targetContainer=$this->getContainer(dirname($path2));
+ $result=$sourceContainer->copy_object_to(basename($path1),$targetContainer,basename($path2));
+ if($result){
+ $targetObj=$this->getObject($path2);
+ $this->resetMTime($targetObj);
+ }
+ return $result;
+ }
+
+ public function stat($path){
+ $obj=$this->getObject($path);
+ if(is_null($obj)){
+ return false;
+ }
+
+ if(isset($obj->metadata['Mtime']) and $obj->metadata['Mtime']>-1){
+ $mtime=$obj->metadata['Mtime'];
+ }else{
+ $mtime=strtotime($obj->last_modified);
+ }
+ return array(
+ 'mtime'=>$mtime,
+ '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);
+ $this->resetMTime($obj);
+ }
+
+ /**
+ * remove custom mtime metadata
+ * @param CF_Object obj
+ */
+ private function resetMTime($obj){
+ if(isset($obj->metadata['Mtime'])){
+ $obj->metadata['Mtime']=-1;
+ $obj->sync_metadata();
+ }
+ }
+}
diff --git a/apps/files_external/tests/config.php b/apps/files_external/tests/config.php
index fa4c74a6e26..edbbe9dfec8 100644
--- a/apps/files_external/tests/config.php
+++ b/apps/files_external/tests/config.php
@@ -21,5 +21,12 @@ return array(
'token'=>'test',
'token_secret'=>'test',
'root'=>'/google',
- )
+ ),
+ 'swift'=>array(
+ 'run'=>true,
+ 'user'=>'test:tester',
+ 'token'=>'testing',
+ 'host'=>'localhost:8080/auth',
+ 'root'=>'/',
+ ),
);
diff --git a/apps/files_external/tests/swift.php b/apps/files_external/tests/swift.php
new file mode 100644
index 00000000000..f0bde6ed605
--- /dev/null
+++ b/apps/files_external/tests/swift.php
@@ -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('');
+ }
+
+ }
+}
+