From: Jan-Christoph Borchardt Date: Fri, 30 Mar 2012 16:10:16 +0000 (+0200) Subject: renaming remote storage support to External storage support to clear up naming conflict X-Git-Tag: v4.0.0beta~392^2~16 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=011132feb33b4f7954eb5df5e2283e9c8f8ae944;p=nextcloud-server.git renaming remote storage support to External storage support to clear up naming conflict --- diff --git a/apps/files_external/appinfo/app.php b/apps/files_external/appinfo/app.php new file mode 100644 index 00000000000..95770b44b75 --- /dev/null +++ b/apps/files_external/appinfo/app.php @@ -0,0 +1,11 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +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'; diff --git a/apps/files_external/appinfo/info.xml b/apps/files_external/appinfo/info.xml new file mode 100644 index 00000000000..fb58297ff17 --- /dev/null +++ b/apps/files_external/appinfo/info.xml @@ -0,0 +1,13 @@ + + + files_external + External storage support + Mount external storage sources + 0.1 + AGPL + Robin Appelman + 3 + + + + diff --git a/apps/files_external/lib/ftp.php b/apps/files_external/lib/ftp.php new file mode 100644 index 00000000000..802446b4fd8 --- /dev/null +++ b/apps/files_external/lib/ftp.php @@ -0,0 +1,157 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +class OC_FileStorage_FTP extends OC_Filestorage_Common{ + private $password; + private $user; + private $host; + private $secure; + private $root; + + private static $tempFiles=array(); + + public function __construct($params){ + $this->host=$params['host']; + $this->user=$params['user']; + $this->password=$params['password']; + $this->secure=isset($params['secure'])?(bool)$params['secure']:false; + $this->root=isset($params['root'])?$params['root']:'/'; + if(substr($this->root,0,1)!='/'){ + $this->root='/'.$this->root; + } + + //create the root folder if necesary + mkdir($this->constructUrl('')); + } + + /** + * construct the ftp url + * @param string path + * @return string + */ + public function constructUrl($path){ + $url='ftp'; + if($this->secure){ + $url.='s'; + } + $url.='://'.$this->user.':'.$this->password.'@'.$this->host.$this->root.$path; + return $url; + } + + public function mkdir($path){ + return mkdir($this->constructUrl($path)); + } + + public function rmdir($path){ + if($this->file_exists($path)){ + $succes=rmdir($this->constructUrl($path)); + clearstatcache(); + return $succes; + }else{ + return false; + } + } + + public function opendir($path){ + return opendir($this->constructUrl($path)); + } + + public function filetype($path){ + return filetype($this->constructUrl($path)); + } + + public function is_readable($path){ + return true;//not properly supported + } + + public function is_writable($path){ + return true;//not properly supported + } + + public function file_exists($path){ + return file_exists($this->constructUrl($path)); + } + + public function unlink($path){ + $succes=unlink($this->constructUrl($path)); + clearstatcache(); + return $succes; + } + + public function fopen($path,$mode){ + switch($mode){ + case 'r': + case 'rb': + case 'w': + case 'wb': + case 'a': + case 'ab': + //these are supported by the wrapper + $context = stream_context_create(array('ftp' => array('overwrite' => true))); + return fopen($this->constructUrl($path),$mode,false,$context); + case 'r+': + case 'w+': + case 'wb+': + case 'a+': + case 'x': + case 'x+': + case 'c': + case 'c+': + //emulate these + 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)){ + $this->getFile($path,$tmpFile); + } + self::$tempFiles[$tmpFile]=$path; + return fopen('close://'.$tmpFile,$mode); + } + } + + public function writeBack($tmpFile){ + if(isset(self::$tempFiles[$tmpFile])){ + $this->uploadFile($tmpFile,self::$tempFiles[$tmpFile]); + unlink($tmpFile); + } + } + + public function free_space($path){ + return 0; + } + + public function touch($path,$mtime=null){ + if(is_null($mtime)){ + $fh=$this->fopen($path,'a'); + fwrite($fh,''); + fclose($fh); + }else{ + return false;//not supported + } + } + + public function getFile($path,$target){ + return copy($this->constructUrl($path),$target); + } + + public function uploadFile($path,$target){ + return copy($path,$this->constructUrl($target)); + } + + public function rename($path1,$path2){ + return rename($this->constructUrl($path1),$this->constructUrl($path2)); + } + + public function stat($path){ + return stat($this->constructUrl($path)); + } +} diff --git a/apps/files_external/lib/google.php b/apps/files_external/lib/google.php new file mode 100644 index 00000000000..0d6db1987f8 --- /dev/null +++ b/apps/files_external/lib/google.php @@ -0,0 +1,409 @@ +. +*/ + +require_once 'common.inc.php'; + +class OC_Filestorage_Google extends OC_Filestorage_Common { + + private $consumer; + private $oauth_token; + private $sig_method; + private $entries; + + public function __construct($arguments) { + $consumer_key = isset($arguments['consumer_key']) ? $arguments['consumer_key'] : 'anonymous'; + $consumer_secret = isset($arguments['consumer_secret']) ? $arguments['consumer_secret'] : 'anonymous'; + $this->consumer = new OAuthConsumer($consumer_key, $consumer_secret); + $this->oauth_token = new OAuthToken($arguments['token'], $arguments['token_secret']); + $this->sig_method = new OAuthSignatureMethod_HMAC_SHA1(); + $this->entries = array(); + } + + private function sendRequest($feedUri, $http_method, $isDownload = false, $postData = null) { + $feedUri = trim($feedUri); + // create an associative array from each key/value url query param pair. + $params = array(); + $pieces = explode('?', $feedUri); + if (isset($pieces[1])) { + $params = explode_assoc('=', '&', $pieces[1]); + } + // urlencode each url parameter key/value pair + $tempStr = $pieces[0]; + foreach ($params as $key => $value) { + $tempStr .= '&' . urlencode($key) . '=' . urlencode($value); + } + $feedUri = preg_replace('/&/', '?', $tempStr, 1); + $request = OAuthRequest::from_consumer_and_token($this->consumer, $this->oauth_token, $http_method, $feedUri, $params); + $request->sign_request($this->sig_method, $this->consumer, $this->oauth_token); + $auth_header = $request->to_header(); + $headers = array($auth_header, 'Content-Type: application/atom+xml', 'GData-Version: 3.0'); + $curl = curl_init($feedUri); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_FAILONERROR, false); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + switch ($http_method) { + case 'GET': + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + break; + case 'POST': + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + curl_setopt($curl, CURLOPT_POST, 1); + curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); + break; + case 'PUT': + $headers[] = 'If-Match: *'; + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $http_method); + curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); + break; + case 'DELETE': + $headers[] = 'If-Match: *'; + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $http_method); + break; + default: + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + } + if ($isDownload) { + $tmpFile = OC_Helper::tmpFile(); + $fp = fopen($tmpFile, 'w'); + curl_setopt($curl, CURLOPT_FILE, $fp); + curl_exec($curl); + curl_close($curl); + return $tmpFile; + } + $result = curl_exec($curl); + curl_close($curl); + $dom = new DOMDocument(); + $dom->loadXML($result); + return $dom; + } + + private function getResource($path) { + $file = basename($path); + if (array_key_exists($file, $this->entries)) { + return $this->entries[$file]; + } else { + // Strip the file extension; file could be a native Google Docs resource + if ($pos = strpos($file, '.')) { + $title = substr($file, 0, $pos); + $dom = $this->sendRequest('https://docs.google.com/feeds/default/private/full?showfolders=true&title='.$title, 'GET'); + // Check if request was successful and entry exists + if ($dom && $entry = $dom->getElementsByTagName('entry')->item(0)) { + $this->entries[$file] = $entry; + return $entry; + } + } + $dom = $this->sendRequest('https://docs.google.com/feeds/default/private/full?showfolders=true&title='.$file, 'GET'); + // Check if request was successful and entry exists + if ($dom && $entry = $dom->getElementsByTagName('entry')->item(0)) { + $this->entries[$file] = $entry; + return $entry; + } + return false; + } + } + + private function getExtension($entry) { + $mimetype = $this->getMimeType('', $entry); + switch ($mimetype) { + case 'httpd/unix-directory': + return ''; + case 'application/vnd.oasis.opendocument.text': + return 'odt'; + case 'application/vnd.oasis.opendocument.spreadsheet': + return 'ods'; + case 'application/vnd.oasis.opendocument.presentation': + return 'pptx'; + case 'text/html': + return 'html'; + default: + return 'html'; + } + } + + + public function mkdir($path) { + $dir = dirname($path); + // Check if path parent is root directory + if ($dir == '/' || $dir == '\.' || $dir == '.') { + $feedUri = 'https://docs.google.com/feeds/default/private/full'; + // Get parent content link + } else if ($dom = $this->getResource(basename($dir))) { + $feedUri = $dom->getElementsByTagName('content')->item(0)->getAttribute('src'); + } + if (isset($feedUri)) { + $title = basename($path); + // Construct post data + $postData = ''; + $postData .= ''; + $postData .= ''; + $postData .= ''.$title.''; + $postData .= ''; + if ($dom = $this->sendRequest($feedUri, 'POST', $postData)) { + return true; + } + } + return false; + } + + public function rmdir($path) { + return $this->unlink($path); + } + + public function opendir($path) { + if ($path == '' || $path == '/') { + $next = 'https://docs.google.com/feeds/default/private/full/folder%3Aroot/contents'; + } else { + if ($entry = $this->getResource($path)) { + $next = $entry->getElementsByTagName('content')->item(0)->getAttribute('src'); + } else { + return false; + } + } + $files = array(); + while ($next) { + $dom = $this->sendRequest($next, 'GET'); + $links = $dom->getElementsByTagName('link'); + foreach ($links as $link) { + if ($link->getAttribute('rel') == 'next') { + $next = $link->getAttribute('src'); + break; + } else { + $next = false; + } + } + $entries = $dom->getElementsByTagName('entry'); + foreach ($entries as $entry) { + $name = $entry->getElementsByTagName('title')->item(0)->nodeValue; + // Google Docs resources don't always include extensions in title + if (!strpos($name, '.')) { + $extension = $this->getExtension($entry); + if ($extension != '') { + $name .= '.'.$extension; + } + } + $files[] = $name; + // Cache entry for future use + $this->entries[$name] = $entry; + } + } + OC_FakeDirStream::$dirs['google'] = $files; + return opendir('fakedir://google'); + } + + public function stat($path) { + if ($path == '' || $path == '/') { + $stat['size'] = $this->free_space($path); + $stat['atime'] = time(); + $stat['mtime'] = time(); + $stat['ctime'] = time(); + } else if ($entry = $this->getResource($path)) { + // NOTE: Native resources don't have a file size + $stat['size'] = $entry->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'quotaBytesUsed')->item(0)->nodeValue; +// if (isset($atime = $entry->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'lastViewed')->item(0)->nodeValue)) +// $stat['atime'] = strtotime($entry->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'lastViewed')->item(0)->nodeValue); + $stat['mtime'] = strtotime($entry->getElementsByTagName('updated')->item(0)->nodeValue); + $stat['ctime'] = strtotime($entry->getElementsByTagName('published')->item(0)->nodeValue); + } + if (isset($stat)) { + return $stat; + } + return false; + } + + public function filetype($path) { + if ($path == '' || $path == '/') { + return 'dir'; + } else if ($entry = $this->getResource($path)) { + $categories = $entry->getElementsByTagName('category'); + foreach ($categories as $category) { + if ($category->getAttribute('scheme') == 'http://schemas.google.com/g/2005#kind') { + $type = $category->getAttribute('label'); + if (strlen(strstr($type, 'folder')) > 0) { + return 'dir'; + } else { + return 'file'; + } + } + } + } + return false; + } + + public function is_readable($path) { + return true; + } + + public function is_writable($path) { + if ($path == '' || $path == '/') { + return true; + } else if ($entry = $this->getResource($path)) { + // Check if edit or edit-media links exist + $links = $entry->getElementsByTagName('link'); + foreach ($links as $link) { + if ($link->getAttribute('rel') == 'edit') { + return true; + } else if ($link->getAttribute('rel') == 'edit-media') { + return true; + } + } + } + return false; + } + + public function file_exists($path) { + if ($path == '' || $path == '/') { + return true; + } else if ($this->getResource($path)) { + return true; + } + return false; + } + + public function unlink($path) { + // Get resource self link to trash resource + if ($entry = $this->getResource($path)) { + $links = $entry->getElementsByTagName('link'); + foreach ($links as $link) { + if ($link->getAttribute('rel') == 'self') { + $feedUri = $link->getAttribute('href'); + } + } + } + if (isset($feedUri)) { + $this->sendRequest($feedUri, 'DELETE'); + return true; + } + return false; + } + + public function rename($path1, $path2) { + // TODO Add support for moving to different collections + // Get resource edit link to rename resource + if ($entry = $this->getResource($path1)) { + $etag = $entry->getElementsByTagName('entry')->item(0)->getAttribute('gd:etag'); + $links = $entry->getElementsByTagName('link'); + foreach ($links as $link) { + if ($link->getAttribute('rel') == 'edit') { + $feedUri = $link->getAttribute('href'); + } + } + } + if (isset($etag) && isset($feedUri)) { + $title = basename($path2); + // Construct post data + $postData = ''; + $postData .= ''; + $postData .= ''.$title.''; + $postData .= ''; + $this->sendRequest($feedUri, 'PUT', $postData); + return true; + } + return false; + } + + public function fopen($path, $mode) { + if ($entry = $this->getResource($path)) { + switch ($mode) { + case 'r': + case 'rb': + $extension = $this->getExtension($entry); + $downloadUri = $entry->getElementsByTagName('content')->item(0)->getAttribute('src'); + // TODO Non-native documents don't need these additional parameters + $downloadUri .= '&exportFormat='.$extension.'&format='.$extension; + $tmpFile = $this->sendRequest($downloadUri, 'GET', true); + return fopen($tmpFile, 'r'); + case 'w': + case 'wb': + case 'a': + case 'ab': + case 'r+': + case 'w+': + case 'wb+': + case 'a+': + case 'x': + case 'x+': + case 'c': + case 'c+': + // TODO Edit documents + } + + } + return false; + } + + public function getMimeType($path, $entry = null) { + // Entry can be passed, because extension is required for opendir and the entry can't be cached without the extension + if ($entry == null) { + if ($path == '' || $path == '/') { + return 'httpd/unix-directory'; + } else { + $entry = $this->getResource($path); + } + } + if ($entry) { + $mimetype = $entry->getElementsByTagName('content')->item(0)->getAttribute('type'); + // Native Google Docs resources often default to text/html, but it may be more useful to default to a corresponding ODF mimetype + // Collections get reported as application/atom+xml, make sure it actually is a folder and fix the mimetype + if ($mimetype == 'text/html' || $mimetype == 'application/atom+xml;type=feed') { + $categories = $entry->getElementsByTagName('category'); + foreach ($categories as $category) { + if ($category->getAttribute('scheme') == 'http://schemas.google.com/g/2005#kind') { + $type = $category->getAttribute('label'); + if (strlen(strstr($type, 'folder')) > 0) { + return 'httpd/unix-directory'; + } else if (strlen(strstr($type, 'document')) > 0) { + return 'application/vnd.oasis.opendocument.text'; + } else if (strlen(strstr($type, 'spreadsheet')) > 0) { + return 'application/vnd.oasis.opendocument.spreadsheet'; + } else if (strlen(strstr($type, 'presentation')) > 0) { + return 'application/vnd.oasis.opendocument.presentation'; + } else if (strlen(strstr($type, 'drawing')) > 0) { + return 'application/vnd.oasis.opendocument.graphics'; + } else { + // If nothing matches return text/html, all native Google Docs resources can be exported as text/html + return 'text/html'; + } + } + } + } + return $mimetype; + } + return false; + } + + public function free_space($path) { + if ($dom = $this->sendRequest('https://docs.google.com/feeds/metadata/default', 'GET')) { + // NOTE: Native Google Docs resources don't count towards quota + $total = $dom->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'quotaBytesTotal')->item(0)->nodeValue; + $used = $dom->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'quotaBytesUsed')->item(0)->nodeValue; + return $total - $used; + } + return false; + } + + public function touch($path, $mtime = null) { + + } + +} \ No newline at end of file diff --git a/apps/files_external/lib/webdav.php b/apps/files_external/lib/webdav.php new file mode 100644 index 00000000000..7a2da5c8ec0 --- /dev/null +++ b/apps/files_external/lib/webdav.php @@ -0,0 +1,293 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +class OC_FileStorage_DAV extends OC_Filestorage_Common{ + private $password; + private $user; + private $host; + private $secure; + private $root; + /** + * @var Sabre_DAV_Client + */ + private $client; + + private static $tempFiles=array(); + + public function __construct($params){ + $this->host=$params['host']; + $this->user=$params['user']; + $this->password=$params['password']; + $this->secure=isset($params['secure'])?(bool)$params['secure']:false; + $this->root=isset($params['root'])?$params['root']:'/'; + if(substr($this->root,0,1)!='/'){ + $this->root='/'.$this->root; + } + if(substr($this->root,-1,1)!='/'){ + $this->root.='/'; + } + + $settings = array( + 'baseUri' => $this->createBaseUri(), + 'userName' => $this->user, + 'password' => $this->password, + ); + $this->client = new Sabre_DAV_Client($settings); + + //create the root folder if necesary + $this->mkdir(''); + } + + private function createBaseUri(){ + $baseUri='http'; + if($this->secure){ + $baseUri.'s'; + } + $baseUri.='://'.$this->host.$this->root; + return $baseUri; + } + + public function mkdir($path){ + $path=$this->cleanPath($path); + return $this->simpleResponse('MKCOL',$path,null,201); + } + + public function rmdir($path){ + $path=$this->cleanPath($path); + return $this->simpleResponse('DELETE',$path,null,204); + } + + public function opendir($path){ + $path=$this->cleanPath($path); + try{ + $response=$this->client->propfind($path, array(),1); + $stripLength=strlen($this->root)+strlen($path); + $id=md5('webdav'.$this->root.$path); + OC_FakeDirStream::$dirs[$id]=array(); + foreach($response as $file=>$data){ + //strip root and path + $file=trim(substr($file,$stripLength)); + $file=trim($file,'/'); + if($file){ + OC_FakeDirStream::$dirs[$id][]=$file; + } + } + return opendir('fakedir://'.$id); + }catch(Exception $e){ + return false; + } + } + + public function filetype($path){ + $path=$this->cleanPath($path); + try{ + $response=$this->client->propfind($path, array('{DAV:}resourcetype')); + $responseType=$response["{DAV:}resourcetype"]->resourceType; + return (count($responseType)>0 and $responseType[0]=="{DAV:}collection")?'dir':'file'; + }catch(Exception $e){ + return false; + } + } + + public function is_readable($path){ + return true;//not properly supported + } + + public function is_writable($path){ + return true;//not properly supported + } + + public function file_exists($path){ + $path=$this->cleanPath($path); + try{ + $response=$this->client->propfind($path, array('{DAV:}resourcetype')); + return true;//no 404 exception + }catch(Exception $e){ + return false; + } + } + + public function unlink($path){ + return $this->simpleResponse('DELETE',$path,null,204); + } + + public function fopen($path,$mode){ + $path=$this->cleanPath($path); + switch($mode){ + case 'r': + case 'rb': + //straight up curl instead of sabredav here, sabredav put's the entire get result in memory + $curl = curl_init(); + $fp = fopen('php://temp', 'r+'); + curl_setopt($curl,CURLOPT_USERPWD,$this->user.':'.$this->password); + curl_setopt($curl, CURLOPT_URL, $this->createBaseUri().$path); + curl_setopt($curl, CURLOPT_FILE, $fp); + + curl_exec ($curl); + curl_close ($curl); + 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+': + //emulate these + 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)){ + $this->getFile($path,$tmpFile); + } + self::$tempFiles[$tmpFile]=$path; + return fopen('close://'.$tmpFile,$mode); + } + } + + public function writeBack($tmpFile){ + if(isset(self::$tempFiles[$tmpFile])){ + $this->uploadFile($tmpFile,self::$tempFiles[$tmpFile]); + unlink($tmpFile); + } + } + + public function free_space($path){ + $path=$this->cleanPath($path); + try{ + $response=$this->client->propfind($path, array('{DAV:}quota-available-bytes')); + if(isset($response['{DAV:}quota-available-bytes'])){ + return (int)$response['{DAV:}quota-available-bytes']; + }else{ + return 0; + } + }catch(Exception $e){ + return 0; + } + } + + public function touch($path,$mtime=null){ + if(is_null($mtime)){ + $mtime=time(); + } + $path=$this->cleanPath($path); + $this->client->proppatch($path, array('{DAV:}lastmodified' => $mtime,)); + } + + public function getFile($path,$target){ + $source=$this->fopen($path,'r'); + file_put_contents($target,$source); + } + + public function uploadFile($path,$target){ + $source=fopen($path,'r'); + + $curl = curl_init(); + curl_setopt($curl,CURLOPT_USERPWD,$this->user.':'.$this->password); + curl_setopt($curl, CURLOPT_URL, $this->createBaseUri().$target); + curl_setopt($curl, CURLOPT_BINARYTRANSFER, true); + curl_setopt($curl, CURLOPT_INFILE, $source); // file pointer + curl_setopt($curl, CURLOPT_INFILESIZE, filesize($path)); + curl_setopt($curl, CURLOPT_PUT, true); + curl_exec ($curl); + curl_close ($curl); + } + + public function rename($path1,$path2){ + $path1=$this->cleanPath($path1); + $path2=$this->root.$this->cleanPath($path2); + try{ + $response=$this->client->request('MOVE',$path1,null,array('Destination'=>$path2)); + return true; + }catch(Exception $e){ + echo $e; + echo 'fail'; + var_dump($response); + return false; + } + } + + public function copy($path1,$path2){ + $path1=$this->cleanPath($path1); + $path2=$this->root.$this->cleanPath($path2); + try{ + $response=$this->client->request('COPY',$path1,null,array('Destination'=>$path2)); + return true; + }catch(Exception $e){ + echo $e; + echo 'fail'; + var_dump($response); + return false; + } + } + + public function stat($path){ + $path=$this->cleanPath($path); + try{ + $response=$this->client->propfind($path, array('{DAV:}getlastmodified','{DAV:}getcontentlength')); + if(isset($response['{DAV:}getlastmodified']) and isset($response['{DAV:}getcontentlength'])){ + return array( + 'mtime'=>strtotime($response['{DAV:}getlastmodified']), + 'size'=>(int)$response['{DAV:}getcontentlength'], + 'ctime'=>-1, + ); + }else{ + return array(); + } + }catch(Exception $e){ + return array(); + } + } + + public function getMimeType($path){ + $path=$this->cleanPath($path); + try{ + $response=$this->client->propfind($path, array('{DAV:}getcontenttype','{DAV:}resourcetype')); + $responseType=$response["{DAV:}resourcetype"]->resourceType; + $type=(count($responseType)>0 and $responseType[0]=="{DAV:}collection")?'dir':'file'; + if($type=='dir'){ + return 'httpd/unix-directory'; + }elseif(isset($response['{DAV:}getcontenttype'])){ + return $response['{DAV:}getcontenttype']; + }else{ + return false; + } + }catch(Exception $e){ + return false; + } + } + + private function cleanPath($path){ + if(substr($path,0,1)=='/'){ + return substr($path,1); + }else{ + return $path; + } + } + + private function simpleResponse($method,$path,$body,$expected){ + $path=$this->cleanPath($path); + try{ + $response=$this->client->request($method,$path,$body); + return $response['statusCode']==$expected; + }catch(Exception $e){ + return false; + } + } +} + diff --git a/apps/files_external/tests/config.php b/apps/files_external/tests/config.php new file mode 100644 index 00000000000..9b40d2b98cf --- /dev/null +++ b/apps/files_external/tests/config.php @@ -0,0 +1,22 @@ +array( + 'host'=>'localhost', + 'user'=>'test', + 'password'=>'test', + 'root'=>'/test', + ), + 'webdav'=>array( + 'host'=>'localhost', + 'user'=>'test', + 'password'=>'test', + 'root'=>'/owncloud/files/webdav.php', + ), + 'google'=>array( + 'consumer_key'=>'anonymous', + 'consumer_secret'=>'anonymous', + 'token'=>'test', + 'token_secret'=>'test', + 'root'=>'/google', + ) +); diff --git a/apps/files_external/tests/ftp.php b/apps/files_external/tests/ftp.php new file mode 100644 index 00000000000..aa565751ba3 --- /dev/null +++ b/apps/files_external/tests/ftp.php @@ -0,0 +1,23 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +class Test_Filestorage_FTP extends Test_FileStorage { + private $config; + private $id; + + public function setUp(){ + $id=uniqid(); + $this->config=include('apps/files_external/tests/config.php'); + $this->config['ftp']['root'].='/'.$id;//make sure we have an new empty folder to work in + $this->instance=new OC_Filestorage_FTP($this->config['ftp']); + } + + public function tearDown(){ + OC_Helper::rmdirr($this->instance->constructUrl('')); + } +} diff --git a/apps/files_external/tests/google.php b/apps/files_external/tests/google.php new file mode 100644 index 00000000000..1c028945228 --- /dev/null +++ b/apps/files_external/tests/google.php @@ -0,0 +1,38 @@ +. +*/ + +class Test_Filestorage_Google extends Test_FileStorage { + + private $config; + private $id; + + public function setUp(){ + $id=uniqid(); + $this->config=include('apps/files_external/tests/config.php'); + $this->config['google']['root'].='/'.$id;//make sure we have an new empty folder to work in + $this->instance=new OC_Filestorage_Google($this->config['google']); + } + + public function tearDown(){ + $this->instance->rmdir('/'); + } +} diff --git a/apps/files_external/tests/webdav.php b/apps/files_external/tests/webdav.php new file mode 100644 index 00000000000..51799290540 --- /dev/null +++ b/apps/files_external/tests/webdav.php @@ -0,0 +1,23 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +class Test_Filestorage_DAV extends Test_FileStorage { + private $config; + private $id; + + public function setUp(){ + $id=uniqid(); + $this->config=include('apps/files_external/tests/config.php'); + $this->config['webdav']['root'].='/'.$id;//make sure we have an new empty folder to work in + $this->instance=new OC_Filestorage_DAV($this->config['webdav']); + } + + public function tearDown(){ + $this->instance->rmdir('/'); + } +} diff --git a/apps/files_remote/appinfo/app.php b/apps/files_remote/appinfo/app.php deleted file mode 100644 index 02c1c3ae313..00000000000 --- a/apps/files_remote/appinfo/app.php +++ /dev/null @@ -1,11 +0,0 @@ - - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - */ - -OC::$CLASSPATH['OC_Filestorage_FTP']='apps/files_remote/lib/ftp.php'; -OC::$CLASSPATH['OC_Filestorage_DAV']='apps/files_remote/lib/webdav.php'; -OC::$CLASSPATH['OC_Filestorage_Google']='apps/files_remote/lib/google.php'; diff --git a/apps/files_remote/appinfo/info.xml b/apps/files_remote/appinfo/info.xml deleted file mode 100644 index 8cf66ddbc37..00000000000 --- a/apps/files_remote/appinfo/info.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - files_remote - Remote storage support - Mount remote storage sources - 0.1 - AGPL - Robin Appelman - 3 - - - - diff --git a/apps/files_remote/lib/ftp.php b/apps/files_remote/lib/ftp.php deleted file mode 100644 index 802446b4fd8..00000000000 --- a/apps/files_remote/lib/ftp.php +++ /dev/null @@ -1,157 +0,0 @@ - - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - */ - -class OC_FileStorage_FTP extends OC_Filestorage_Common{ - private $password; - private $user; - private $host; - private $secure; - private $root; - - private static $tempFiles=array(); - - public function __construct($params){ - $this->host=$params['host']; - $this->user=$params['user']; - $this->password=$params['password']; - $this->secure=isset($params['secure'])?(bool)$params['secure']:false; - $this->root=isset($params['root'])?$params['root']:'/'; - if(substr($this->root,0,1)!='/'){ - $this->root='/'.$this->root; - } - - //create the root folder if necesary - mkdir($this->constructUrl('')); - } - - /** - * construct the ftp url - * @param string path - * @return string - */ - public function constructUrl($path){ - $url='ftp'; - if($this->secure){ - $url.='s'; - } - $url.='://'.$this->user.':'.$this->password.'@'.$this->host.$this->root.$path; - return $url; - } - - public function mkdir($path){ - return mkdir($this->constructUrl($path)); - } - - public function rmdir($path){ - if($this->file_exists($path)){ - $succes=rmdir($this->constructUrl($path)); - clearstatcache(); - return $succes; - }else{ - return false; - } - } - - public function opendir($path){ - return opendir($this->constructUrl($path)); - } - - public function filetype($path){ - return filetype($this->constructUrl($path)); - } - - public function is_readable($path){ - return true;//not properly supported - } - - public function is_writable($path){ - return true;//not properly supported - } - - public function file_exists($path){ - return file_exists($this->constructUrl($path)); - } - - public function unlink($path){ - $succes=unlink($this->constructUrl($path)); - clearstatcache(); - return $succes; - } - - public function fopen($path,$mode){ - switch($mode){ - case 'r': - case 'rb': - case 'w': - case 'wb': - case 'a': - case 'ab': - //these are supported by the wrapper - $context = stream_context_create(array('ftp' => array('overwrite' => true))); - return fopen($this->constructUrl($path),$mode,false,$context); - case 'r+': - case 'w+': - case 'wb+': - case 'a+': - case 'x': - case 'x+': - case 'c': - case 'c+': - //emulate these - 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)){ - $this->getFile($path,$tmpFile); - } - self::$tempFiles[$tmpFile]=$path; - return fopen('close://'.$tmpFile,$mode); - } - } - - public function writeBack($tmpFile){ - if(isset(self::$tempFiles[$tmpFile])){ - $this->uploadFile($tmpFile,self::$tempFiles[$tmpFile]); - unlink($tmpFile); - } - } - - public function free_space($path){ - return 0; - } - - public function touch($path,$mtime=null){ - if(is_null($mtime)){ - $fh=$this->fopen($path,'a'); - fwrite($fh,''); - fclose($fh); - }else{ - return false;//not supported - } - } - - public function getFile($path,$target){ - return copy($this->constructUrl($path),$target); - } - - public function uploadFile($path,$target){ - return copy($path,$this->constructUrl($target)); - } - - public function rename($path1,$path2){ - return rename($this->constructUrl($path1),$this->constructUrl($path2)); - } - - public function stat($path){ - return stat($this->constructUrl($path)); - } -} diff --git a/apps/files_remote/lib/google.php b/apps/files_remote/lib/google.php deleted file mode 100644 index 0d6db1987f8..00000000000 --- a/apps/files_remote/lib/google.php +++ /dev/null @@ -1,409 +0,0 @@ -. -*/ - -require_once 'common.inc.php'; - -class OC_Filestorage_Google extends OC_Filestorage_Common { - - private $consumer; - private $oauth_token; - private $sig_method; - private $entries; - - public function __construct($arguments) { - $consumer_key = isset($arguments['consumer_key']) ? $arguments['consumer_key'] : 'anonymous'; - $consumer_secret = isset($arguments['consumer_secret']) ? $arguments['consumer_secret'] : 'anonymous'; - $this->consumer = new OAuthConsumer($consumer_key, $consumer_secret); - $this->oauth_token = new OAuthToken($arguments['token'], $arguments['token_secret']); - $this->sig_method = new OAuthSignatureMethod_HMAC_SHA1(); - $this->entries = array(); - } - - private function sendRequest($feedUri, $http_method, $isDownload = false, $postData = null) { - $feedUri = trim($feedUri); - // create an associative array from each key/value url query param pair. - $params = array(); - $pieces = explode('?', $feedUri); - if (isset($pieces[1])) { - $params = explode_assoc('=', '&', $pieces[1]); - } - // urlencode each url parameter key/value pair - $tempStr = $pieces[0]; - foreach ($params as $key => $value) { - $tempStr .= '&' . urlencode($key) . '=' . urlencode($value); - } - $feedUri = preg_replace('/&/', '?', $tempStr, 1); - $request = OAuthRequest::from_consumer_and_token($this->consumer, $this->oauth_token, $http_method, $feedUri, $params); - $request->sign_request($this->sig_method, $this->consumer, $this->oauth_token); - $auth_header = $request->to_header(); - $headers = array($auth_header, 'Content-Type: application/atom+xml', 'GData-Version: 3.0'); - $curl = curl_init($feedUri); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - curl_setopt($curl, CURLOPT_FAILONERROR, false); - curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); - switch ($http_method) { - case 'GET': - curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); - break; - case 'POST': - curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); - curl_setopt($curl, CURLOPT_POST, 1); - curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); - break; - case 'PUT': - $headers[] = 'If-Match: *'; - curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); - curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $http_method); - curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); - break; - case 'DELETE': - $headers[] = 'If-Match: *'; - curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); - curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $http_method); - break; - default: - curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); - } - if ($isDownload) { - $tmpFile = OC_Helper::tmpFile(); - $fp = fopen($tmpFile, 'w'); - curl_setopt($curl, CURLOPT_FILE, $fp); - curl_exec($curl); - curl_close($curl); - return $tmpFile; - } - $result = curl_exec($curl); - curl_close($curl); - $dom = new DOMDocument(); - $dom->loadXML($result); - return $dom; - } - - private function getResource($path) { - $file = basename($path); - if (array_key_exists($file, $this->entries)) { - return $this->entries[$file]; - } else { - // Strip the file extension; file could be a native Google Docs resource - if ($pos = strpos($file, '.')) { - $title = substr($file, 0, $pos); - $dom = $this->sendRequest('https://docs.google.com/feeds/default/private/full?showfolders=true&title='.$title, 'GET'); - // Check if request was successful and entry exists - if ($dom && $entry = $dom->getElementsByTagName('entry')->item(0)) { - $this->entries[$file] = $entry; - return $entry; - } - } - $dom = $this->sendRequest('https://docs.google.com/feeds/default/private/full?showfolders=true&title='.$file, 'GET'); - // Check if request was successful and entry exists - if ($dom && $entry = $dom->getElementsByTagName('entry')->item(0)) { - $this->entries[$file] = $entry; - return $entry; - } - return false; - } - } - - private function getExtension($entry) { - $mimetype = $this->getMimeType('', $entry); - switch ($mimetype) { - case 'httpd/unix-directory': - return ''; - case 'application/vnd.oasis.opendocument.text': - return 'odt'; - case 'application/vnd.oasis.opendocument.spreadsheet': - return 'ods'; - case 'application/vnd.oasis.opendocument.presentation': - return 'pptx'; - case 'text/html': - return 'html'; - default: - return 'html'; - } - } - - - public function mkdir($path) { - $dir = dirname($path); - // Check if path parent is root directory - if ($dir == '/' || $dir == '\.' || $dir == '.') { - $feedUri = 'https://docs.google.com/feeds/default/private/full'; - // Get parent content link - } else if ($dom = $this->getResource(basename($dir))) { - $feedUri = $dom->getElementsByTagName('content')->item(0)->getAttribute('src'); - } - if (isset($feedUri)) { - $title = basename($path); - // Construct post data - $postData = ''; - $postData .= ''; - $postData .= ''; - $postData .= ''.$title.''; - $postData .= ''; - if ($dom = $this->sendRequest($feedUri, 'POST', $postData)) { - return true; - } - } - return false; - } - - public function rmdir($path) { - return $this->unlink($path); - } - - public function opendir($path) { - if ($path == '' || $path == '/') { - $next = 'https://docs.google.com/feeds/default/private/full/folder%3Aroot/contents'; - } else { - if ($entry = $this->getResource($path)) { - $next = $entry->getElementsByTagName('content')->item(0)->getAttribute('src'); - } else { - return false; - } - } - $files = array(); - while ($next) { - $dom = $this->sendRequest($next, 'GET'); - $links = $dom->getElementsByTagName('link'); - foreach ($links as $link) { - if ($link->getAttribute('rel') == 'next') { - $next = $link->getAttribute('src'); - break; - } else { - $next = false; - } - } - $entries = $dom->getElementsByTagName('entry'); - foreach ($entries as $entry) { - $name = $entry->getElementsByTagName('title')->item(0)->nodeValue; - // Google Docs resources don't always include extensions in title - if (!strpos($name, '.')) { - $extension = $this->getExtension($entry); - if ($extension != '') { - $name .= '.'.$extension; - } - } - $files[] = $name; - // Cache entry for future use - $this->entries[$name] = $entry; - } - } - OC_FakeDirStream::$dirs['google'] = $files; - return opendir('fakedir://google'); - } - - public function stat($path) { - if ($path == '' || $path == '/') { - $stat['size'] = $this->free_space($path); - $stat['atime'] = time(); - $stat['mtime'] = time(); - $stat['ctime'] = time(); - } else if ($entry = $this->getResource($path)) { - // NOTE: Native resources don't have a file size - $stat['size'] = $entry->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'quotaBytesUsed')->item(0)->nodeValue; -// if (isset($atime = $entry->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'lastViewed')->item(0)->nodeValue)) -// $stat['atime'] = strtotime($entry->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'lastViewed')->item(0)->nodeValue); - $stat['mtime'] = strtotime($entry->getElementsByTagName('updated')->item(0)->nodeValue); - $stat['ctime'] = strtotime($entry->getElementsByTagName('published')->item(0)->nodeValue); - } - if (isset($stat)) { - return $stat; - } - return false; - } - - public function filetype($path) { - if ($path == '' || $path == '/') { - return 'dir'; - } else if ($entry = $this->getResource($path)) { - $categories = $entry->getElementsByTagName('category'); - foreach ($categories as $category) { - if ($category->getAttribute('scheme') == 'http://schemas.google.com/g/2005#kind') { - $type = $category->getAttribute('label'); - if (strlen(strstr($type, 'folder')) > 0) { - return 'dir'; - } else { - return 'file'; - } - } - } - } - return false; - } - - public function is_readable($path) { - return true; - } - - public function is_writable($path) { - if ($path == '' || $path == '/') { - return true; - } else if ($entry = $this->getResource($path)) { - // Check if edit or edit-media links exist - $links = $entry->getElementsByTagName('link'); - foreach ($links as $link) { - if ($link->getAttribute('rel') == 'edit') { - return true; - } else if ($link->getAttribute('rel') == 'edit-media') { - return true; - } - } - } - return false; - } - - public function file_exists($path) { - if ($path == '' || $path == '/') { - return true; - } else if ($this->getResource($path)) { - return true; - } - return false; - } - - public function unlink($path) { - // Get resource self link to trash resource - if ($entry = $this->getResource($path)) { - $links = $entry->getElementsByTagName('link'); - foreach ($links as $link) { - if ($link->getAttribute('rel') == 'self') { - $feedUri = $link->getAttribute('href'); - } - } - } - if (isset($feedUri)) { - $this->sendRequest($feedUri, 'DELETE'); - return true; - } - return false; - } - - public function rename($path1, $path2) { - // TODO Add support for moving to different collections - // Get resource edit link to rename resource - if ($entry = $this->getResource($path1)) { - $etag = $entry->getElementsByTagName('entry')->item(0)->getAttribute('gd:etag'); - $links = $entry->getElementsByTagName('link'); - foreach ($links as $link) { - if ($link->getAttribute('rel') == 'edit') { - $feedUri = $link->getAttribute('href'); - } - } - } - if (isset($etag) && isset($feedUri)) { - $title = basename($path2); - // Construct post data - $postData = ''; - $postData .= ''; - $postData .= ''.$title.''; - $postData .= ''; - $this->sendRequest($feedUri, 'PUT', $postData); - return true; - } - return false; - } - - public function fopen($path, $mode) { - if ($entry = $this->getResource($path)) { - switch ($mode) { - case 'r': - case 'rb': - $extension = $this->getExtension($entry); - $downloadUri = $entry->getElementsByTagName('content')->item(0)->getAttribute('src'); - // TODO Non-native documents don't need these additional parameters - $downloadUri .= '&exportFormat='.$extension.'&format='.$extension; - $tmpFile = $this->sendRequest($downloadUri, 'GET', true); - return fopen($tmpFile, 'r'); - case 'w': - case 'wb': - case 'a': - case 'ab': - case 'r+': - case 'w+': - case 'wb+': - case 'a+': - case 'x': - case 'x+': - case 'c': - case 'c+': - // TODO Edit documents - } - - } - return false; - } - - public function getMimeType($path, $entry = null) { - // Entry can be passed, because extension is required for opendir and the entry can't be cached without the extension - if ($entry == null) { - if ($path == '' || $path == '/') { - return 'httpd/unix-directory'; - } else { - $entry = $this->getResource($path); - } - } - if ($entry) { - $mimetype = $entry->getElementsByTagName('content')->item(0)->getAttribute('type'); - // Native Google Docs resources often default to text/html, but it may be more useful to default to a corresponding ODF mimetype - // Collections get reported as application/atom+xml, make sure it actually is a folder and fix the mimetype - if ($mimetype == 'text/html' || $mimetype == 'application/atom+xml;type=feed') { - $categories = $entry->getElementsByTagName('category'); - foreach ($categories as $category) { - if ($category->getAttribute('scheme') == 'http://schemas.google.com/g/2005#kind') { - $type = $category->getAttribute('label'); - if (strlen(strstr($type, 'folder')) > 0) { - return 'httpd/unix-directory'; - } else if (strlen(strstr($type, 'document')) > 0) { - return 'application/vnd.oasis.opendocument.text'; - } else if (strlen(strstr($type, 'spreadsheet')) > 0) { - return 'application/vnd.oasis.opendocument.spreadsheet'; - } else if (strlen(strstr($type, 'presentation')) > 0) { - return 'application/vnd.oasis.opendocument.presentation'; - } else if (strlen(strstr($type, 'drawing')) > 0) { - return 'application/vnd.oasis.opendocument.graphics'; - } else { - // If nothing matches return text/html, all native Google Docs resources can be exported as text/html - return 'text/html'; - } - } - } - } - return $mimetype; - } - return false; - } - - public function free_space($path) { - if ($dom = $this->sendRequest('https://docs.google.com/feeds/metadata/default', 'GET')) { - // NOTE: Native Google Docs resources don't count towards quota - $total = $dom->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'quotaBytesTotal')->item(0)->nodeValue; - $used = $dom->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'quotaBytesUsed')->item(0)->nodeValue; - return $total - $used; - } - return false; - } - - public function touch($path, $mtime = null) { - - } - -} \ No newline at end of file diff --git a/apps/files_remote/lib/webdav.php b/apps/files_remote/lib/webdav.php deleted file mode 100644 index 7a2da5c8ec0..00000000000 --- a/apps/files_remote/lib/webdav.php +++ /dev/null @@ -1,293 +0,0 @@ - - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - */ - -class OC_FileStorage_DAV extends OC_Filestorage_Common{ - private $password; - private $user; - private $host; - private $secure; - private $root; - /** - * @var Sabre_DAV_Client - */ - private $client; - - private static $tempFiles=array(); - - public function __construct($params){ - $this->host=$params['host']; - $this->user=$params['user']; - $this->password=$params['password']; - $this->secure=isset($params['secure'])?(bool)$params['secure']:false; - $this->root=isset($params['root'])?$params['root']:'/'; - if(substr($this->root,0,1)!='/'){ - $this->root='/'.$this->root; - } - if(substr($this->root,-1,1)!='/'){ - $this->root.='/'; - } - - $settings = array( - 'baseUri' => $this->createBaseUri(), - 'userName' => $this->user, - 'password' => $this->password, - ); - $this->client = new Sabre_DAV_Client($settings); - - //create the root folder if necesary - $this->mkdir(''); - } - - private function createBaseUri(){ - $baseUri='http'; - if($this->secure){ - $baseUri.'s'; - } - $baseUri.='://'.$this->host.$this->root; - return $baseUri; - } - - public function mkdir($path){ - $path=$this->cleanPath($path); - return $this->simpleResponse('MKCOL',$path,null,201); - } - - public function rmdir($path){ - $path=$this->cleanPath($path); - return $this->simpleResponse('DELETE',$path,null,204); - } - - public function opendir($path){ - $path=$this->cleanPath($path); - try{ - $response=$this->client->propfind($path, array(),1); - $stripLength=strlen($this->root)+strlen($path); - $id=md5('webdav'.$this->root.$path); - OC_FakeDirStream::$dirs[$id]=array(); - foreach($response as $file=>$data){ - //strip root and path - $file=trim(substr($file,$stripLength)); - $file=trim($file,'/'); - if($file){ - OC_FakeDirStream::$dirs[$id][]=$file; - } - } - return opendir('fakedir://'.$id); - }catch(Exception $e){ - return false; - } - } - - public function filetype($path){ - $path=$this->cleanPath($path); - try{ - $response=$this->client->propfind($path, array('{DAV:}resourcetype')); - $responseType=$response["{DAV:}resourcetype"]->resourceType; - return (count($responseType)>0 and $responseType[0]=="{DAV:}collection")?'dir':'file'; - }catch(Exception $e){ - return false; - } - } - - public function is_readable($path){ - return true;//not properly supported - } - - public function is_writable($path){ - return true;//not properly supported - } - - public function file_exists($path){ - $path=$this->cleanPath($path); - try{ - $response=$this->client->propfind($path, array('{DAV:}resourcetype')); - return true;//no 404 exception - }catch(Exception $e){ - return false; - } - } - - public function unlink($path){ - return $this->simpleResponse('DELETE',$path,null,204); - } - - public function fopen($path,$mode){ - $path=$this->cleanPath($path); - switch($mode){ - case 'r': - case 'rb': - //straight up curl instead of sabredav here, sabredav put's the entire get result in memory - $curl = curl_init(); - $fp = fopen('php://temp', 'r+'); - curl_setopt($curl,CURLOPT_USERPWD,$this->user.':'.$this->password); - curl_setopt($curl, CURLOPT_URL, $this->createBaseUri().$path); - curl_setopt($curl, CURLOPT_FILE, $fp); - - curl_exec ($curl); - curl_close ($curl); - 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+': - //emulate these - 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)){ - $this->getFile($path,$tmpFile); - } - self::$tempFiles[$tmpFile]=$path; - return fopen('close://'.$tmpFile,$mode); - } - } - - public function writeBack($tmpFile){ - if(isset(self::$tempFiles[$tmpFile])){ - $this->uploadFile($tmpFile,self::$tempFiles[$tmpFile]); - unlink($tmpFile); - } - } - - public function free_space($path){ - $path=$this->cleanPath($path); - try{ - $response=$this->client->propfind($path, array('{DAV:}quota-available-bytes')); - if(isset($response['{DAV:}quota-available-bytes'])){ - return (int)$response['{DAV:}quota-available-bytes']; - }else{ - return 0; - } - }catch(Exception $e){ - return 0; - } - } - - public function touch($path,$mtime=null){ - if(is_null($mtime)){ - $mtime=time(); - } - $path=$this->cleanPath($path); - $this->client->proppatch($path, array('{DAV:}lastmodified' => $mtime,)); - } - - public function getFile($path,$target){ - $source=$this->fopen($path,'r'); - file_put_contents($target,$source); - } - - public function uploadFile($path,$target){ - $source=fopen($path,'r'); - - $curl = curl_init(); - curl_setopt($curl,CURLOPT_USERPWD,$this->user.':'.$this->password); - curl_setopt($curl, CURLOPT_URL, $this->createBaseUri().$target); - curl_setopt($curl, CURLOPT_BINARYTRANSFER, true); - curl_setopt($curl, CURLOPT_INFILE, $source); // file pointer - curl_setopt($curl, CURLOPT_INFILESIZE, filesize($path)); - curl_setopt($curl, CURLOPT_PUT, true); - curl_exec ($curl); - curl_close ($curl); - } - - public function rename($path1,$path2){ - $path1=$this->cleanPath($path1); - $path2=$this->root.$this->cleanPath($path2); - try{ - $response=$this->client->request('MOVE',$path1,null,array('Destination'=>$path2)); - return true; - }catch(Exception $e){ - echo $e; - echo 'fail'; - var_dump($response); - return false; - } - } - - public function copy($path1,$path2){ - $path1=$this->cleanPath($path1); - $path2=$this->root.$this->cleanPath($path2); - try{ - $response=$this->client->request('COPY',$path1,null,array('Destination'=>$path2)); - return true; - }catch(Exception $e){ - echo $e; - echo 'fail'; - var_dump($response); - return false; - } - } - - public function stat($path){ - $path=$this->cleanPath($path); - try{ - $response=$this->client->propfind($path, array('{DAV:}getlastmodified','{DAV:}getcontentlength')); - if(isset($response['{DAV:}getlastmodified']) and isset($response['{DAV:}getcontentlength'])){ - return array( - 'mtime'=>strtotime($response['{DAV:}getlastmodified']), - 'size'=>(int)$response['{DAV:}getcontentlength'], - 'ctime'=>-1, - ); - }else{ - return array(); - } - }catch(Exception $e){ - return array(); - } - } - - public function getMimeType($path){ - $path=$this->cleanPath($path); - try{ - $response=$this->client->propfind($path, array('{DAV:}getcontenttype','{DAV:}resourcetype')); - $responseType=$response["{DAV:}resourcetype"]->resourceType; - $type=(count($responseType)>0 and $responseType[0]=="{DAV:}collection")?'dir':'file'; - if($type=='dir'){ - return 'httpd/unix-directory'; - }elseif(isset($response['{DAV:}getcontenttype'])){ - return $response['{DAV:}getcontenttype']; - }else{ - return false; - } - }catch(Exception $e){ - return false; - } - } - - private function cleanPath($path){ - if(substr($path,0,1)=='/'){ - return substr($path,1); - }else{ - return $path; - } - } - - private function simpleResponse($method,$path,$body,$expected){ - $path=$this->cleanPath($path); - try{ - $response=$this->client->request($method,$path,$body); - return $response['statusCode']==$expected; - }catch(Exception $e){ - return false; - } - } -} - diff --git a/apps/files_remote/tests/config.php b/apps/files_remote/tests/config.php deleted file mode 100644 index 9b40d2b98cf..00000000000 --- a/apps/files_remote/tests/config.php +++ /dev/null @@ -1,22 +0,0 @@ -array( - 'host'=>'localhost', - 'user'=>'test', - 'password'=>'test', - 'root'=>'/test', - ), - 'webdav'=>array( - 'host'=>'localhost', - 'user'=>'test', - 'password'=>'test', - 'root'=>'/owncloud/files/webdav.php', - ), - 'google'=>array( - 'consumer_key'=>'anonymous', - 'consumer_secret'=>'anonymous', - 'token'=>'test', - 'token_secret'=>'test', - 'root'=>'/google', - ) -); diff --git a/apps/files_remote/tests/ftp.php b/apps/files_remote/tests/ftp.php deleted file mode 100644 index 03633b7c0d1..00000000000 --- a/apps/files_remote/tests/ftp.php +++ /dev/null @@ -1,23 +0,0 @@ - - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - */ - -class Test_Filestorage_FTP extends Test_FileStorage { - private $config; - private $id; - - public function setUp(){ - $id=uniqid(); - $this->config=include('apps/files_remote/tests/config.php'); - $this->config['ftp']['root'].='/'.$id;//make sure we have an new empty folder to work in - $this->instance=new OC_Filestorage_FTP($this->config['ftp']); - } - - public function tearDown(){ - OC_Helper::rmdirr($this->instance->constructUrl('')); - } -} diff --git a/apps/files_remote/tests/google.php b/apps/files_remote/tests/google.php deleted file mode 100644 index b49f9e4647c..00000000000 --- a/apps/files_remote/tests/google.php +++ /dev/null @@ -1,38 +0,0 @@ -. -*/ - -class Test_Filestorage_Google extends Test_FileStorage { - - private $config; - private $id; - - public function setUp(){ - $id=uniqid(); - $this->config=include('apps/files_remote/tests/config.php'); - $this->config['google']['root'].='/'.$id;//make sure we have an new empty folder to work in - $this->instance=new OC_Filestorage_Google($this->config['google']); - } - - public function tearDown(){ - $this->instance->rmdir('/'); - } -} \ No newline at end of file diff --git a/apps/files_remote/tests/webdav.php b/apps/files_remote/tests/webdav.php deleted file mode 100644 index 219fff8852d..00000000000 --- a/apps/files_remote/tests/webdav.php +++ /dev/null @@ -1,23 +0,0 @@ - - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - */ - -class Test_Filestorage_DAV extends Test_FileStorage { - private $config; - private $id; - - public function setUp(){ - $id=uniqid(); - $this->config=include('apps/files_remote/tests/config.php'); - $this->config['webdav']['root'].='/'.$id;//make sure we have an new empty folder to work in - $this->instance=new OC_Filestorage_DAV($this->config['webdav']); - } - - public function tearDown(){ - $this->instance->rmdir('/'); - } -}