mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-22 07:53:39 +01:00
WebDAV can use now the new stream wrapper interface, thought its switched off by default in filemanager/webdav.php (see the comments at the end of the file)
This commit is contained in:
parent
9aa040bec2
commit
9c649da978
@ -1,49 +1,54 @@
|
||||
<?php
|
||||
/**
|
||||
* FileManger - WebDAV access
|
||||
*
|
||||
* Using the PEAR HTTP/WebDAV/Server class (which need to be installed!)
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package filemanger
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2006 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id: class.boetemplate.inc.php 21437 2006-04-24 20:42:42Z ralfbecker $
|
||||
*/
|
||||
|
||||
/**
|
||||
* check if the given user has access
|
||||
*
|
||||
* Create a session or if the user has no account return authenticate header and 401 Unauthorized
|
||||
*
|
||||
* @param array &$account
|
||||
* @return int session-id
|
||||
*/
|
||||
function check_access(&$account)
|
||||
{
|
||||
$account = array(
|
||||
'login' => $_SERVER['PHP_AUTH_USER'],
|
||||
'passwd' => $_SERVER['PHP_AUTH_PW'],
|
||||
'passwd_type' => 'text',
|
||||
);
|
||||
if (!($sessionid = $GLOBALS['egw']->session->create($account)))
|
||||
{
|
||||
header('WWW-Authenticate: Basic realm="eGroupWare WebDAV"');
|
||||
header("HTTP/1.1 401 Unauthorized");
|
||||
header("X-WebDAV-Status: 401 Unauthorized", true);
|
||||
exit;
|
||||
}
|
||||
return $sessionid;
|
||||
}
|
||||
|
||||
$GLOBALS['egw_info']['flags'] = array(
|
||||
'disable_Template_class' => True,
|
||||
'noheader' => True,
|
||||
'currentapp' => 'filemanager',
|
||||
'autocreate_session_callback' => 'check_access',
|
||||
);
|
||||
// if you move this file somewhere else, you need to adapt the path to the header!
|
||||
include('../header.inc.php');
|
||||
|
||||
ExecMethod('phpgwapi.vfs_webdav_server.ServeRequest');
|
||||
<?php
|
||||
/**
|
||||
* FileManger - WebDAV access
|
||||
*
|
||||
* Using the PEAR HTTP/WebDAV/Server class (which need to be installed!)
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package filemanger
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2006 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* check if the given user has access
|
||||
*
|
||||
* Create a session or if the user has no account return authenticate header and 401 Unauthorized
|
||||
*
|
||||
* @param array &$account
|
||||
* @return int session-id
|
||||
*/
|
||||
function check_access(&$account)
|
||||
{
|
||||
$account = array(
|
||||
'login' => $_SERVER['PHP_AUTH_USER'],
|
||||
'passwd' => $_SERVER['PHP_AUTH_PW'],
|
||||
'passwd_type' => 'text',
|
||||
);
|
||||
if (!($sessionid = $GLOBALS['egw']->session->create($account)))
|
||||
{
|
||||
header('WWW-Authenticate: Basic realm="eGroupWare WebDAV"');
|
||||
header("HTTP/1.1 401 Unauthorized");
|
||||
header("X-WebDAV-Status: 401 Unauthorized", true);
|
||||
exit;
|
||||
}
|
||||
return $sessionid;
|
||||
}
|
||||
|
||||
$GLOBALS['egw_info']['flags'] = array(
|
||||
'disable_Template_class' => True,
|
||||
'noheader' => True,
|
||||
'currentapp' => 'filemanager',
|
||||
'autocreate_session_callback' => 'check_access',
|
||||
);
|
||||
// if you move this file somewhere else, you need to adapt the path to the header!
|
||||
include('../header.inc.php');
|
||||
|
||||
// only enable one of the following WebDAV server:
|
||||
// 1. this uses the old webdav class, using the old vfs classes direct (1.4 and current default)
|
||||
ExecMethod('phpgwapi.oldvfs_webdav_server.ServeRequest');
|
||||
|
||||
// 2. this uses the new streamwrapper VFS interface
|
||||
//ExecMethod('phpgwapi.vfs_webdav_server.ServeRequest');
|
||||
|
@ -59,6 +59,9 @@
|
||||
*/
|
||||
class egw_vfs extends vfs_stream_wrapper
|
||||
{
|
||||
const EXECUTABLE = 4;
|
||||
const READABLE = 2;
|
||||
const WRITABLE = 1;
|
||||
/**
|
||||
* fopen working on just the eGW VFS
|
||||
*
|
||||
@ -129,7 +132,7 @@ class egw_vfs extends vfs_stream_wrapper
|
||||
{
|
||||
throw new egw_exception_assertion_failed("File '$path' is not an absolute path!");
|
||||
}
|
||||
return self::url_stat($path);
|
||||
return self::url_stat($path,0);
|
||||
}
|
||||
|
||||
|
||||
@ -185,6 +188,96 @@ class egw_vfs extends vfs_stream_wrapper
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The stream_wrapper interface checks is_{readable|writable|executable} against the webservers uid,
|
||||
* which is wrong in case of our vfs, as we use the current users id and memberships
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $check=4 mode to check: 4 = read, 2 = write, 1 = executable
|
||||
* @return boolean
|
||||
*/
|
||||
static function is_readable($path,$check = 4)
|
||||
{
|
||||
if (!($stat = self::stat($path)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return self::check_access($stat,$check);
|
||||
}
|
||||
|
||||
/**
|
||||
* The stream_wrapper interface checks is_{readable|writable|executable} against the webservers uid,
|
||||
* which is wrong in case of our vfs, as we use the current users id and memberships
|
||||
*
|
||||
* @param array $stat
|
||||
* @param int $check mode to check: 4 = read, 2 = write, 1 = executable
|
||||
* @return boolean
|
||||
*/
|
||||
static function check_access($stat,$check)
|
||||
{
|
||||
//error_log(__METHOD__."(stat[name]={$stat['name']},stat[mode]=".sprintf('%o',$stat['mode']).",$check)");
|
||||
|
||||
if (!$stat)
|
||||
{
|
||||
//error_log(__METHOD__."(stat[name]={$stat['name']},stat[mode]=".sprintf('%o',$stat['mode']).",$check) no stat array!");
|
||||
return false; // file not found
|
||||
}
|
||||
// check if other rights grant access
|
||||
if ($stat['mode'] & $check)
|
||||
{
|
||||
error_log(__METHOD__."(stat[name]={$stat['name']},stat[mode]=".sprintf('%o',$stat['mode']).",$check) access via other rights!");
|
||||
return true;
|
||||
}
|
||||
// check if there's owner access and we are the owner
|
||||
if (($stat['mode'] & ($check << 6)) && $stat['uid'] && $stat['uid'] == $GLOBALS['egw_info']['user']['account_id'])
|
||||
{
|
||||
//error_log(__METHOD__."(stat[name]={$stat['name']},stat[mode]=".sprintf('%o',$stat['mode']).",$check) access via owner rights!");
|
||||
return true;
|
||||
}
|
||||
// check if there's a group access and we have the right membership
|
||||
if (($stat['mode'] & ($check << 3)) && $stat['gid'])
|
||||
{
|
||||
static $memberships;
|
||||
if (is_null($memberships))
|
||||
{
|
||||
$memberships = $GLOBALS['egw']->accounts->memberships($GLOBALS['egw_info']['user']['account_id'],true);
|
||||
}
|
||||
if (in_array(-abs($stat['gid']),$memberships))
|
||||
{
|
||||
//error_log(__METHOD__."(stat[name]={$stat['name']},stat[mode]=".sprintf('%o',$stat['mode']).",$check) access via group rights!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// here could be a check for extended acls ...
|
||||
|
||||
//error_log(__METHOD__."(stat[name]={$stat['name']},stat[mode]=".sprintf('%o',$stat['mode']).",$check) no access!");
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The stream_wrapper interface checks is_{readable|writable|executable} against the webservers uid,
|
||||
* which is wrong in case of our vfs, as we use the current users id and memberships
|
||||
*
|
||||
* @param string $path
|
||||
* @return boolean
|
||||
*/
|
||||
static function is_writable($path)
|
||||
{
|
||||
return self::is_readable($path,2);
|
||||
}
|
||||
|
||||
/**
|
||||
* The stream_wrapper interface checks is_{readable|writable|executable} against the webservers uid,
|
||||
* which is wrong in case of our vfs, as we use the current users id and memberships
|
||||
*
|
||||
* @param string $path
|
||||
* @return boolean
|
||||
*/
|
||||
static function is_executable($path)
|
||||
{
|
||||
return self::is_readable($path,1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instanciating this class, only it's static methods should be used
|
||||
*/
|
||||
|
@ -11,9 +11,6 @@
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
require_once(EGW_API_INC.'/class.vfs_home.inc.php');
|
||||
require_once(EGW_API_INC.'/class.iface_stream_wrapper.inc.php');
|
||||
|
||||
/**
|
||||
* eGroupWare API: VFS - old (until eGW 1.4 inclusive) VFS stream wrapper
|
||||
*
|
||||
@ -27,14 +24,20 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
{
|
||||
/**
|
||||
* If this class should do the operations direct in the filesystem, instead of going through the vfs
|
||||
*
|
||||
*/
|
||||
const USE_FILESYSTEM_DIRECT = true;
|
||||
/**
|
||||
* Mime type of directories, the old vfs uses 'Directory', while eg. WebDAV uses 'httpd/unix-directory'
|
||||
*
|
||||
*/
|
||||
const DIR_MIME_TYPE = 'Directory';
|
||||
/**
|
||||
* Scheme / protocoll used for this stream-wrapper
|
||||
*/
|
||||
const SCHEME = 'oldvfs';
|
||||
/**
|
||||
* Does url_stat returns a mime type, or has it to be determined otherwise (string with attribute name)
|
||||
*/
|
||||
const STAT_RETURN_MIME_TYPE = 'mime';
|
||||
/**
|
||||
* How much should be logged to the apache error-log
|
||||
*
|
||||
@ -145,7 +148,7 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
'operation' => EGW_ACL_ADD,
|
||||
)))
|
||||
{
|
||||
self::remove_password($url);
|
||||
self::_remove_password($url);
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."($url,$mode,$options) file does not exist or can not be created!");
|
||||
if (!($options & STREAM_URL_STAT_QUIET))
|
||||
{
|
||||
@ -164,7 +167,7 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
'operation' => EGW_ACL_EDIT,
|
||||
)))
|
||||
{
|
||||
self::remove_password($url);
|
||||
self::_remove_password($url);
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."($url,$mode,$options) file can not be edited!");
|
||||
if (!($options & STREAM_URL_STAT_QUIET))
|
||||
{
|
||||
@ -457,7 +460,7 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
'must_exist' => true,
|
||||
)) || ($type = self::$old_vfs->file_type($data)) === self::DIR_MIME_TYPE)
|
||||
{
|
||||
self::remove_password($url);
|
||||
self::_remove_password($url);
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."($url) (type=$type) permission denied!");
|
||||
return false; // no permission or file does not exist
|
||||
}
|
||||
@ -509,8 +512,8 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
'operation' => EGW_ACL_ADD,
|
||||
)))
|
||||
{
|
||||
self::remove_password($url_from);
|
||||
self::remove_password($url_to);
|
||||
self::_remove_password($url_from);
|
||||
self::_remove_password($url_to);
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."($url_from,$url_to): $path_to permission denied!");
|
||||
return false; // no permission or file does not exist
|
||||
}
|
||||
@ -520,8 +523,8 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
($type_to === self::DIR_MIME_TYPE) !== (self::$old_vfs->file_type($data_from) === self::DIR_MIME_TYPE))
|
||||
{
|
||||
$is_dir = $type_to === self::DIR_MIME_TYPE ? 'a' : 'no';
|
||||
self::remove_password($url_from);
|
||||
self::remove_password($url_to);
|
||||
self::_remove_password($url_from);
|
||||
self::_remove_password($url_to);
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."($url_to,$url_from) $path_to is $is_dir directory!");
|
||||
return false; // no permission or file does not exist
|
||||
}
|
||||
@ -576,7 +579,7 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
'must_exist' => false,
|
||||
)))
|
||||
{
|
||||
self::remove_password($url);
|
||||
self::_remove_password($url);
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."($url) permission denied!");
|
||||
if (!($options & STREAM_URL_STAT_QUIET))
|
||||
{
|
||||
@ -616,7 +619,7 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
'must_exist' => true,
|
||||
)) || ($type = self::$old_vfs->file_type($data)) !== self::DIR_MIME_TYPE)
|
||||
{
|
||||
self::remove_password($url);
|
||||
self::_remove_password($url);
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."($url,$options) (type=$type) permission denied!");
|
||||
if (!($options & STREAM_URL_STAT_QUIET))
|
||||
{
|
||||
@ -628,7 +631,7 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
// our vfs deletes recursive, while the stream-wrapper interface does not!
|
||||
if (($files = self::$old_vfs->ls($data)))
|
||||
{
|
||||
self::remove_password($url);
|
||||
self::_remove_password($url);
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."($url,$options) dir is not empty!");
|
||||
if (!($options & STREAM_URL_STAT_QUIET))
|
||||
{
|
||||
@ -699,7 +702,7 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
count($files) == 1 && $path == $files[0]['directory'].'/'.$files[0]['name'] &&
|
||||
$files[0]['mime_type'] != self::DIR_MIME_TYPE)
|
||||
{
|
||||
self::remove_password($url);
|
||||
self::_remove_password($url);
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."('$url',$options) $url is not directory!");
|
||||
$this->opened_dir = null;
|
||||
return false;
|
||||
@ -769,7 +772,7 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
//print_r($info);
|
||||
if (!$info)
|
||||
{
|
||||
self::remove_password($url);
|
||||
self::_remove_password($url);
|
||||
if (self::LOG_LEVEL) error_log(__METHOD__."('$url',$flags) file or directory not found!");
|
||||
return false;
|
||||
}
|
||||
@ -848,12 +851,14 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
($info['mime_type'] == self::DIR_MIME_TYPE ? 040070 : 0100060),
|
||||
'size' => $info['size'],
|
||||
'uid' => $info['owner_id'] > 0 ? $info['owner_id'] : 0,
|
||||
'gid' => $info['owner_id'] < 0 ? $info['owner_id'] : 0,
|
||||
'gid' => $info['owner_id'] < 0 ? -$info['owner_id'] : 0,
|
||||
'mtime' => strtotime($info['modified'] ? $info['modified'] : $info['created']),
|
||||
'ctime' => strtotime($info['created']),
|
||||
'nlink' => $info['mime_type'] == self::DIR_MIME_TYPE ? 2 : 1,
|
||||
// eGW addition to return the mime type
|
||||
'mime' => $info['mime_type'],
|
||||
);
|
||||
//print_r($stat);
|
||||
//error_log(__METHOD__."($info[name]) = ".print_r($stat,true));
|
||||
return $stat;
|
||||
}
|
||||
|
||||
@ -873,13 +878,13 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
|
||||
return $func_overload & 2 ? mb_substr($str,$start,$length,'ascii') : substr($str,$start,$length);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replace the password of an url with '...' for error messages
|
||||
*
|
||||
* @param string &$url
|
||||
*/
|
||||
static private function remove_password(&$url)
|
||||
static private function _remove_password(&$url)
|
||||
{
|
||||
$parts = parse_url($url);
|
||||
|
||||
@ -891,4 +896,4 @@ class oldvfs_stream_wrapper implements iface_stream_wrapper
|
||||
}
|
||||
}
|
||||
|
||||
stream_register_wrapper('oldvfs','oldvfs_stream_wrapper');
|
||||
stream_register_wrapper(oldvfs_stream_wrapper::SCHEME ,'oldvfs_stream_wrapper');
|
||||
|
480
phpgwapi/inc/class.oldvfs_webdav_server.inc.php
Normal file
480
phpgwapi/inc/class.oldvfs_webdav_server.inc.php
Normal file
@ -0,0 +1,480 @@
|
||||
<?php
|
||||
/**
|
||||
* eGroupWare API: VFS - WebDAV access
|
||||
*
|
||||
* Using the PEAR HTTP/WebDAV/Server class (which need to be installed!)
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage vfs
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2006 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
require_once('HTTP/WebDAV/Server.php');
|
||||
require_once(EGW_API_INC.'/class.vfs_home.inc.php');
|
||||
|
||||
/**
|
||||
* FileManger - WebDAV access
|
||||
*
|
||||
* Using the PEAR HTTP/WebDAV/Server class (which need to be installed!)
|
||||
*/
|
||||
class oldvfs_webdav_server extends HTTP_WebDAV_Server
|
||||
{
|
||||
/**
|
||||
* instance of the vfs class
|
||||
*
|
||||
* @var vfs_home
|
||||
*/
|
||||
var $vfs;
|
||||
|
||||
var $dav_powered_by = 'eGroupWare WebDAV server';
|
||||
|
||||
/**
|
||||
* Debug level: 0 = nothing, 1 = function calls, 2 = more info, eg. complete $_SERVER array
|
||||
*
|
||||
* The debug messages are send to the apache error_log
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
var $debug = 0;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
if ($this->debug === 2) foreach($_SERVER as $name => $val) error_log("vfs_webdav_server: \$_SERVER[$name]='$val'");
|
||||
|
||||
parent::HTTP_WebDAV_Server();
|
||||
|
||||
$this->vfs =& new vfs_home;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
$vfs_data = array(
|
||||
'string' => $GLOBALS['egw']->translation->convert($options['path'],'utf-8'),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
// at first only list the given path itself
|
||||
'checksubdirs' => False,
|
||||
'nofiles' => True
|
||||
);
|
||||
if (!($vfs_files = $this->vfs->ls($vfs_data))) // path not found
|
||||
{
|
||||
// check if the users home-dir is just not yet created (should be done by the vfs-class!)
|
||||
// ToDo: group-dirs
|
||||
if ($vfs_data['string'] == '/home/'.$GLOBALS['egw_info']['user']['account_lid'])
|
||||
{
|
||||
$this->vfs->override_acl = true; // user has no right to create dir in /home
|
||||
$created = $this->vfs->mkdir(array(
|
||||
'string' => $GLOBALS['egw']->translation->convert($options['path'],'utf-8'),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
));
|
||||
$this->vfs->override_acl = false;
|
||||
|
||||
if (!$created)
|
||||
{
|
||||
if ($this->debug) error_log("vfs_webdav_server::PROPFIND(path='$options[path]',depth=$options[depth]) could not create home dir");
|
||||
}
|
||||
$vfs_files = $this->vfs->ls($vfs_data);
|
||||
}
|
||||
if (!$vfs_files)
|
||||
{
|
||||
if ($this->debug) error_log("vfs_webdav_server::PROPFIND(path='$options[path]',depth=$options[depth]) return false (path not found)");
|
||||
return false; // path not found
|
||||
}
|
||||
}
|
||||
// if depth > 0 and path is a directory => show it's contents
|
||||
if (!empty($options['depth']) && $vfs_files[0]['mime_type'] == 'Directory')
|
||||
{
|
||||
$vfs_data['checksubdirs'] = (int) $options['depth'] != 1;
|
||||
$vfs_data['nofiles'] = false;
|
||||
|
||||
if ($vfs_files[0]['directory'] == '/') // sub-dirs of the root?
|
||||
{
|
||||
$vfs_files = array(); // dont return the directory, it shows up double in konq
|
||||
}
|
||||
else // return the dir itself with a trailing slash, otherwise empty dirs are reported as non-existent
|
||||
{
|
||||
$vfs_files[0]['name'] .= '/';
|
||||
}
|
||||
$vfs_files = array_merge($vfs_files,$this->vfs->ls($vfs_data));
|
||||
}
|
||||
if ($this->debug) error_log("vfs_webdav_server::PROPFIND(path='$options[path]',depth=$options[depth]) ".count($vfs_files).' files');
|
||||
|
||||
$files['files'] = array();
|
||||
$egw_charset = $GLOBALS['egw']->translation->charset();
|
||||
foreach($vfs_files as $fileinfo)
|
||||
{
|
||||
if ($this->debug) error_log('dir="'.$fileinfo['directory'].'", name="'.$fileinfo['name'].'": '.$fileinfo['mime_type']);
|
||||
foreach(array('modified','created') as $date)
|
||||
{
|
||||
// our vfs has no modified set, if never modified, use created
|
||||
list($y,$m,$d,$h,$i,$s) = split("[- :]",$fileinfo[$date] ? $fileinfo[$date] : $fileinfo['created']);
|
||||
$fileinfo[$date] = mktime((int)$h,(int)$i,(int)$s,(int)$m,(int)$d,(int)$y);
|
||||
}
|
||||
$info = array(
|
||||
'path' => $GLOBALS['egw']->translation->convert($fileinfo['directory'].'/'.$fileinfo['name'],$egw_charset,'utf-8'),
|
||||
'props' => array(
|
||||
$this->mkprop('displayname',$GLOBALS['egw']->translation->convert($fileinfo['name'],$egw_charset,'utf-8')),
|
||||
$this->mkprop('creationdate',$fileinfo['created']),
|
||||
$this->mkprop('getlastmodified',$fileinfo['modified']),
|
||||
),
|
||||
);
|
||||
if ($fileinfo['mime_type'] == 'Directory')
|
||||
{
|
||||
$info['props'][] = $this->mkprop('resourcetype', 'collection');
|
||||
$info['props'][] = $this->mkprop('getcontenttype', 'httpd/unix-directory');
|
||||
}
|
||||
else
|
||||
{
|
||||
$info['props'][] = $this->mkprop('resourcetype', '');
|
||||
$info['props'][] = $this->mkprop('getcontenttype', $fileinfo['mime_type']);
|
||||
$info['props'][] = $this->mkprop('getcontentlength', $fileinfo['size']);
|
||||
}
|
||||
$files['files'][] = $info;
|
||||
}
|
||||
if ($this->debug == 2) foreach($files['files'] as $info) error_log(print_r($info,true));
|
||||
// ok, all done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* GET method handler
|
||||
*
|
||||
* @param array parameter passing array
|
||||
* @return bool true on success
|
||||
*/
|
||||
function GET(&$options)
|
||||
{
|
||||
if ($this->debug) error_log('vfs_webdav_server::GET('.print_r($options,true).')');
|
||||
|
||||
$vfs_data = array(
|
||||
'string' => $GLOBALS['egw']->translation->convert($options['path'],'utf-8'),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
'checksubdirs' => False,
|
||||
'nofiles' => True
|
||||
);
|
||||
// sanity check
|
||||
if (!($vfs_file = $this->vfs->ls($vfs_data)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
$options['mimetype'] = $vfs_file[0]['mime_type'];
|
||||
$options['size'] = $vfs_file[0]['size'];
|
||||
|
||||
if (($options['data'] = $this->vfs->read($vfs_data)) === false)
|
||||
{
|
||||
return '403 Forbidden'; // not sure if this is the right code for access denied
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* PUT method handler
|
||||
*
|
||||
* @param array parameter passing array
|
||||
* @return bool true on success
|
||||
*/
|
||||
function PUT(&$options)
|
||||
{
|
||||
if ($this->debug) error_log('vfs_webdav_server::PUT('.print_r($options,true).')');
|
||||
|
||||
$vfs_data = array(
|
||||
'string' => dirname($GLOBALS['egw']->translation->convert($options['path'],'utf-8')),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
'checksubdirs' => False,
|
||||
'nofiles' => True
|
||||
);
|
||||
if (!($vfs_file = $this->vfs->ls($vfs_data)) || $vfs_file[0]['mime_type'] != 'Directory')
|
||||
{
|
||||
return '409 Conflict';
|
||||
}
|
||||
$vfs_data = array(
|
||||
'string' => $GLOBALS['egw']->translation->convert($options['path'],'utf-8'),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
);
|
||||
$options['new'] = !$this->vfs->file_exists($vfs_data);
|
||||
|
||||
$vfs_data['content'] = '';
|
||||
while(!feof($options['stream']))
|
||||
{
|
||||
$vfs_data['content'] .= fread($options['stream'],8192);
|
||||
}
|
||||
return $this->vfs->write($vfs_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* MKCOL method handler
|
||||
*
|
||||
* @param array general parameter passing array
|
||||
* @return bool true on success
|
||||
*/
|
||||
function MKCOL($options)
|
||||
{
|
||||
if ($this->debug) error_log('vfs_webdav_server::MKCOL('.print_r($options,true).')');
|
||||
|
||||
$vfs_data = array(
|
||||
'string' => dirname($GLOBALS['egw']->translation->convert($options['path'],'utf-8')),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
'checksubdirs' => False,
|
||||
'nofiles' => True
|
||||
);
|
||||
if (!($vfs_file = $this->vfs->ls($vfs_data)))
|
||||
{
|
||||
return '409 Conflict';
|
||||
}
|
||||
if ($this->debug) error_log(print_r($vfs_file,true));
|
||||
|
||||
if ($vfs_file[0]['mime_type'] != 'Directory')
|
||||
{
|
||||
return '403 Forbidden';
|
||||
}
|
||||
|
||||
$vfs_data = array(
|
||||
'string' => $GLOBALS['egw']->translation->convert($options['path'],'utf-8'),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
);
|
||||
if ($this->vfs->file_exists($vfs_data) )
|
||||
{
|
||||
return '405 Method not allowed';
|
||||
}
|
||||
|
||||
if (!empty($_SERVER['CONTENT_LENGTH'])) // no body parsing yet
|
||||
{
|
||||
return '415 Unsupported media type';
|
||||
}
|
||||
|
||||
if (!$this->vfs->mkdir($vfs_data))
|
||||
{
|
||||
return '403 Forbidden';
|
||||
}
|
||||
|
||||
return '201 Created';
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE method handler
|
||||
*
|
||||
* @param array general parameter passing array
|
||||
* @return bool true on success
|
||||
*/
|
||||
function DELETE($options)
|
||||
{
|
||||
if ($this->debug) error_log('vfs_webdav_server::DELETE('.print_r($options,true).')');
|
||||
|
||||
$vfs_data = array(
|
||||
'string' => $GLOBALS['egw']->translation->convert($options['path'],'utf-8'),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
);
|
||||
if (!$this->vfs->file_exists($vfs_data))
|
||||
{
|
||||
return '404 Not found';
|
||||
}
|
||||
if (!$this->vfs->rm($vfs_data))
|
||||
{
|
||||
return '403 Forbidden';
|
||||
}
|
||||
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)
|
||||
{
|
||||
if ($this->debug) error_log('vfs_webdav_server::'.($del ? 'MOVE' : 'COPY').'('.print_r($options,true).')');
|
||||
|
||||
// TODO Property updates still broken (Litmus should detect this?)
|
||||
|
||||
if (!empty($_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 = array(
|
||||
'string' => $GLOBALS['egw']->translation->convert($options['path'],'utf-8'),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
);
|
||||
if (!$this->vfs->file_exists($source))
|
||||
{
|
||||
return '404 Not found';
|
||||
}
|
||||
|
||||
$dest = array(
|
||||
'string' => $options['dest'],
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
);
|
||||
$new = !$this->vfs->file_exists($dest);
|
||||
$existing_col = false;
|
||||
|
||||
if (!$new)
|
||||
{
|
||||
if ($del && $this->vfs->file_type($dest) == 'Directory')
|
||||
{
|
||||
if (!$options['overwrite'])
|
||||
{
|
||||
return '412 precondition failed';
|
||||
}
|
||||
$dest['string'] .= basename($GLOBALS['egw']->translation->convert($options['path'],'utf-8'));
|
||||
if ($this->vfs->file_exists($dest))
|
||||
{
|
||||
$options['dest'] .= basename($GLOBALS['egw']->translation->convert($options['path'],'utf-8'));
|
||||
}
|
||||
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 ($this->vfs->file_type($source) == 'Directory' && ($options['depth'] != 'infinity'))
|
||||
{
|
||||
// RFC 2518 Section 9.2, last paragraph
|
||||
return '400 Bad request';
|
||||
}
|
||||
|
||||
$op = $del ? 'mv' : 'cp';
|
||||
$vfs_data = array(
|
||||
'from' => $source['string'],
|
||||
'to' => $dest['string'],
|
||||
'relatives' => array(RELATIVE_ROOT,RELATIVE_ROOT)
|
||||
);
|
||||
if (!$this->vfs->$op($vfs_data))
|
||||
{
|
||||
return '500 Internal server error';
|
||||
}
|
||||
return ($new && !$existing_col) ? '201 Created' : '204 No Content';
|
||||
}
|
||||
|
||||
/**
|
||||
* PROPPATCH method handler
|
||||
*
|
||||
* The current version only allows Webdrive to set creation and modificaton dates.
|
||||
* They are not stored as (arbitrary) WebDAV properties with their own namespace and name,
|
||||
* but in the regular vfs attributes.
|
||||
*
|
||||
* @todo Store a properties in the DB and retrieve them in PROPFIND again.
|
||||
* @param array general parameter passing array
|
||||
* @return bool true on success
|
||||
*/
|
||||
function PROPPATCH(&$options)
|
||||
{
|
||||
foreach ($options["props"] as $key => $prop) {
|
||||
$attributes = array();
|
||||
switch($prop['ns'])
|
||||
{
|
||||
// allow Webdrive to set creation and modification time
|
||||
case 'http://www.southrivertech.com/':
|
||||
switch($prop['name'])
|
||||
{
|
||||
case 'srt_modifiedtime':
|
||||
case 'getlastmodified':
|
||||
$attributes['modified'] = strtotime($prop['val']);
|
||||
break;
|
||||
case 'srt_creationtime':
|
||||
$attributes['created'] = strtotime($prop['val']);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'DAV:':
|
||||
switch($prop['name'])
|
||||
{
|
||||
// allow netdrive to change the modification time
|
||||
case 'getlastmodified':
|
||||
$attributes['modified'] = strtotime($prop['val']);
|
||||
break;
|
||||
// not sure why, the filesystem example of the WebDAV class does it ...
|
||||
default:
|
||||
$options["props"][$key]['status'] = "403 Forbidden";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ($this->debug) $props[] = '('.$prop["ns"].')'.$prop['name'].'='.$prop['val'];
|
||||
}
|
||||
if ($attributes)
|
||||
{
|
||||
$vfs_data = array(
|
||||
'string' => $GLOBALS['egw']->translation->convert($options['path'],'utf-8'),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
'attributes'=> $attributes,
|
||||
);
|
||||
$this->vfs->set_attributes($vfs_data);
|
||||
}
|
||||
if ($this->debug)
|
||||
{
|
||||
error_log(__CLASS__.'::'.__METHOD__.": path=$options[path], props=".implode(', ',$props));
|
||||
if ($attributes) error_log(__CLASS__.'::'.__METHOD__.": path=$options[path], set attributes=".str_replace("\n",' ',print_r($attributes,true)));
|
||||
}
|
||||
|
||||
|
||||
return ""; // this is as the filesystem example handler does it, no true or false ...
|
||||
}
|
||||
|
||||
/**
|
||||
* auth check in the session creation in dav.php, to avoid being redirected to login.php
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $login account_lid or account_lid@domain
|
||||
* @param string $password this is checked in the session creation
|
||||
* @return boolean true if authorized or false otherwise
|
||||
*/
|
||||
function checkAuth($type,$login,$password)
|
||||
{
|
||||
list($account_lid,$domain) = explode('@',$login);
|
||||
|
||||
$auth = ($login === $GLOBALS['egw_info']['user']['account_lid'] ||
|
||||
($account_lid === $GLOBALS['egw_info']['user']['account_lid'] && $domain === $GLOBALS['egw']->session->account_domain)) &&
|
||||
$GLOBALS['egw_info']['user']['apps']['filemanager'];
|
||||
|
||||
if ($this->debug) error_log("vfs_webdav_server::checkAuth('$type','$login','\$password'): account_lid='$account_lid', domain='$domain' ==> ".(int)$auth);
|
||||
|
||||
return $auth;
|
||||
}
|
||||
}
|
@ -22,9 +22,13 @@
|
||||
class vfs_stream_wrapper implements iface_stream_wrapper
|
||||
{
|
||||
/**
|
||||
* Scheme / protocoll used for this stream-wrapper
|
||||
* Scheme / protocol used for this stream-wrapper
|
||||
*/
|
||||
const SCHEME = 'vfs';
|
||||
/**
|
||||
* Mime type of directories, the old vfs used 'Directory', while eg. WebDAV uses 'httpd/unix-directory'
|
||||
*/
|
||||
const DIR_MIME_TYPE = 'httpd/unix-directory';
|
||||
/**
|
||||
* optional context param when opening the stream, null if no context passed
|
||||
*
|
||||
@ -40,7 +44,8 @@ class vfs_stream_wrapper implements iface_stream_wrapper
|
||||
* @var array
|
||||
*/
|
||||
protected static $fstab = array(
|
||||
'/' => 'oldvfs://$user:$pass@$host/',
|
||||
'/' => 'sqlfs://$user:$pass@$host/',
|
||||
// '/' => 'oldvfs://$user:$pass@$host/',
|
||||
// '/files' => 'oldvfs://$user:$pass@$host/home/Default',
|
||||
// '/images' => 'http://localhost/egroupware/phpgwapi/templates/idots/images',
|
||||
// '/home/ralf/linux' => '/home/ralf', // we probably need to forbid direct filesystem access for security reasons!
|
||||
@ -88,7 +93,17 @@ class vfs_stream_wrapper implements iface_stream_wrapper
|
||||
{
|
||||
return $cache[$path];
|
||||
}
|
||||
$parts = parse_url($path);
|
||||
// setting default user, passwd and domain, if it's not contained int the url
|
||||
static $defaults;
|
||||
if (is_null($defaults))
|
||||
{
|
||||
$defaults = array(
|
||||
'user' => $GLOBALS['egw_info']['user']['account_lid'],
|
||||
'pass' => $GLOBALS['egw_info']['user']['passwd'],
|
||||
'host' => $GLOBALS['egw_info']['user']['domain'],
|
||||
);
|
||||
}
|
||||
$parts = array_merge(parse_url($path),$defaults);
|
||||
|
||||
if (empty($parts['path'])) $parts['path'] = '/';
|
||||
|
||||
@ -319,7 +334,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return mkdir($path,$mode,$options);
|
||||
return mkdir($url,$mode,$options);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -338,7 +353,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return rmdir($path,$options);
|
||||
return rmdir($url);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -366,6 +381,60 @@ class vfs_stream_wrapper implements iface_stream_wrapper
|
||||
return touch($url,$time);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is not (yet) a stream-wrapper function, but it's necessary and can be used static
|
||||
*
|
||||
* The methods use the following ways to get the mime type (in that order)
|
||||
* - directories (is_dir()) --> self::DIR_MIME_TYPE
|
||||
* - stream implemented by class defining the STAT_RETURN_MIME_TYPE constant --> use mime-type returned by url_stat
|
||||
* - for regular filesystem use mime_content_type function if available
|
||||
* - use eGW's mime-magic class
|
||||
*
|
||||
* @param string $path
|
||||
* @return string mime-type (self::DIR_MIME_TYPE for directories)
|
||||
*/
|
||||
static function mime_content_type($path)
|
||||
{
|
||||
if (!($url = self::resolve_url($path)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (is_dir($url))
|
||||
{
|
||||
$mime = self::DIR_MIME_TYPE;
|
||||
}
|
||||
if (!$mime && ($scheme = parse_url($url,PHP_URL_SCHEME)))
|
||||
{
|
||||
// check it it's an eGW stream wrapper returning mime-type via url_stat
|
||||
if (class_exists($class = $scheme.'_stream_wrapper') && ($mime_attr = constant($class.'::STAT_RETURN_MIME_TYPE')))
|
||||
{
|
||||
$stat = call_user_func(array($scheme.'_stream_wrapper','url_stat'),parse_url($url,PHP_URL_PATH),0);
|
||||
if ($stat[$mime_attr])
|
||||
{
|
||||
$mime = $stat[$mime_attr];
|
||||
}
|
||||
}
|
||||
}
|
||||
// if we operate on the regular filesystem and the mime_content_type function is available --> use it
|
||||
if (!$mime && !$scheme && function_exists('mime_content_type'))
|
||||
{
|
||||
$mime = mime_content_type($path);
|
||||
}
|
||||
// using eGW's own mime magic
|
||||
// ToDo: rework mime_magic as all methods cound be static!
|
||||
if (!$mime)
|
||||
{
|
||||
static $mime_magic;
|
||||
if (is_null($mime_magic))
|
||||
{
|
||||
$mime_magic = mime_magic();
|
||||
}
|
||||
$mime = $mime_magic->filename2mime(parse_url($url,PHP_URL_PATH));
|
||||
}
|
||||
//error_log(__METHOD__."($path) mime=$mime");
|
||||
return $mime;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called immediately when your stream object is created for examining directory contents with opendir().
|
||||
*
|
||||
@ -431,6 +500,7 @@ class vfs_stream_wrapper implements iface_stream_wrapper
|
||||
{
|
||||
return false;
|
||||
}
|
||||
error_log(__METHOD__."('$path',$flags) calling stat($url)");
|
||||
return stat($url);
|
||||
}
|
||||
|
||||
@ -498,8 +568,9 @@ class vfs_stream_wrapper implements iface_stream_wrapper
|
||||
self::$wrappers[] = 'webdav';
|
||||
break;
|
||||
case 'oldvfs':
|
||||
require_once(EGW_API_INC.'/class.oldvfs_stream_wrapper.inc.php');
|
||||
self::$wrappers[] = 'oldvfs';
|
||||
case 'sqlfs':
|
||||
require_once(EGW_API_INC.'/class.'.$scheme.'_stream_wrapper.inc.php');
|
||||
self::$wrappers[] = $scheme;
|
||||
break;
|
||||
case '':
|
||||
return true; // default file, always loaded
|
||||
|
@ -1,37 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* eGroupWare API: VFS - WebDAV access
|
||||
* eGroupWare API: VFS - WebDAV access using the new stream wrapper VFS interface
|
||||
*
|
||||
* Using the PEAR HTTP/WebDAV/Server class (which need to be installed!)
|
||||
* Using the PEAR HTTP/WebDAV/Server/Filesystem class (which need to be installed!)
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage vfs
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2006 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @author Hartmut Holzgraefe <hartmut@php.net> original HTTP/WebDAV/Server/Filesystem class, of which some code is used
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
require_once('HTTP/WebDAV/Server.php');
|
||||
require_once(EGW_API_INC.'/class.vfs_home.inc.php');
|
||||
require_once('HTTP/WebDAV/Server/Filesystem.php');
|
||||
require_once(EGW_API_INC.'/class.egw_vfs.inc.php');
|
||||
|
||||
/**
|
||||
* FileManger - WebDAV access
|
||||
* FileManger - WebDAV access using the new stream wrapper VFS interface
|
||||
*
|
||||
* Using the PEAR HTTP/WebDAV/Server class (which need to be installed!)
|
||||
* Using the PEAR HTTP/WebDAV/Server/Filesystem class (which need to be installed!)
|
||||
*
|
||||
* @todo table to store locks and properties
|
||||
* @todo filesystem class uses PEAR's System::find which we dont require nor know if it works on custom streamwrapper
|
||||
*/
|
||||
class vfs_webdav_server extends HTTP_WebDAV_Server
|
||||
class vfs_webdav_server extends HTTP_WebDAV_Server_Filesystem
|
||||
{
|
||||
/**
|
||||
* instance of the vfs class
|
||||
*
|
||||
* @var vfs_home
|
||||
*/
|
||||
var $vfs;
|
||||
|
||||
var $dav_powered_by = 'eGroupWare WebDAV server';
|
||||
|
||||
/**
|
||||
* Base directory is the URL of our VFS root
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
var $base = 'vfs://default';
|
||||
|
||||
/**
|
||||
* Debug level: 0 = nothing, 1 = function calls, 2 = more info, eg. complete $_SERVER array
|
||||
*
|
||||
@ -41,354 +44,151 @@ class vfs_webdav_server extends HTTP_WebDAV_Server
|
||||
*/
|
||||
var $debug = 0;
|
||||
|
||||
function vfs_webdav_server()
|
||||
/**
|
||||
* Serve a webdav request
|
||||
*
|
||||
* Reimplemented to not check our vfs base path with realpath and connect to mysql DB
|
||||
*
|
||||
* @access public
|
||||
* @param string
|
||||
*/
|
||||
function ServeRequest($base = false)
|
||||
{
|
||||
if ($this->debug === 2) foreach($_SERVER as $name => $val) error_log("vfs_webdav_server: \$_SERVER[$name]='$val'");
|
||||
|
||||
parent::HTTP_WebDAV_Server();
|
||||
// special treatment for litmus compliance test
|
||||
// reply on its identifier header
|
||||
// not needed for the test itself but eases debugging
|
||||
foreach (apache_request_headers() as $key => $value)
|
||||
{
|
||||
if (stristr($key, "litmus"))
|
||||
{
|
||||
error_log("Litmus test $value");
|
||||
header("X-Litmus-reply: ".$value);
|
||||
}
|
||||
}
|
||||
|
||||
$this->vfs =& new vfs_home;
|
||||
// let the base class do all the work
|
||||
HTTP_WebDAV_Server::ServeRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
$vfs_data = array(
|
||||
'string' => $GLOBALS['egw']->translation->convert($options['path'],'utf-8'),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
// at first only list the given path itself
|
||||
'checksubdirs' => False,
|
||||
'nofiles' => True
|
||||
);
|
||||
if (!($vfs_files = $this->vfs->ls($vfs_data))) // path not found
|
||||
{
|
||||
// check if the users home-dir is just not yet created (should be done by the vfs-class!)
|
||||
// ToDo: group-dirs
|
||||
if ($vfs_data['string'] == '/home/'.$GLOBALS['egw_info']['user']['account_lid'])
|
||||
{
|
||||
$this->vfs->override_acl = true; // user has no right to create dir in /home
|
||||
$created = $this->vfs->mkdir(array(
|
||||
'string' => $GLOBALS['egw']->translation->convert($options['path'],'utf-8'),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
));
|
||||
$this->vfs->override_acl = false;
|
||||
|
||||
if (!$created)
|
||||
{
|
||||
if ($this->debug) error_log("vfs_webdav_server::PROPFIND(path='$options[path]',depth=$options[depth]) could not create home dir");
|
||||
}
|
||||
$vfs_files = $this->vfs->ls($vfs_data);
|
||||
}
|
||||
if (!$vfs_files)
|
||||
{
|
||||
if ($this->debug) error_log("vfs_webdav_server::PROPFIND(path='$options[path]',depth=$options[depth]) return false (path not found)");
|
||||
return false; // path not found
|
||||
}
|
||||
}
|
||||
// if depth > 0 and path is a directory => show it's contents
|
||||
if (!empty($options['depth']) && $vfs_files[0]['mime_type'] == 'Directory')
|
||||
{
|
||||
$vfs_data['checksubdirs'] = (int) $options['depth'] != 1;
|
||||
$vfs_data['nofiles'] = false;
|
||||
/**
|
||||
* DELETE method handler
|
||||
*
|
||||
* @param array general parameter passing array
|
||||
* @return bool true on success
|
||||
*/
|
||||
function DELETE($options)
|
||||
{
|
||||
$path = $this->base . "/" .$options["path"];
|
||||
|
||||
if ($vfs_files[0]['directory'] == '/') // sub-dirs of the root?
|
||||
{
|
||||
$vfs_files = array(); // dont return the directory, it shows up double in konq
|
||||
}
|
||||
else // return the dir itself with a trailing slash, otherwise empty dirs are reported as non-existent
|
||||
{
|
||||
$vfs_files[0]['name'] .= '/';
|
||||
}
|
||||
$vfs_files = array_merge($vfs_files,$this->vfs->ls($vfs_data));
|
||||
}
|
||||
if ($this->debug) error_log("vfs_webdav_server::PROPFIND(path='$options[path]',depth=$options[depth]) ".count($vfs_files).' files');
|
||||
|
||||
$files['files'] = array();
|
||||
$egw_charset = $GLOBALS['egw']->translation->charset();
|
||||
foreach($vfs_files as $fileinfo)
|
||||
{
|
||||
if ($this->debug) error_log('dir="'.$fileinfo['directory'].'", name="'.$fileinfo['name'].'": '.$fileinfo['mime_type']);
|
||||
foreach(array('modified','created') as $date)
|
||||
{
|
||||
// our vfs has no modified set, if never modified, use created
|
||||
list($y,$m,$d,$h,$i,$s) = split("[- :]",$fileinfo[$date] ? $fileinfo[$date] : $fileinfo['created']);
|
||||
$fileinfo[$date] = mktime((int)$h,(int)$i,(int)$s,(int)$m,(int)$d,(int)$y);
|
||||
}
|
||||
$info = array(
|
||||
'path' => $GLOBALS['egw']->translation->convert($fileinfo['directory'].'/'.$fileinfo['name'],$egw_charset,'utf-8'),
|
||||
'props' => array(
|
||||
$this->mkprop('displayname',$GLOBALS['egw']->translation->convert($fileinfo['name'],$egw_charset,'utf-8')),
|
||||
$this->mkprop('creationdate',$fileinfo['created']),
|
||||
$this->mkprop('getlastmodified',$fileinfo['modified']),
|
||||
),
|
||||
);
|
||||
if ($fileinfo['mime_type'] == 'Directory')
|
||||
if (!file_exists($path))
|
||||
{
|
||||
return "404 Not found";
|
||||
}
|
||||
|
||||
if (is_dir($path))
|
||||
{
|
||||
/*$query = "DELETE FROM {$this->db_prefix}properties
|
||||
WHERE path LIKE '".$this->_slashify($options["path"])."%'";
|
||||
mysql_query($query); */
|
||||
// recursive delete the directory
|
||||
if ($dir = egw_vfs::dir_opendir($options["path"]))
|
||||
{
|
||||
$info['props'][] = $this->mkprop('resourcetype', 'collection');
|
||||
$info['props'][] = $this->mkprop('getcontenttype', 'httpd/unix-directory');
|
||||
while(($file = readdir($dir)))
|
||||
{
|
||||
if ($file == '.' || $file == '..') continue;
|
||||
|
||||
if (is_dir($path.'/'.$file))
|
||||
{
|
||||
// recursivly call ourself with the dir
|
||||
$opts = $options;
|
||||
$opts['path'] .= '/'.$file;
|
||||
$this->DELETE($opts);
|
||||
}
|
||||
else
|
||||
{
|
||||
unlink($path.'/'.$file);
|
||||
}
|
||||
}
|
||||
closedir($dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
$info['props'][] = $this->mkprop('resourcetype', '');
|
||||
$info['props'][] = $this->mkprop('getcontenttype', $fileinfo['mime_type']);
|
||||
$info['props'][] = $this->mkprop('getcontentlength', $fileinfo['size']);
|
||||
}
|
||||
$files['files'][] = $info;
|
||||
}
|
||||
if ($this->debug == 2) foreach($files['files'] as $info) error_log(print_r($info,true));
|
||||
// ok, all done
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* GET method handler
|
||||
*
|
||||
* @param array parameter passing array
|
||||
* @return bool true on success
|
||||
*/
|
||||
function GET(&$options)
|
||||
{
|
||||
if ($this->debug) error_log('vfs_webdav_server::GET('.print_r($options,true).')');
|
||||
|
||||
$vfs_data = array(
|
||||
'string' => $GLOBALS['egw']->translation->convert($options['path'],'utf-8'),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
'checksubdirs' => False,
|
||||
'nofiles' => True
|
||||
);
|
||||
// sanity check
|
||||
if (!($vfs_file = $this->vfs->ls($vfs_data)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
$options['mimetype'] = $vfs_file[0]['mime_type'];
|
||||
$options['size'] = $vfs_file[0]['size'];
|
||||
|
||||
if (($options['data'] = $this->vfs->read($vfs_data)) === false)
|
||||
{
|
||||
return '403 Forbidden'; // not sure if this is the right code for access denied
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unlink($path);
|
||||
}
|
||||
/*$query = "DELETE FROM {$this->db_prefix}properties
|
||||
WHERE path = '$options[path]'";
|
||||
mysql_query($query);*/
|
||||
|
||||
return "204 No Content";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get properties for a single file/resource
|
||||
*
|
||||
* @param string resource path
|
||||
* @return array resource properties
|
||||
*/
|
||||
function fileinfo($path)
|
||||
{
|
||||
error_log(__METHOD__."($path)");
|
||||
// map URI path to filesystem path
|
||||
$fspath = $this->base . $path;
|
||||
|
||||
// create result array
|
||||
$info = array();
|
||||
// TODO remove slash append code when base clase is able to do it itself
|
||||
$info["path"] = 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", filectime($fspath));
|
||||
$info["props"][] = $this->mkprop("getlastmodified", filemtime($fspath));
|
||||
|
||||
// type and size (caller already made sure that path exists)
|
||||
if (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 (egw_vfs::is_readable($path)) {
|
||||
$info["props"][] = $this->mkprop("getcontenttype", egw_vfs::mime_content_type($path));
|
||||
} else {
|
||||
error_log(__METHOD__."($path) $fspath is not readable!");
|
||||
$info["props"][] = $this->mkprop("getcontenttype", "application/x-non-readable");
|
||||
}
|
||||
$info["props"][] = $this->mkprop("getcontentlength", filesize($fspath));
|
||||
}
|
||||
/*
|
||||
// get additional properties from database
|
||||
$query = "SELECT ns, name, value
|
||||
FROM {$this->db_prefix}properties
|
||||
WHERE path = '$path'";
|
||||
$res = mysql_query($query);
|
||||
while ($row = mysql_fetch_assoc($res)) {
|
||||
$info["props"][] = $this->mkprop($row["ns"], $row["name"], $row["value"]);
|
||||
}
|
||||
mysql_free_result($res);
|
||||
*/
|
||||
//error_log(__METHOD__."($path) info=".print_r($info,true));
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* PUT method handler
|
||||
*
|
||||
* @param array parameter passing array
|
||||
* @return bool true on success
|
||||
*/
|
||||
function PUT(&$options)
|
||||
{
|
||||
if ($this->debug) error_log('vfs_webdav_server::PUT('.print_r($options,true).')');
|
||||
|
||||
$vfs_data = array(
|
||||
'string' => dirname($GLOBALS['egw']->translation->convert($options['path'],'utf-8')),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
'checksubdirs' => False,
|
||||
'nofiles' => True
|
||||
);
|
||||
if (!($vfs_file = $this->vfs->ls($vfs_data)) || $vfs_file[0]['mime_type'] != 'Directory')
|
||||
{
|
||||
return '409 Conflict';
|
||||
}
|
||||
$vfs_data = array(
|
||||
'string' => $GLOBALS['egw']->translation->convert($options['path'],'utf-8'),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
);
|
||||
$options['new'] = !$this->vfs->file_exists($vfs_data);
|
||||
|
||||
$vfs_data['content'] = '';
|
||||
while(!feof($options['stream']))
|
||||
{
|
||||
$vfs_data['content'] .= fread($options['stream'],8192);
|
||||
}
|
||||
return $this->vfs->write($vfs_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* MKCOL method handler
|
||||
* Used eg. by get
|
||||
*
|
||||
* @param array general parameter passing array
|
||||
* @return bool true on success
|
||||
* @todo replace all calls to _mimetype with egw_vfs::mime_content_type()
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function MKCOL($options)
|
||||
{
|
||||
if ($this->debug) error_log('vfs_webdav_server::MKCOL('.print_r($options,true).')');
|
||||
|
||||
$vfs_data = array(
|
||||
'string' => dirname($GLOBALS['egw']->translation->convert($options['path'],'utf-8')),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
'checksubdirs' => False,
|
||||
'nofiles' => True
|
||||
);
|
||||
if (!($vfs_file = $this->vfs->ls($vfs_data)))
|
||||
{
|
||||
return '409 Conflict';
|
||||
}
|
||||
if ($this->debug) error_log(print_r($vfs_file,true));
|
||||
|
||||
if ($vfs_file[0]['mime_type'] != 'Directory')
|
||||
{
|
||||
return '403 Forbidden';
|
||||
}
|
||||
|
||||
$vfs_data = array(
|
||||
'string' => $GLOBALS['egw']->translation->convert($options['path'],'utf-8'),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
);
|
||||
if ($this->vfs->file_exists($vfs_data) )
|
||||
{
|
||||
return '405 Method not allowed';
|
||||
}
|
||||
|
||||
if (!empty($_SERVER['CONTENT_LENGTH'])) // no body parsing yet
|
||||
{
|
||||
return '415 Unsupported media type';
|
||||
}
|
||||
|
||||
if (!$this->vfs->mkdir($vfs_data))
|
||||
{
|
||||
return '403 Forbidden';
|
||||
}
|
||||
|
||||
return '201 Created';
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE method handler
|
||||
*
|
||||
* @param array general parameter passing array
|
||||
* @return bool true on success
|
||||
*/
|
||||
function DELETE($options)
|
||||
function _mimetype($path)
|
||||
{
|
||||
if ($this->debug) error_log('vfs_webdav_server::DELETE('.print_r($options,true).')');
|
||||
|
||||
$vfs_data = array(
|
||||
'string' => $GLOBALS['egw']->translation->convert($options['path'],'utf-8'),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
);
|
||||
if (!$this->vfs->file_exists($vfs_data))
|
||||
{
|
||||
return '404 Not found';
|
||||
}
|
||||
if (!$this->vfs->rm($vfs_data))
|
||||
{
|
||||
return '403 Forbidden';
|
||||
}
|
||||
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)
|
||||
{
|
||||
if ($this->debug) error_log('vfs_webdav_server::'.($del ? 'MOVE' : 'COPY').'('.print_r($options,true).')');
|
||||
|
||||
// TODO Property updates still broken (Litmus should detect this?)
|
||||
|
||||
if (!empty($_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 = array(
|
||||
'string' => $GLOBALS['egw']->translation->convert($options['path'],'utf-8'),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
);
|
||||
if (!$this->vfs->file_exists($source))
|
||||
{
|
||||
return '404 Not found';
|
||||
}
|
||||
|
||||
$dest = array(
|
||||
'string' => $options['dest'],
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
);
|
||||
$new = !$this->vfs->file_exists($dest);
|
||||
$existing_col = false;
|
||||
|
||||
if (!$new)
|
||||
{
|
||||
if ($del && $this->vfs->file_type($dest) == 'Directory')
|
||||
{
|
||||
if (!$options['overwrite'])
|
||||
{
|
||||
return '412 precondition failed';
|
||||
}
|
||||
$dest['string'] .= basename($GLOBALS['egw']->translation->convert($options['path'],'utf-8'));
|
||||
if ($this->vfs->file_exists($dest))
|
||||
{
|
||||
$options['dest'] .= basename($GLOBALS['egw']->translation->convert($options['path'],'utf-8'));
|
||||
}
|
||||
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 ($this->vfs->file_type($source) == 'Directory' && ($options['depth'] != 'infinity'))
|
||||
{
|
||||
// RFC 2518 Section 9.2, last paragraph
|
||||
return '400 Bad request';
|
||||
}
|
||||
|
||||
$op = $del ? 'mv' : 'cp';
|
||||
$vfs_data = array(
|
||||
'from' => $source['string'],
|
||||
'to' => $dest['string'],
|
||||
'relatives' => array(RELATIVE_ROOT,RELATIVE_ROOT)
|
||||
);
|
||||
if (!$this->vfs->$op($vfs_data))
|
||||
{
|
||||
return '500 Internal server error';
|
||||
}
|
||||
return ($new && !$existing_col) ? '201 Created' : '204 No Content';
|
||||
return egw_vfs::mime_content_type($path);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -404,6 +204,8 @@ class vfs_webdav_server extends HTTP_WebDAV_Server
|
||||
*/
|
||||
function PROPPATCH(&$options)
|
||||
{
|
||||
$path = $GLOBALS['egw']->translation->convert($options['path'],'utf-8');
|
||||
|
||||
foreach ($options["props"] as $key => $prop) {
|
||||
$attributes = array();
|
||||
switch($prop['ns'])
|
||||
@ -414,10 +216,11 @@ class vfs_webdav_server extends HTTP_WebDAV_Server
|
||||
{
|
||||
case 'srt_modifiedtime':
|
||||
case 'getlastmodified':
|
||||
$attributes['modified'] = strtotime($prop['val']);
|
||||
egw_vfs::touch($path,strtotime($prop['val']));
|
||||
break;
|
||||
case 'srt_creationtime':
|
||||
$attributes['created'] = strtotime($prop['val']);
|
||||
// not supported via the streamwrapper interface atm.
|
||||
//$attributes['created'] = strtotime($prop['val']);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -427,7 +230,7 @@ class vfs_webdav_server extends HTTP_WebDAV_Server
|
||||
{
|
||||
// allow netdrive to change the modification time
|
||||
case 'getlastmodified':
|
||||
$attributes['modified'] = strtotime($prop['val']);
|
||||
egw_vfs::touch($path,strtotime($prop['val']));
|
||||
break;
|
||||
// not sure why, the filesystem example of the WebDAV class does it ...
|
||||
default:
|
||||
@ -438,26 +241,147 @@ class vfs_webdav_server extends HTTP_WebDAV_Server
|
||||
}
|
||||
if ($this->debug) $props[] = '('.$prop["ns"].')'.$prop['name'].'='.$prop['val'];
|
||||
}
|
||||
if ($attributes)
|
||||
{
|
||||
$vfs_data = array(
|
||||
'string' => $GLOBALS['egw']->translation->convert($options['path'],'utf-8'),
|
||||
'relatives' => array(RELATIVE_ROOT), // filename is relative to the vfs-root
|
||||
'attributes'=> $attributes,
|
||||
);
|
||||
$this->vfs->set_attributes($vfs_data);
|
||||
}
|
||||
if ($this->debug)
|
||||
{
|
||||
error_log(__CLASS__.'::'.__METHOD__.": path=$options[path], props=".implode(', ',$props));
|
||||
if ($attributes) error_log(__CLASS__.'::'.__METHOD__.": path=$options[path], set attributes=".str_replace("\n",' ',print_r($attributes,true)));
|
||||
error_log(__METHOD__.": path=$options[path], props=".implode(', ',$props));
|
||||
if ($attributes) error_log(__METHOD__.": path=$options[path], set attributes=".str_replace("\n",' ',print_r($attributes,true)));
|
||||
}
|
||||
|
||||
|
||||
return ""; // this is as the filesystem example handler does it, no true or false ...
|
||||
}
|
||||
|
||||
/**
|
||||
* LOCK method handler
|
||||
*
|
||||
* @param array general parameter passing array
|
||||
* @return bool true on success
|
||||
*/
|
||||
function LOCK(&$options)
|
||||
{
|
||||
// behaving like LOCK is not implemented
|
||||
return "412 Precondition failed";
|
||||
/*
|
||||
// get absolute fs path to requested resource
|
||||
$fspath = $this->base . $options["path"];
|
||||
|
||||
// TODO recursive locks on directories not supported yet
|
||||
if (is_dir($fspath) && !empty($options["depth"])) {
|
||||
return "409 Conflict";
|
||||
}
|
||||
|
||||
$options["timeout"] = time()+300; // 5min. hardcoded
|
||||
|
||||
if (isset($options["update"])) { // Lock Update
|
||||
$where = "WHERE path = '$options[path]' AND token = '$options[update]'";
|
||||
|
||||
$query = "SELECT owner, exclusivelock FROM {$this->db_prefix}locks $where";
|
||||
$res = mysql_query($query);
|
||||
$row = mysql_fetch_assoc($res);
|
||||
mysql_free_result($res);
|
||||
|
||||
if (is_array($row)) {
|
||||
$query = "UPDATE {$this->db_prefix}locks
|
||||
SET expires = '$options[timeout]'
|
||||
, modified = ".time()."
|
||||
$where";
|
||||
mysql_query($query);
|
||||
|
||||
$options['owner'] = $row['owner'];
|
||||
$options['scope'] = $row["exclusivelock"] ? "exclusive" : "shared";
|
||||
$options['type'] = $row["exclusivelock"] ? "write" : "read";
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$query = "INSERT INTO {$this->db_prefix}locks
|
||||
SET token = '$options[locktoken]'
|
||||
, path = '$options[path]'
|
||||
, created = ".time()."
|
||||
, modified = ".time()."
|
||||
, owner = '$options[owner]'
|
||||
, expires = '$options[timeout]'
|
||||
, exclusivelock = " .($options['scope'] === "exclusive" ? "1" : "0")
|
||||
;
|
||||
mysql_query($query);
|
||||
|
||||
return mysql_affected_rows() ? "200 OK" : "409 Conflict";*/
|
||||
}
|
||||
|
||||
/**
|
||||
* UNLOCK method handler
|
||||
*
|
||||
* @param array general parameter passing array
|
||||
* @return bool true on success
|
||||
*/
|
||||
function UNLOCK(&$options)
|
||||
{
|
||||
// behaving like LOCK is not implemented
|
||||
return "405 Method not allowed";
|
||||
/*
|
||||
$query = "DELETE FROM {$this->db_prefix}locks
|
||||
WHERE path = '$options[path]'
|
||||
AND token = '$options[token]'";
|
||||
mysql_query($query);
|
||||
|
||||
return mysql_affected_rows() ? "204 No Content" : "409 Conflict";*/
|
||||
}
|
||||
|
||||
/**
|
||||
* checkLock() helper
|
||||
*
|
||||
* @param string resource path to check for locks
|
||||
* @return bool true on success
|
||||
*/
|
||||
function checkLock($path)
|
||||
{
|
||||
// behave like checkLock is not implemented
|
||||
return false;
|
||||
/*
|
||||
$result = false;
|
||||
|
||||
$query = "SELECT owner, token, created, modified, expires, exclusivelock
|
||||
FROM {$this->db_prefix}locks
|
||||
WHERE path = '$path'
|
||||
";
|
||||
$res = mysql_query($query);
|
||||
|
||||
if ($res) {
|
||||
$row = mysql_fetch_array($res);
|
||||
mysql_free_result($res);
|
||||
|
||||
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']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove not (yet) implemented LOCK methods, so we can use the mostly unchanged HTTP_WebDAV_Server_Filesystem class
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function _allow()
|
||||
{
|
||||
$allow = parent::_allow();
|
||||
unset($allow['LOCK']);
|
||||
unset($allow['UNLOCK']);
|
||||
return $allow;
|
||||
}
|
||||
|
||||
/**
|
||||
* auth check in the session creation in dav.php, to avoid being redirected to login.php
|
||||
*
|
||||
* @param string $type
|
||||
|
Loading…
Reference in New Issue
Block a user