summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMichael Gapczynski <GapczynskiM@gmail.com>2011-07-24 16:08:39 -0400
committerMichael Gapczynski <GapczynskiM@gmail.com>2011-07-24 16:08:39 -0400
commit415ae8e40a5473aa03aeaea7f5516ebc8a79c63b (patch)
treeff9a708725a12ae5bd3cb20f2c664399e48c5e8d /lib
parent5148eb9121e3d19211629ea29ac3ebf70b111ef6 (diff)
parent3097e4f48a5490de6e55a21b9ee66b2a7b4ae26d (diff)
downloadnextcloud-server-415ae8e40a5473aa03aeaea7f5516ebc8a79c63b.tar.gz
nextcloud-server-415ae8e40a5473aa03aeaea7f5516ebc8a79c63b.zip
Merge branch 'master' into sharing
Diffstat (limited to 'lib')
-rw-r--r--lib/Connector/Sabre/auth.php35
-rw-r--r--lib/Connector/Sabre/directory.php131
-rw-r--r--lib/Connector/Sabre/file.php89
-rw-r--r--lib/Connector/Sabre/locks.php154
-rw-r--r--lib/Connector/Sabre/node.php161
-rw-r--r--lib/HTTP/WebDAV/Server/Filesystem.php757
6 files changed, 570 insertions, 757 deletions
diff --git a/lib/Connector/Sabre/auth.php b/lib/Connector/Sabre/auth.php
new file mode 100644
index 00000000000..cfe7723e761
--- /dev/null
+++ b/lib/Connector/Sabre/auth.php
@@ -0,0 +1,35 @@
+<?php
+require_once("lib/base.php");
+/**
+ * HTTP Basic authentication backend class
+ *
+ * This class can be used by authentication objects wishing to use HTTP Basic
+ * Most of the digest logic is handled, implementors just need to worry about
+ * the validateUserPass method.
+ *
+ * @package Sabre
+ * @subpackage DAV
+ * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @author James David Low (http://jameslow.com/)
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class OC_Connector_Sabre_Auth extends Sabre_DAV_Auth_Backend_AbstractBasic {
+ /**
+ * Validates a username and password
+ *
+ * This method should return true or false depending on if login
+ * succeeded.
+ *
+ * @return bool
+ */
+ protected function validateUserPass($username, $password){
+ if(OC_USER::login($username,$password)){
+ OC_UTIL::setUpFS();
+ return true;
+ }
+ else{
+ return false;
+ }
+ }
+}
diff --git a/lib/Connector/Sabre/directory.php b/lib/Connector/Sabre/directory.php
new file mode 100644
index 00000000000..d0ff87f9b1a
--- /dev/null
+++ b/lib/Connector/Sabre/directory.php
@@ -0,0 +1,131 @@
+<?php
+
+require_once("lib/base.php");
+
+/**
+ * Directory class
+ *
+ * @package Sabre
+ * @subpackage DAV
+ * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sabre_DAV_ICollection, Sabre_DAV_IQuota {
+
+ /**
+ * Creates a new file in the directory
+ *
+ * data is a readable stream resource
+ *
+ * @param string $name Name of the file
+ * @param resource $data Initial payload
+ * @return void
+ */
+ public function createFile($name, $data = null) {
+
+ $newPath = $this->path . '/' . $name;
+ OC_FILESYSTEM::file_put_contents($newPath,$data);
+
+ }
+
+ /**
+ * Creates a new subdirectory
+ *
+ * @param string $name
+ * @return void
+ */
+ public function createDirectory($name) {
+
+ $newPath = $this->path . '/' . $name;
+ OC_FILESYSTEM::mkdir($newPath);
+
+ }
+
+ /**
+ * Returns a specific child node, referenced by its name
+ *
+ * @param string $name
+ * @throws Sabre_DAV_Exception_FileNotFound
+ * @return Sabre_DAV_INode
+ */
+ public function getChild($name) {
+
+ $path = $this->path . '/' . $name;
+
+ if (!OC_FILESYSTEM::file_exists($path)) throw new Sabre_DAV_Exception_FileNotFound('File with name ' . $path . ' could not be located');
+
+ if (OC_FILESYSTEM::is_dir($path)) {
+
+ return new OC_Connector_Sabre_Directory($path);
+
+ } else {
+
+ return new OC_Connector_Sabre_File($path);
+
+ }
+
+ }
+
+ /**
+ * Returns an array with all the child nodes
+ *
+ * @return Sabre_DAV_INode[]
+ */
+ public function getChildren() {
+
+ $nodes = array();
+ // foreach(scandir($this->path) as $node) if($node!='.' && $node!='..') $nodes[] = $this->getChild($node);
+ if( OC_FILESYSTEM::is_dir($this->path)){
+ $dh = OC_FILESYSTEM::opendir($this->path);
+ while(( $node = readdir($dh)) !== false ){
+ if($node!='.' && $node!='..'){
+ $nodes[] = $this->getChild($node);
+ }
+ }
+ }
+ return $nodes;
+
+ }
+
+ /**
+ * Checks if a child exists.
+ *
+ * @param string $name
+ * @return bool
+ */
+ public function childExists($name) {
+
+ $path = $this->path . '/' . $name;
+ return OC_FILESYSTEM::file_exists($path);
+
+ }
+
+ /**
+ * Deletes all files in this directory, and then itself
+ *
+ * @return void
+ */
+ public function delete() {
+
+ foreach($this->getChildren() as $child) $child->delete();
+ OC_FILESYSTEM::rmdir($this->path);
+
+ }
+
+ /**
+ * Returns available diskspace information
+ *
+ * @return array
+ */
+ public function getQuotaInfo() {
+
+ return array(
+ OC_FILESYSTEM::filesize('/'),
+ OC_FILESYSTEM::free_space()
+ );
+
+ }
+
+}
+
diff --git a/lib/Connector/Sabre/file.php b/lib/Connector/Sabre/file.php
new file mode 100644
index 00000000000..bb5ab738430
--- /dev/null
+++ b/lib/Connector/Sabre/file.php
@@ -0,0 +1,89 @@
+<?php
+
+require_once("lib/base.php");
+/**
+ * File class
+ *
+ * @package Sabre
+ * @subpackage DAV
+ * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_DAV_IFile {
+
+ /**
+ * Updates the data
+ *
+ * @param resource $data
+ * @return void
+ */
+ public function put($data) {
+
+ OC_FILESYSTEM::file_put_contents($this->path,$data);
+
+ }
+
+ /**
+ * Returns the data
+ *
+ * @return string
+ */
+ public function get() {
+
+ return OC_FILESYSTEM::file_get_contents($this->path);
+
+ }
+
+ /**
+ * Delete the current file
+ *
+ * @return void
+ */
+ public function delete() {
+
+ OC_FILESYSTEM::unlink($this->path);
+
+ }
+
+ /**
+ * Returns the size of the node, in bytes
+ *
+ * @return int
+ */
+ public function getSize() {
+
+ return OC_FILESYSTEM::filesize($this->path);
+
+ }
+
+ /**
+ * Returns the ETag for a file
+ *
+ * An ETag is a unique identifier representing the current version of the file. If the file changes, the ETag MUST change.
+ * The ETag is an arbritrary string, but MUST be surrounded by double-quotes.
+ *
+ * Return null if the ETag can not effectively be determined
+ *
+ * @return mixed
+ */
+ public function getETag() {
+
+ return null;
+
+ }
+
+ /**
+ * Returns the mime-type for a file
+ *
+ * If null is returned, we'll assume application/octet-stream
+ *
+ * @return mixed
+ */
+ public function getContentType() {
+
+ return OC_FILESYSTEM::getMimeType($this->path);
+
+ }
+}
+
diff --git a/lib/Connector/Sabre/locks.php b/lib/Connector/Sabre/locks.php
new file mode 100644
index 00000000000..8414891b778
--- /dev/null
+++ b/lib/Connector/Sabre/locks.php
@@ -0,0 +1,154 @@
+<?php
+require_once("lib/base.php");
+
+/**
+ * The Lock manager allows you to handle all file-locks centrally.
+ *
+ * This Lock Manager stores all its data in a database. You must pass a PDO
+ * connection object in the constructor.
+ *
+ * @package Sabre
+ * @subpackage DAV
+ * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+/*
+ *
+ * The following SQL statement is just a help for developers and will not be
+ * executed!
+ *
+ * CREATE TABLE locks (
+ * `id` INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ * `userid` VARCHAR(200),
+ * `owner` VARCHAR(100),
+ * `timeout` INTEGER UNSIGNED,
+ * `created` INTEGER,
+ * `token` VARCHAR(100),
+ * `scope` TINYINT,
+ * `depth` TINYINT,
+ * `uri` text
+ * );
+ *
+ */
+class OC_Connector_Sabre_Locks extends Sabre_DAV_Locks_Backend_Abstract {
+
+ /**
+ * Returns a list of Sabre_DAV_Locks_LockInfo objects
+ *
+ * This method should return all the locks for a particular uri, including
+ * locks that might be set on a parent uri.
+ *
+ * If returnChildLocks is set to true, this method should also look for
+ * any locks in the subtree of the uri for locks.
+ *
+ * @param string $uri
+ * @param bool $returnChildLocks
+ * @return array
+ */
+ public function getLocks($uri, $returnChildLocks) {
+
+ // NOTE: the following 10 lines or so could be easily replaced by
+ // pure sql. MySQL's non-standard string concatination prevents us
+ // from doing this though.
+ $query = 'SELECT * FROM *PREFIX*locks WHERE userid = ? AND ((created + timeout) > CAST(? AS UNSIGNED INTEGER)) AND ((uri = ?)';
+ $params = array(OC_USER::getUser(),time(),$uri);
+
+ // We need to check locks for every part in the uri.
+ $uriParts = explode('/',$uri);
+
+ // We already covered the last part of the uri
+ array_pop($uriParts);
+
+ $currentPath='';
+
+ foreach($uriParts as $part) {
+
+ if ($currentPath) $currentPath.='/';
+ $currentPath.=$part;
+
+ $query.=' OR (depth!=0 AND uri = ?)';
+ $params[] = $currentPath;
+
+ }
+
+ if ($returnChildLocks) {
+
+ $query.=' OR (uri LIKE ?)';
+ $params[] = $uri . '/%';
+
+ }
+ $query.=')';
+
+ $stmt = OC_DB::prepare($query);
+ $result = $stmt->execute($params);
+
+ $lockList = array();
+ while( $row = $result->fetchRow()){
+
+ $lockInfo = new Sabre_DAV_Locks_LockInfo();
+ $lockInfo->owner = $row['owner'];
+ $lockInfo->token = $row['token'];
+ $lockInfo->timeout = $row['timeout'];
+ $lockInfo->created = $row['created'];
+ $lockInfo->scope = $row['scope'];
+ $lockInfo->depth = $row['depth'];
+ $lockInfo->uri = $row['uri'];
+ $lockList[] = $lockInfo;
+
+ }
+
+ return $lockList;
+
+ }
+
+ /**
+ * Locks a uri
+ *
+ * @param string $uri
+ * @param Sabre_DAV_Locks_LockInfo $lockInfo
+ * @return bool
+ */
+ public function lock($uri,Sabre_DAV_Locks_LockInfo $lockInfo) {
+
+ // We're making the lock timeout 5 minutes
+ $lockInfo->timeout = 300;
+ $lockInfo->created = time();
+ $lockInfo->uri = $uri;
+
+ $locks = $this->getLocks($uri,false);
+ $exists = false;
+ foreach($locks as $k=>$lock) {
+ if ($lock->token == $lockInfo->token) $exists = true;
+ }
+
+ if ($exists) {
+ $query = OC_DB::prepare( 'UPDATE *PREFIX*locks SET owner = ?, timeout = ?, scope = ?, depth = ?, uri = ?, created = ? WHERE userid = ? AND token = ?' );
+ $result = $query->execute( array($lockInfo->owner,$lockInfo->timeout,$lockInfo->scope,$lockInfo->depth,$uri,$lockInfo->created,OC_USER::getUser(),$lockInfo->token));
+ } else {
+ $query = OC_DB::prepare( 'INSERT INTO *PREFIX*locks (userid,owner,timeout,scope,depth,uri,created,token) VALUES (?,?,?,?,?,?,?,?)' );
+ $result = $query->execute( array(OC_USER::getUser(),$lockInfo->owner,$lockInfo->timeout,$lockInfo->scope,$lockInfo->depth,$uri,$lockInfo->created,$lockInfo->token));
+ }
+
+ return true;
+
+ }
+
+ /**
+ * Removes a lock from a uri
+ *
+ * @param string $uri
+ * @param Sabre_DAV_Locks_LockInfo $lockInfo
+ * @return bool
+ */
+ public function unlock($uri,Sabre_DAV_Locks_LockInfo $lockInfo) {
+
+ $query = OC_DB::prepare( 'DELETE FROM *PREFIX*locks WHERE userid = ? AND uri=? AND token=?' );
+ $result = $query->execute( array(OC_USER::getUser(),$uri,$lockInfo->token));
+
+ return $result->numRows() === 1;
+
+ }
+
+}
+
diff --git a/lib/Connector/Sabre/node.php b/lib/Connector/Sabre/node.php
new file mode 100644
index 00000000000..dc1013dc524
--- /dev/null
+++ b/lib/Connector/Sabre/node.php
@@ -0,0 +1,161 @@
+<?php
+
+require_once("lib/base.php");
+
+/**
+ * Base node-class
+ *
+ * The node class implements the method used by both the File and the Directory classes
+ *
+ * @package Sabre
+ * @subpackage DAV
+ * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+/*
+ *
+ * The following SQL statement is just a help for developers and will not be
+ * executed!
+ *
+ * CREATE TABLE IF NOT EXISTS `properties` (
+ * `userid` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
+ * `propertypath` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
+ * `propertyname` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
+ * `propertyvalue` text COLLATE utf8_unicode_ci NOT NULL
+ * ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+ *
+ */
+abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IProperties {
+
+ /**
+ * The path to the current node
+ *
+ * @var string
+ */
+ protected $path;
+
+ /**
+ * Sets up the node, expects a full path name
+ *
+ * @param string $path
+ * @return void
+ */
+ public function __construct($path) {
+ $this->path = $path;
+ }
+
+
+
+ /**
+ * Returns the name of the node
+ *
+ * @return string
+ */
+ public function getName() {
+
+ list(, $name) = Sabre_DAV_URLUtil::splitPath($this->path);
+ return $name;
+
+ }
+
+ /**
+ * Renames the node
+ *
+ * @param string $name The new name
+ * @return void
+ */
+ public function setName($name) {
+
+ list($parentPath, ) = Sabre_DAV_URLUtil::splitPath($this->path);
+ list(, $newName) = Sabre_DAV_URLUtil::splitPath($name);
+
+ $newPath = $parentPath . '/' . $newName;
+ $oldPath = $this->path;
+
+ OC_FILESYSTEM::rename($this->path,$newPath);
+
+ $this->path = $newPath;
+
+ $query = OC_DB::prepare( 'UPDATE *PREFIX*properties SET propertypath = ? WHERE userid = ? AND propertypath = ?' );
+ $query->execute( array( $newPath,OC_USER::getUser(), $oldPath ));
+
+ }
+
+
+
+ /**
+ * Returns the last modification time, as a unix timestamp
+ *
+ * @return int
+ */
+ public function getLastModified() {
+
+ return OC_FILESYSTEM::filemtime($this->path);
+
+ }
+
+ /**
+ * Updates properties on this node,
+ *
+ * @param array $mutations
+ * @see Sabre_DAV_IProperties::updateProperties
+ * @return bool|array
+ */
+ public function updateProperties($properties) {
+ $existing = $this->getProperties(array());
+ foreach($properties as $propertyName => $propertyValue) {
+ // If it was null, we need to delete the property
+ if (is_null($propertyValue)) {
+ if(array_key_exists( $propertyName, $existing )){
+ $query = OC_DB::prepare( 'DELETE FROM *PREFIX*properties WHERE userid = ? AND propertypath = ? AND propertyname = ?' );
+ $query->execute( array( OC_USER::getUser(), $this->path, $propertyName ));
+ }
+ }
+ else {
+ if(!array_key_exists( $propertyName, $existing )){
+ $query = OC_DB::prepare( 'INSERT INTO *PREFIX*properties (userid,propertypath,propertyname,propertyvalue) VALUES(?,?,?,?)' );
+ $query->execute( array( OC_USER::getUser(), $this->path, $propertyName,$propertyValue ));
+ }
+ else{
+ $query = OC_DB::prepare( 'UPDATE *PREFIX*properties SET propertyvalue = ? WHERE userid = ? AND propertypath = ? AND propertyname = ?' );
+ $query->execute( array( $propertyValue,OC_USER::getUser(), $this->path, $propertyName ));
+ }
+ }
+
+ }
+ return true;
+ }
+
+ /**
+ * Returns a list of properties for this nodes.;
+ *
+ * The properties list is a list of propertynames the client requested, encoded as xmlnamespace#tagName, for example: http://www.example.org/namespace#author
+ * If the array is empty, all properties should be returned
+ *
+ * @param array $properties
+ * @return void
+ */
+ function getProperties($properties) {
+ // At least some magic in here :-)
+ $query = OC_DB::prepare( 'SELECT * FROM *PREFIX*properties WHERE userid = ? AND propertypath = ?' );
+ $result = $query->execute( array( OC_USER::getUser(), $this->path ));
+
+ $existing = array();
+ while( $row = $result->fetchRow()){
+ $existing[$row['propertyname']] = $row['propertyvalue'];
+ }
+
+ if(count($properties) == 0){
+ return $existing;
+ }
+
+ // if the array was empty, we need to return everything
+ $props = array();
+ foreach($properties as $property) {
+ if (isset($existing[$property])) $props[$property] = $existing[$property];
+ }
+ return $props;
+ }
+}
+
diff --git a/lib/HTTP/WebDAV/Server/Filesystem.php b/lib/HTTP/WebDAV/Server/Filesystem.php
deleted file mode 100644
index 5f261643624..00000000000
--- a/lib/HTTP/WebDAV/Server/Filesystem.php
+++ /dev/null
@@ -1,757 +0,0 @@
-<?php
-/*
- +----------------------------------------------------------------------+
- | Copyright (c) 2002-2007 Christian Stocker, Hartmut Holzgraefe |
- | All rights reserved |
- | |
- | Redistribution and use in source and binary forms, with or without |
- | modification, are permitted provided that the following conditions |
- | are met: |
- | |
- | 1. Redistributions of source code must retain the above copyright |
- | notice, this list of conditions and the following disclaimer. |
- | 2. Redistributions in binary form must reproduce the above copyright |
- | notice, this list of conditions and the following disclaimer in |
- | the documentation and/or other materials provided with the |
- | distribution. |
- | 3. The names of the authors may not be used to endorse or promote |
- | products derived from this software without specific prior |
- | written permission. |
- | |
- | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
- | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
- | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
- | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
- | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
- | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
- | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
- | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
- | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
- | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
- | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
- | POSSIBILITY OF SUCH DAMAGE. |
- +----------------------------------------------------------------------+
- --- modified for ownCloud ---
-*/
- require_once("lib/base.php");
- require_once("HTTP/WebDAV/Server.php");
- require_once("System.php");
-
- /**
- * Filesystem access using WebDAV
- *
- * @access public
- * @author Hartmut Holzgraefe <hartmut@php.net>
- * @version @package-version@
- */
- class HTTP_WebDAV_Server_Filesystem extends HTTP_WebDAV_Server
- {
- /**
- * Root directory for WebDAV access
- *
- * Defaults to webserver document root (set by ServeRequest)
- *
- * @access private
- * @var string
- */
- var $base = "";
-
- /**
- * Serve a webdav request
- *
- * @access public
- * @param string
- */
- function ServeRequest($base = false)
- {
- // special treatment for litmus compliance test
- // reply on its identifier header
- // not needed for the test itself but eases debugging
- if (isset($this->_SERVER['HTTP_X_LITMUS'])) {
- error_log("Litmus test ".$this->_SERVER['HTTP_X_LITMUS']);
- header("X-Litmus-reply: ".$this->_SERVER['HTTP_X_LITMUS']);
- }
-
- // set root directory, defaults to webserver document root if not set
- if ($base) {
- $this->base = realpath($base); // TODO throw if not a directory
- } else if (!$this->base) {
- $this->base = $this->_SERVER['DOCUMENT_ROOT'];
- }
-
- // let the base class do all the work
- parent::ServeRequest();
- }
-
- /**
- * No authentication is needed here
- *
- * @access private
- * @param string HTTP Authentication type (Basic, Digest, ...)
- * @param string Username
- * @param string Password
- * @return bool true on successful authentication
- */
- function check_auth($type, $user, $pass)
- {
- return true;
- }
-
-
- /**
- * PROPFIND method handler
- *
- * @param array general parameter passing array
- * @param array return array for file properties
- * @return bool true on success
- */
- function PROPFIND(&$options, &$files)
- {
- // get absolute fs path to requested resource
- $fspath = $options["path"];
-
- // sanity check
- if (!OC_FILESYSTEM::file_exists($fspath)) {
- return false;
- }
-
- // prepare property array
- $files["files"] = array();
- // store information for the requested path itself
- $files["files"][] = $this->fileinfo($options["path"]);
- // information for contained resources requested?
- if (!empty($options["depth"]) && OC_FILESYSTEM::is_dir($fspath) && OC_FILESYSTEM::is_readable($fspath)) {
- // make sure path ends with '/'
- $options["path"] = $this->_slashify($options["path"]);
-
- // try to open directory
- $handle = @OC_FILESYSTEM::opendir($fspath);
-
- if ($handle) {
- // ok, now get all its contents
- while ($filename = readdir($handle)) {
- if ($filename != "." && $filename != "..") {
- $files["files"][] = $this->fileinfo($options["path"].$filename);
- }
- }
- // TODO recursion needed if "Depth: infinite"
- }
- }
-
- // ok, all done
- return true;
- }
-
- /**
- * Get properties for a single file/resource
- *
- * @param string resource path
- * @return array resource properties
- */
- function fileinfo($path)
- {
-
- // map URI path to filesystem path
- $fspath =$path;
-
- // create result array
- $info = array();
- // TODO remove slash append code when base clase is able to do it itself
- $info["path"] = OC_FILESYSTEM::is_dir($fspath) ? $this->_slashify($path) : $path;
- $info["props"] = array();
- // no special beautified displayname here ...
- $info["props"][] = $this->mkprop("displayname", strtoupper($path));
-
- // creation and modification time
- $info["props"][] = $this->mkprop("creationdate", OC_FILESYSTEM::filectime($fspath));
- $info["props"][] = $this->mkprop("getlastmodified", OC_FILESYSTEM::filemtime($fspath));
- // Microsoft extensions: last access time and 'hidden' status
- $info["props"][] = $this->mkprop("lastaccessed", OC_FILESYSTEM::fileatime($fspath));
- $info["props"][] = $this->mkprop("ishidden", ('.' === substr(basename($fspath), 0, 1)));
- // type and size (caller already made sure that path exists)
- if ( OC_FILESYSTEM::is_dir($fspath)) {
- // directory (WebDAV collection)
- $info["props"][] = $this->mkprop("resourcetype", "collection");
- $info["props"][] = $this->mkprop("getcontenttype", "httpd/unix-directory");
- } else {
- // plain file (WebDAV resource)
- $info["props"][] = $this->mkprop("resourcetype", "");
- if ( OC_FILESYSTEM::is_readable($fspath)) {
- $info["props"][] = $this->mkprop("getcontenttype", $this->_mimetype($fspath));
- } else {
- $info["props"][] = $this->mkprop("getcontenttype", "application/x-non-readable");
- }
- $info["props"][] = $this->mkprop("getcontentlength", OC_FILESYSTEM::filesize($fspath));
- }
- // get additional properties from database
- $query = OC_DB::prepare("SELECT ns, name, value FROM *PREFIX*properties WHERE path = ?");
- $res = $query->execute(array($path))->fetchAll();
- foreach($res as $row){
- $info["props"][] = $this->mkprop($row["ns"], $row["name"], $row["value"]);
- }
- return $info;
- }
-
- /**
- * try to detect the mime type of a file
- *
- * @param string file path
- * @return string guessed mime type
- */
- function _mimetype($fspath)
- {
- return OC_FILESYSTEM::getMimeType($fspath);
- }
-
- /**
- * HEAD method handler
- *
- * @param array parameter passing array
- * @return bool true on success
- */
- function HEAD(&$options)
- {
- // get absolute fs path to requested resource
- $fspath = $options["path"];
-
- // sanity check
- if (! OC_FILESYSTEM::file_exists($fspath)) return false;
-
- // detect resource type
- $options['mimetype'] = $this->_mimetype($fspath);
-
- // detect modification time
- // see rfc2518, section 13.7
- // some clients seem to treat this as a reverse rule
- // requiering a Last-Modified header if the getlastmodified header was set
- $options['mtime'] = OC_FILESYSTEM::filemtime($fspath);
-
- // detect resource size
- $options['size'] = OC_FILESYSTEM::filesize($fspath);
-
- return true;
- }
-
- /**
- * GET method handler
- *
- * @param array parameter passing array
- * @return bool true on success
- */
- function GET(&$options)
- {
- // get absolute fs path to requested resource)
- $fspath = $options["path"];
- // is this a collection?
- if (OC_FILESYSTEM::is_dir($fspath)) {
- return $this->GetDir($fspath, $options);
- }
-
- // the header output is the same as for HEAD
- if (!$this->HEAD($options)) {
- return false;
- }
-
- // no need to check result here, it is handled by the base class
- $options['stream'] = OC_FILESYSTEM::fopen($fspath, "r");
-
- return true;
- }
-
- /**
- * GET method handler for directories
- *
- * This is a very simple mod_index lookalike.
- * See RFC 2518, Section 8.4 on GET/HEAD for collections
- *
- * @param string directory path
- * @return void function has to handle HTTP response itself
- */
- function GetDir($fspath, &$options)
- {
- $path = $this->_slashify($options["path"]);
- if ($path != $options["path"]) {
- header("Location: ".$this->base_uri.$path);
- exit;
- }
-
- // fixed width directory column format
- $format = "%15s %-19s %-s\n";
-
- if (!OC_FILESYSTEM::is_readable($fspath)) {
- return false;
- }
-
- $handle = OC_FILESYSTEM::opendir($fspath);
- if (!$handle) {
- return false;
- }
-
- echo "<html><head><title>Index of ".htmlspecialchars($options['path'])."</title></head>\n";
-
- echo "<h1>Index of ".htmlspecialchars($options['path'])."</h1>\n";
-
- echo "<pre>";
- printf($format, "Size", "Last modified", "Filename");
- echo "<hr>";
-
- while ($filename = readdir($handle)) {
- if ($filename != "." && $filename != "..") {
- if( substr($fspath, -1) != '/' ){
- $fspath .= '/';
- }
- $fullpath = $fspath.$filename;
- $name = htmlspecialchars($filename);
- $uri = $_SERVER['SCRIPT_NAME'] . $fullpath;
- printf($format,
- number_format(OC_FILESYSTEM::filesize($fullpath)),
- strftime("%Y-%m-%d %H:%M:%S", OC_FILESYSTEM::filemtime($fullpath)),
- "<a href='$uri'>$name</a>");
- }
- }
-
- echo "</pre>";
-
- closedir($handle);
-
- echo "</html>\n";
-
- exit;
- }
-
- /**
- * PUT method handler
- *
- * @param array parameter passing array
- * @return bool true on success
- */
- function PUT(&$options)
- {
- $fspath = $options["path"];
- $dir = dirname($fspath);
- if (!OC_FILESYSTEM::file_exists($dir) || !OC_FILESYSTEM::is_dir($dir)) {
- return "409 Conflict"; // TODO right status code for both?
- }
-
- $options["new"] = ! OC_FILESYSTEM::file_exists($fspath);
-
- if ($options["new"] && !OC_FILESYSTEM::is_writeable($dir)) {
- return "403 Forbidden";
- }
- if (!$options["new"] && !OC_FILESYSTEM::is_writeable($fspath)) {
- return "403 Forbidden";
- }
- if (!$options["new"] && OC_FILESYSTEM::is_dir($fspath)) {
- return "403 Forbidden";
- }
- $fp = OC_FILESYSTEM::fopen($fspath, "w");
-
- return $fp;
- }
-
-
- /**
- * MKCOL method handler
- *
- * @param array general parameter passing array
- * @return bool true on success
- */
- function MKCOL($options)
- {
- $path = $options["path"];
- $parent = dirname($path);
- $name = basename($path);
- if (!OC_FILESYSTEM::file_exists($parent)) {
- return "409 Conflict";
- }
-
- if (!OC_FILESYSTEM::is_dir($parent)) {
- return "403 Forbidden";
- }
-
- if ( OC_FILESYSTEM::file_exists($parent."/".$name) ) {
- return "405 Method not allowed";
- }
-
- if (!empty($this->_SERVER["CONTENT_LENGTH"])) { // no body parsing yet
- return "415 Unsupported media type";
- }
-
- $stat = OC_FILESYSTEM::mkdir($parent."/".$name, 0777);
- if (!$stat) {
- return "403 Forbidden";
- }
-
- return ("201 Created");
- }
-
-
- /**
- * DELETE method handler
- *
- * @param array general parameter passing array
- * @return bool true on success
- */
- function DELETE($options)
- {
- $path =$options["path"];
- if (!OC_FILESYSTEM::file_exists($path)) {
- return "404 Not found";
- }
- $lock=self::checkLock($path);
- if(is_array($lock)){
- $owner=$options['owner'];
- $lockOwner=$lock['owner'];
- if($owner==$lockOwner){
- return "423 Locked";
- }
- }
- if (OC_FILESYSTEM::is_dir($path)) {
- $query = OC_DB::prepare("DELETE FROM *PREFIX*properties WHERE path LIKE '?%'");
- $query->execute(array($this->_slashify($options["path"])));
- OC_FILESYSTEM::delTree($path);
- } else {
- OC_FILESYSTEM::unlink($path);
- }
- $query = OC_DB::prepare("DELETE FROM *PREFIX*properties WHERE path = ?");
- $query->execute(array($options['path']));
-
- return "204 No Content";
- }
-
-
- /**
- * MOVE method handler
- *
- * @param array general parameter passing array
- * @return bool true on success
- */
- function MOVE($options)
- {
- return $this->COPY($options, true);
- }
-
- /**
- * COPY method handler
- *
- * @param array general parameter passing array
- * @return bool true on success
- */
- function COPY($options, $del=false)
- {
- // TODO Property updates still broken (Litmus should detect this?)
-
- if (!empty($this->_SERVER["CONTENT_LENGTH"])) { // no body parsing yet
- return "415 Unsupported media type";
- }
-
- // no copying to different WebDAV Servers yet
- if (isset($options["dest_url"])) {
- return "502 bad gateway";
- }
-
- $source = $options["path"];
- if (!OC_FILESYSTEM::file_exists($source)) {
- return "404 Not found";
- }
-
- if (OC_FILESYSTEM::is_dir($source)) { // resource is a collection
- switch ($options["depth"]) {
- case "infinity": // valid
- break;
- case "0": // valid for COPY only
- if ($del) { // MOVE?
- return "400 Bad request";
- }
- break;
- case "1": // invalid for both COPY and MOVE
- default:
- return "400 Bad request";
- }
- }
-
- $dest = $options["dest"];
- $destdir = dirname($dest);
-
- if (!OC_FILESYSTEM::file_exists($destdir) || !OC_FILESYSTEM::is_dir($destdir)) {
- return "409 Conflict";
- }
-
-
- $new = !OC_FILESYSTEM::file_exists($dest);
- $existing_col = false;
-
- if (!$new) {
- if ($del && OC_FILESYSTEM::is_dir($dest)) {
- if (!$options["overwrite"]) {
- return "412 precondition failed";
- }
- $dest .= basename($source);
- if (OC_FILESYSTEM::file_exists($dest)) {
- $options["dest"] .= basename($source);
- } else {
- $new = true;
- $existing_col = true;
- }
- }
- }
-
- if (!$new) {
- if ($options["overwrite"]) {
- $stat = $this->DELETE(array("path" => $options["dest"]));
- if (($stat{0} != "2") && (substr($stat, 0, 3) != "404")) {
- return $stat;
- }
- } else {
- return "412 precondition failed";
- }
- }
-
- if ($del) {
- if (!OC_FILESYSTEM::rename($source, $dest)) {
- return "500 Internal server error";
- }
- $destpath = $this->_unslashify($options["dest"]);
- if (is_dir($source)) {
- $dpath=$destpath;
- $path=$options["path"];
- $query = OC_DB::prepare("UPDATE *PREFIX*properties
- SET path = REPLACE(path, ?, ?)
- WHERE path LIKE '?%'");
- $query->execute(array($path,$dpath,$path));
- }
-
- $query = OC_DB::prepare("UPDATE *PREFIX*properties
- SET path = ?
- WHERE path = ?");
- $query->execute(array($dpath,$path));
- } else {
- if (OC_FILESYSTEM::is_dir($source)) {
- $files = OC_FILESYSTEM::getTree($source);
- } else {
- $files = array($source);
- }
-
- if (!is_array($files) || empty($files)) {
- return "500 Internal server error";
- }
-
-
- foreach ($files as $file) {
- if (OC_FILESYSTEM::is_dir($file)) {
- $file = $this->_slashify($file);
- }
- $destfile = str_replace($source, $dest, $file);
-
- if (OC_FILESYSTEM::is_dir($file)) {
- if (!OC_FILESYSTEM::file_exists($destfile)) {
- if (!OC_FILESYSTEM::is_writeable(dirname($destfile))) {
- return "403 Forbidden";
- }
- if (!OC_FILESYSTEM::mkdir($destfile)) {
- return "409 Conflict";
- }
- } else if (!OC_FILESYSTEM::is_dir($destfile)) {
- return "409 Conflict";
- }
- } else {
- if (!OC_FILESYSTEM::copy($file, $destfile)) {
- return "409 Conflict($source) $file --> $destfile ".implode('::',$files);
- }
- }
- }
- }
- return ($new && !$existing_col) ? "201 Created" : "204 No Content";
- }
-
- /**
- * PROPPATCH method handler
- *
- * @param array general parameter passing array
- * @return bool true on success
- */
- function PROPPATCH(&$options)
- {
- global $prefs, $tab;
-
- $msg = "";
- $path = $options["path"];
- $dir = dirname($path)."/";
- $base = basename($path);
-
- foreach ($options["props"] as $key => $prop) {
- if ($prop["ns"] == "DAV:") {
- $options["props"][$key]['status'] = "403 Forbidden";
- } else {
- $path=$options['path'];
- $name=$prop['name'];
- $ns=$prop['ns'];
- if (isset($prop["val"])) {
- $val=$prop['val'];
- $query = OC_DB::prepare("REPLACE INTO *PREFIX*properties (path,name,ns,value) VALUES(?,?,?,?)");
- $query->execute(array($path,$name,$ns,$val));
- } else {
- $query = $query = OC_DB::prepare("DELETE FROM *PREFIX*properties WHERE path = ? AND name = ? AND ns = ?");
- $query->execute(array($path,$name,$ns));
- }
- }
- }
-
- return "";
- }
-
-
- /**
- * LOCK method handler
- *
- * @param array general parameter passing array
- * @return bool true on success
- */
- function LOCK(&$options)
- {
-
- // get absolute fs path to requested resource
- $fspath = $options["path"];
- // TODO recursive locks on directories not supported yet
- // makes litmus test "32. lock_collection" fail
- if (OC_FILESYSTEM::is_dir($fspath) && !empty($options["depth"])) {
- switch($options["depth"]){
- case 'infinity':
- $recursion=1;
- break;
- case '0':
- $recursion=0;
- break;
- }
- }else{
- $recursion=0;
- }
-
- $options["timeout"] = time()+300; // 5min. hardcoded
-
- if (isset($options["update"])) { // Lock Update
- $where = "WHERE path = ? AND token = ?";
-
- $query = OC_DB::prepare("SELECT owner, exclusivelock FROM *PREFIX*locks $where");
- $res = $query->execute(array($options[path],$options[update]))->fetchAll();
-
- if (is_array($res) and isset($res[0])) {
- $row=$res[0];
- $query = OC_DB::prepare("UPDATE `*PREFIX*locks` SET `expires` = , `modified` = $where");
- $query->execute(array($options[timeout],time(),$options[path],$options[update]));
-
- $options['owner'] = $row['owner'];
- $options['scope'] = $row["exclusivelock"] ? "exclusive" : "shared";
- $options['type'] = $row["exclusivelock"] ? "write" : "read";
-
- return true;
- } else {//check for indirect refresh
- $query = OC_DB::prepare("SELECT * FROM *PREFIX*locks WHERE recursive = 1");
- $res = $query->execute();
- foreach($res as $row){
- if(strpos($options['path'],$row['path'])==0){//are we a child of a folder with an recursive lock
- $where = "WHERE path = ? AND token = ?";
- $query = OC_DB::prepare("UPDATE `*PREFIX*locks` SET `expires` = ?, `modified` = ? $where");
- $query->execute(array($options[timeout],time(),$row[path],$options[update]));
- $options['owner'] = $row['owner'];
- $options['scope'] = $row["exclusivelock"] ? "exclusive" : "shared";
- $options['type'] = $row["exclusivelock"] ? "write" : "read";
- return true;
- }
- }
- }
- }
-
- $locktoken=$options['locktoken'];
- $path=$options['path'];
- $time=time();
- $owner=$options['owner'];
- $timeout=$options['timeout'];
- $exclusive=($options['scope'] === "exclusive" ? "1" : "0");
- $query = OC_DB::prepare("INSERT INTO `*PREFIX*locks`
-(`token`,`path`,`created`,`modified`,`owner`,`expires`,`exclusivelock`,`recursive`)
-VALUES (?,?,?,?,?,'timeout',?,?)");
- $result=$query->execute(array($locktoken,$path,$time,$time,$owner,$exclusive,$recursion));
- if(!OC_FILESYSTEM::file_exists($fspath) and $rows>0) {
- return "201 Created";
- }
- return PEAR::isError($result) ? "409 Conflict" : "200 OK";
- }
-
- /**
- * UNLOCK method handler
- *
- * @param array general parameter passing array
- * @return bool true on success
- */
- function UNLOCK(&$options)
- {
- $query = OC_DB::prepare("DELETE FROM *PREFIX*locks
- WHERE path = '$options[path]'
- AND token = '$options[token]'");
- /*
- $query = OC_DB::prepare("DELETE FROM *PREFIX*locks
- WHERE path = ?
- AND token = ?");
- */
- $query->execute();#array($options[path]),$options[token]);
- return PEAR::isError($result) ? "409 Conflict" : "204 No Content";
- }
-
- /**
- * checkLock() helper
- *
- * @param string resource path to check for locks
- * @return bool true on success
- */
- function checkLock($path)
- {
- $result = false;
- $query = OC_DB::prepare("SELECT *
- FROM *PREFIX*locks
- WHERE path = ?
- ");
- $res = $query->execute(array($path))->fetchAll();
- if (is_array($res) and isset($res[0])) {
- $row=$res[0];
-
- if ($row) {
- $result = array( "type" => "write",
- "scope" => $row["exclusivelock"] ? "exclusive" : "shared",
- "depth" => 0,
- "owner" => $row['owner'],
- "token" => $row['token'],
- "created" => $row['created'],
- "modified" => $row['modified'],
- "expires" => $row['expires'],
- "recursive" => $row['recursive']
- );
- }
- }else{
- //check for recursive locks;
- $query = OC_DB::prepare("SELECT *
- FROM *PREFIX*locks
- WHERE recursive = 1
- ");
- $res = $query->execute()->fetchAll();
- foreach($res as $row){
- if(strpos($path,$row['path'])==0){//are we a child of a folder with an recursive lock
- $result = array( "type" => "write",
- "scope" => $row["exclusivelock"] ? "exclusive" : "shared",
- "depth" => 0,
- "owner" => $row['owner'],
- "token" => $row['token'],
- "created" => $row['created'],
- "modified" => $row['modified'],
- "expires" => $row['expires'],
- "recursive" => $row['recursive']
- );
- }
- }
- }
-
- return $result;
- }
-}
-
-?>