* @license PHP License * @package WB * @subpackage vfs */ WBClass::load('WBString' , 'HTTP_WebDAV_Server'); /** * CAUTION! * * Still, WebDAV implementation has some stumbling blocks - consider it as experimental. * * One thing is, that it uses the PEAR package HTTP_WebDAV_Server which doesn't seem * to work as good as promised. Also there may be some bugs in this code, as well. * * Further more locking is missing, for locking you need a table like the following. * Also see methods * @see todoCHECKLOCK() * @see todoLOCK() * @see todoUNLOCK() * DROP TABLE IF EXISTS wbvfswebdavlock; CREATE TABLE wbvfswebdavlock ( vfsdid int(11) UNSIGNED NOT NULL DEFAULT 0, vfsfid int(11) UNSIGNED NOT NULL DEFAULT 0, token varchar(255) NOT NULL DEFAULT '', uid int(11) UNSIGNED NOT NULL DEFAULT 0, `expire` datetime NOT NULL default '0000-00-00 00:00:00', created datetime NOT NULL default '0000-00-00 00:00:00', changed datetime NOT NULL default '0000-00-00 00:00:00', `scope`enum('shared', 'exclusive') NOT NULL DEFAULT 'shared', PRIMARY KEY (vfsdid, vfsfid) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='store per user folders'; */ /** * Virtual File System: WebDAV Server * * Utilize PEAR's WebDAV Server class * * @version 0.6.0 * @package WB * @subpackage vfs */ class WBVFS_WebDAV extends HTTP_WebDAV_Server { const PATH_NON = 0; const PATH_ROOT = 1; const PATH_PARTITION = 2; const PATH_DIR = 3; const PATH_FILE = 4; /** * Table name for locks */ const TABLE_LOCK = 'vfswebdavlock'; /** * http header powered by string * @var string */ public $dav_powered_by = 'Wombat VFS WebDAV V1.0'; /** * http authentication realm * @var string */ public $http_auth_realm = 'Wombat VFS WebDAV'; /** * current user * @var WBUser_Auth */ private $user; /** * Explorer * @var WBVFS_Explorer */ private $expl; /** * File * @var WBVFS_File */ private $file; /** * Logger * @var WBLog */ private $log; /** * WebDAV Server config * @var WBConfig */ private $config; /** * Table access * @var WBDatasource_Table */ private $table; /** * constructor * * Parameter list * - requesturi * * @param array $parameter */ public function __construct($parameter = array()) { // start session WBClass::create('patSession', array('container' => 'HttpAuth')); WBClass::load('WBLog'); $this->log = WBLog::start(__CLASS__); $this->log->debug($parameter); $this->config = WBClass::create('WBConfig'); $this->config->load('vfs/webdav'); $this->http_auth_realm = $this->config->get('access/authrealm', $this->http_auth_realm); WBClass::load('WBUser_Auth'); $this->user = WBUser_Auth::getCurrent(); $this->table = WBClass::create('WBDatasource_Table'); /* * funny hack which is required in some PHP versions * * Usually this is done by parent's constructor function named "HTTP_WebDAV_Server". * Unfortunately, in PHP4 constructors now must be named "__construct". Hence it should * not be executed any more. The funny thing is that it works fine on some servers * but fail on others * * The drawback is that the parent's constructor may be executed twice... */ parent::HTTP_WebDAV_Server(); } /** * WebDAV: PROPFIND * * * @todo support inifinity depth * @param array $options * @param array $files for file properties * @return bool|string true on success, HTTP status otherwise */ public function PROPFIND(&$options, &$files) { $files['files'] = array(); $path = trim($options['path'], '/ '); $part = null; $dir = null; $file = null; $part = null; $type = $this->checkPath($path, $part, $dir, $file); switch ($type) { case self::PATH_ROOT: $path = ''; $node = null; break; case self::PATH_NON: $path = ''; $node = null; return false; break; case self::PATH_PARTITION: $node = array( 'name' => $path, 'created' => gmdate('Y-m-d H:i:s'), 'changed' => gmdate('Y-m-d H:i:s') ); break; case self::PATH_DIR: case self::PATH_FILE: $node = $this->expl->getDir($dir); $path = $part . '/' . $this->expl->getPath($dir, true); break; } $path = explode('/', $path); array_pop($path); if (empty($path)) { $path = ''; } else { $path = '/' . implode('/', $path); } $files['files'][] = $this->node2DirProps($node, $path); if ($node) { $path .= '/' . $node['name']; } // zero depth if (0 == $options['depth']) { $log = array( 'method' => 'propfind', 'path' => $options['path'], 'depth' => $options['depth'], 'dir' => $dir ); $this->log->notice($log); return true; } $log = array( 'method' => 'propfind', 'path' => $options['path'], 'depth' => $options['depth'], 'dir' => $dir, 'dirs' => 0, 'files' => 0 ); // dirs $list = $this->listDir($type, $dir); $log['dirs'] = count($list); foreach ($list as $l) { $files['files'][] = $this->node2DirProps($l, $path); } // files $list = $this->listFile($type, $dir); $log['files'] = count($list); foreach ($list as $l) { $files['files'][] = $this->node2FileProps($l, $path); } $this->log->debug($log); return true; } /** * WebDAV: GET * * @param array $options * @return bool|string true on success, HTTP status otherwise */ public function GET(&$options) { $path = trim($options['path'], '/ '); $part = null; $dir = null; $file = null; $type = $this->checkPath($path, $part, $dir, $file); $log = array( 'method' => 'get', 'path' => $options['path'], 'dir' => $dir, 'file' => '' ); if (self::PATH_FILE != $type) { $this->log->warn($log); $this->profindHTML($path, $type, $dir); return '200 OK'; } $file = $this->file->loadByData($file); $log['file'] = $file->getId(); $this->log->notice($log); $options['mimetype'] = $file->getMime(WBVFS_File::MIME_MAJOR | WBVFS_File::MIME_MINOR); $options['mtime'] = $file->getChanged(); $options['size'] = $file->getSize(); $options['stream'] = fopen($file->getPath() . '.org', 'r'); return true; } /** * WebDAV: MKCOL * * @param array $options * @return bool|string true on success, HTTP status otherwise */ public function MKCOL(&$options) { $path = trim($options['path'], '/ '); $path = explode('/', $path); $name = array_pop($path); $path = implode('/', $path); $part = null; $dir = null; $file = null; $type = $this->checkPath($path, $part, $dir, $file); $log = array( 'method' => 'mkcol', 'path' => $options['path'], 'dir' => '' ); switch ($type) { case self::PATH_NON: case self::PATH_FILE: case self::PATH_ROOT: $this->log->notice($log); return '403 Forbidden'; break; default; break; } $log['dir'] = $this->expl->mkDir($dir, $name); $this->log->notice($log); return '201 Created'; } /** * WebDAV: PUT * * @param array $options * @return bool|string true on success, HTTP status otherwise */ public function PUT(&$options) { $path = trim($options['path'], '/ '); $path = explode('/', $path); $name = array_pop($path); $path = implode('/', $path); $part = null; $dir = null; $file = null; $type = $this->checkPath($path, $part, $dir, $file); if (empty($dir)) { $dir = 0; } $this->log->warn($options); $log = array( 'method' => 'put', 'path' => $options['path'], 'dir' => $dir, 'file' => '', 'size' => 0 ); switch ($type) { case self::PATH_FILE: case self::PATH_NON: case self::PATH_ROOT: $log['error'] = 'wrong folder'; $this->log->notice($log); return '403 Forbidden'; break; default; break; } $tmp = WBClass::create('WBFile'); $tmp->tempnam('vfsDavPut'); $des = fopen($tmp->realpath(), 'w'); while ($buffer = fread($options['stream'], 8192)) { fwrite($des, $buffer); } fclose($des); fclose($options['stream']); $log['size'] = filesize($tmp->realpath()); $ok = $this->file->checkQuota($log['size']); if (WBVFS_File::QUOTA_OK != $ok) { $log['error'] = 'quota exceeded'; $this->log->notice($log); return '507 Insufficient Storage'; } // remove old file $list = $this->file->listDir($dir); foreach ($list as $l) { if ($l['name'] != $name) { continue; } $file = $this->file->loadByData($l); if (10 < $file->getSize()) { $log['error'] = 'file exists'; $this->log->notice($log); return '403 Forbidden'; } $log['file'] = $file->getId(); $log['method'] = 'put-override'; $log['size'] = $file->getSize(); $this->log->warn($log); $log['method'] = 'put'; $file->delete(); } // store new file $this->file->setCurrentDir($dir); $file = $this->file->import($tmp->realpath(), $name); if ($file->isOK()) { $log['file'] = $file->getId(); $this->log->notice($log); return '201 Created'; } $log['error'] = 'unkown'; $this->log->notice($log); return '409 Conflict'; } /** * WebDAV: COPY * * @param array $options * @return bool|string true on success, HTTP status otherwise */ public function COPY(&$options) { $log = array( 'action' => 'copy' ); $src = array(); $des = array(); $error = $this->checkSrcDes($options, $src, $des, $log); if (!empty($error)) { return $error; } if (empty($src['file'])) { return $this->copyDir($options, $src, $des, $log); } else { return $this->copyFile($options, $src, $des, $log); } return '400 Bad request'; } /** * WebDAV: MOVE * * @param array $options * @return bool|string true on success, HTTP status otherwise */ public function MOVE(&$options) { $log = array( 'action' => 'move' ); $src = array(); $des = array(); $error = $this->checkSrcDes($options, $src, $des, $log); if (!empty($error)) { return $error; } if (empty($src['file'])) { return $this->moveDir($options, $src, $des, $log); } else { return $this->moveFile($options, $src, $des, $log); } return '400 Bad request'; } /** * List directories * * @param int $type * @param string $dir * @return array */ private function listDir($type, $dir) { if (self::PATH_NON == $type || self::PATH_FILE == $type) { return array(); } if (self::PATH_ROOT == $type) { return $this->getPartitions(); } if (self::PATH_PARTITION == $type) { $dir = 0; } return $this->expl->lsDir($dir); } /** * List files * * @param int $type * @param string $dir * @return array */ private function listFile($type, $dir) { switch ($type) { case self::PATH_NON: case self::PATH_ROOT: case self::PATH_FILE: return array(); break; case self::PATH_PARTITION: $dir = 0; break; } return $this->file->listDir($dir); } /** * * */ private function profindHTML($path, $type, $dir) { $title = $this->http_auth_realm; $tableDir = $path; $html = << $title

$title

Use a proper WebDAV client for full access. See: http://en.wikipedia.org/wiki/WebDAV

Path: /$tableDir

EOF; if (!empty($path)) { $path .= '/'; } echo WBString::replaceSuperPlaceholders($html); $dirs = $this->listDir($type, $dir); if (!empty($dirs)) { echo '

Folders

'; } // fixed width directory column format $format = '%1$s%3$s%4$s'; $files = $this->listFile($type, $dir); if (!empty($files)) { echo <<Files EOF; foreach ($files as $f) { $html = sprintf($format, $f['name'], $path, $f['size'], $f['changed']); echo WBString::replaceSuperPlaceholders($html); } echo '
Name Size Last Modified
'; } echo << EOF; } /** * Actually copy the file * * Copy file to other folder and / or rename it * * @param array $options * @param array $src * @param array $des * @param array $log */ private function copyFile($options, $src, $des, $log) { $file = $this->file->loadByData($src['file']); $this->file->setCurrentDir($des['dir']); $new = $this->file->import($file->getPath(), $des['name'], true); if (!$new->isOK()) { $log['error'] = 'could not create new file'; $this->log->warn($log); return '412 precondition failed'; } $log['file'] = $new->getId(); $this->log->notice($log); return '201 Created'; } /** * Actually copy the folder * * Copy dir to other folder and / or rename it * * @param array $options * @param array $src * @param array $des * @param array $log */ private function copyDir($options, $src, $des, $log) { if (!isset($options['depth']) || $options['depth'] != 'infinity') { return '400 Bad Request'; } $dir = $this->expl->mkDir($des['dir'], $des['name']); $this->copySubDirs($src['dir'], $dir); $log['dir'] = $dir; $this->log->notice($log); return '201 Created'; } private function copySubDirs($src, $des, $dirIds = array()) { // avoid loop copies if (in_array($src, $dirIds)) { return; } // copy all files $files = $this->file->listDir($src); $log = array( 'action' => 'copy', 'copy' => 'file', 'src' => '', 'des' => '' ); foreach ($files as $f) { $file = $this->file->loadByData($f); $log['src'] = $file->getId(); $this->file->setCurrentDir($des); $file = $this->file->import($file->getPath(), $f['name'], true); $log['des'] = $file->getId(); $this->log->debug($log); } // copy all folders $dirs = $this->expl->lsDir($src); $log = array( 'action' => 'copy', 'copy' => 'dir', 'src' => '', 'des' => '' ); foreach ($dirs as $d) { $dir = $this->expl->mkDir($des, $d['name']); $log['src'] = $d['id']; $log['des'] = $dir; $this->log->debug($log); $dirIds[] = $dir; $this->copySubDirs($d['id'], $dir, $dirIds); } } /** * Check precondition for copy and move operation * * @param array $options * @param array $src * @param array $des * @param array $log * @return string error string or empty on success */ private function checkSrcDes($options, &$src, &$des, &$log = array()) { $src = array( 'path' => trim($options['path'], '/ '), 'part' => null, 'dir' => null, 'file' => null, 'type' => null ); $des = array( 'path' => trim($options['dest'], '/ '), 'part' => null, 'dir' => null, 'file' => null, 'type' => null, 'name' => null ); $log['src'] = $src['path']; $log['des'] = $des['path']; // same same if ($src['path'] == $des['path']) { $log['error'] = 'src and des are the same'; $this->log->warn($log); return '409 Conflict'; } $src['type'] = $this->checkPath($src['path'], $src['part'], $src['dir'], $src['file']); // only allow to move "normal" files and folder switch ($src['type']) { case self::PATH_NON: case self::PATH_ROOT: case self::PATH_PARTITION: $log['error'] = 'wrong type'; $this->log->warn($log); return '403 Forbidden'; break; } $des['path'] = explode('/', $des['path']); if (2 > count($des['path'])) { $log['error'] = 'bad des path'; $this->log->warn($log); return '400 Bad request'; } $des['name'] = array_pop($des['path']); $des['path'] = implode('/', $des['path']); $des['type'] = $this->checkPath($des['path'], $des['part'], $des['dir'], $des['file']); switch ($des['type']) { case self::PATH_FILE: case self::PATH_NON: case self::PATH_ROOT: $log['error'] = 'wrong type'; $this->log->warn($log); return '403 Forbidden'; break; case self::PATH_PARTITION: $des['dir'] = 0; break; } // cannot move into file if (!empty($des['file'])) { $log['error'] = 'wrong des folder'; $this->log->notice($log); return '400 Bad request'; } // don't allow to move between partitions if ($src['part'] != $des['part']) { $log['error'] = 'src and des must be in same partition'; $this->log->warn($log); return '403 Forbidden'; } // destination name must not exist $siblings = $this->file->listDir($des['dir']); foreach ($siblings as $s) { if ($s['name'] == $name) { $log['error'] = 'des name already exists'; $this->log->warn($log); return '400 Bad request'; } } $siblings = $this->expl->lsDir($des['dir']); foreach ($siblings as $s) { if ($s['name'] == $name) { $log['error'] = 'des name already exists'; $this->log->warn($log); return '400 Bad request'; } } return ''; } /** * Actually move the file * * Move file to other folder and / or rename it * * @param array $options * @param array $src * @param array $des * @param array $log */ private function moveFile($options, $src, $des, $log) { $save = array( 'dir' => $des['dir'], 'name' => $des['name'] ); $this->log->err($save); $file = $this->file->loadByData($src['file']); if (!$file->isOK()) { $log['error'] = 'cannot load src file by data'; $this->log->warn($log); return '412 precondition failed'; } $file->save($save); $this->log->notice($log); return '201 Created'; } /** * Actually move the folder * * Move folder to other folder and / or rename it * * @param array $options * @param array $src * @param array $des * @param array $log */ private function moveDir($options, $src, $des, $log) { if (!isset($options['depth']) || $options['depth'] != 'infinity') { return '400 Bad Request'; } $this->expl->mvDir($src['dir'], $des['dir'], $des['name']); $this->log->notice($log); return '201 Created'; } /** * WebDAV: DELETE * * @param array $options * @return bool|string true on success, HTTP status otherwise */ public function DELETE(&$options) { $path = trim($options['path'], '/ '); $part = null; $dir = null; $file = null; $type = $this->checkPath($path, $part, $dir, $file); $log = array( 'method' => 'delete', 'path' => $options['path'], 'dir' => '', 'file' => '' ); switch ($type) { case self::PATH_FILE: $file = $this->file->loadByData($file); $log['file'] = $file->getId(); $file->delete(); break; case self::PATH_DIR: $log['dir'] = $dir; $this->expl->rmDir($dir); break; case self::PATH_NON: case self::PATH_PARTITION: case self::PATH_ROOT: $this->log->notice($log); return '403 Forbidden'; break; default; break; } $this->log->notice($log); return '204 No Content'; } /** * WebDAV: checklock * * Check if file / dir is locked * * @param string $path check lock on path * @return mixed false in case of no lock, or lock specifications in case there is a lock */ public function todoCHECKLOCK($path) { $path = trim($path, '/ '); $part = null; $dir = null; $file = null; $type = $this->checkPath($path, $part, $dir, $file); switch ($type) { case self::PATH_NON: case self::PATH_PARTITION: case self::PATH_ROOT: return '204 No Content'; break; } if (empty($file)) { $file = array('id' => 0); } $log = array( 'method' => 'checklock', 'dir' => $dir, 'file' => $file['id'], ); $clause = array(); $clause[] = array( 'field' => 'vfsdid', 'value' => $dir ); $clause[] = array( 'field' => 'vfsfid', 'value' => $file['id'] ); $locks = $this->table->get(self::TABLE_LOCK, null, null, $clause); $lock = false; $now = time(); foreach ($locks as $l) { $expire = strtotime($l['expire']); if ($expire < $now) { $clause[2] = array( 'field' => 'token', 'value' => $l['token'] ); $log['nowdate'] = gmdate('Y-m-h H:i:', $now); $log['expiredate'] = gmdate('Y-m-h H:i:', $l['expire']); $log = array_merge($log, $l); $this->log->debug($log); // $this->table->delete(self::TABLE_LOCK, null, null, $clause); unset($log['nowdate']); unset($log['expiredate']); continue; } $lock = array( 'type' => 'write', 'scope' => $l['scope'], 'depth' => 0, 'owner' => $l['uid'], 'token' => $l['token'], 'created' => strtotime($l['created']), 'modified' => strtotime($l['changed']), 'expires' => $expire ); $log = array_merge($log, $l); } $this->log->debug($log); return $lock; } /** * WebDAV: LOCK * * Lock a resouce. Not supported * * @param array $options * @return bool|string true on success, HTTP code on error */ public function todoLOCK(&$options) { $path = trim($options['path'], '/ '); $part = null; $dir = null; $file = null; $type = $this->checkPath($path, $part, $dir, $file); // only allow lock on files and folders switch ($type) { case self::PATH_NON: case self::PATH_PARTITION: case self::PATH_ROOT: return '409 Conflict'; break; } if (empty($file)) { $file = array('id' => 0); } $log = array( 'method' => 'lock', 'path' => $path, 'dir' => $dir, 'file' => $file['id'] ); $log = array_merge($log, $options); $this->log->debug($log); $id = '__new'; $lock = array( 'expire' => gmdate('Y-m-d H:i:s', (time() + 300)), ); $clause = array(); if (isset($options['update'])) { $id = null; $clause = array(); $clause[] = array( 'field' => 'token', 'value' => $options['update'] ); $clause[] = array( 'field' => 'vfsdid', 'value' => $dir ); $clause[] = array( 'field' => 'vfsfid', 'value' => $file['id'] ); } else { $lock['uid'] = $this->user->getId(); $lock['vfsdid'] = $dir; $lock['vfsfid'] = $file['id']; $lock['token'] = $options['locktoken']; $lock['scope'] = $options['scope']; } $log = array_merge($log, $lock); $this->log->notice($log); $this->table->save(self::TABLE_LOCK, $id, $lock, $clause); return '200 OK'; } /** * WebDAV: UNLOCK * * Unlock a resouce. Not supported * * @param array $options * @return bool|string true on success, HTTP code on error */ public function todoUNLOCK(&$options) { $path = trim($options['path'], '/ '); $part = null; $dir = null; $file = null; $type = $this->checkPath($path, $part, $dir, $file); // only allow lock on files and folders switch ($type) { case self::PATH_NON: case self::PATH_PARTITION: case self::PATH_ROOT: return '204 No Content'; break; } if (empty($file)) { $file = array('id' => 0); } $log = array( 'method' => 'unlock', 'path' => $path, 'dir' => $dir, 'file' => $file['id'] ); $log = array_merge($log, $options); $this->log->debug($log); $clause = array(); $clause[] = array( 'field' => 'token', 'value' => $options['token'] ); $clause[] = array( 'field' => 'vfsdid', 'value' => $dir ); $clause[] = array( 'field' => 'vfsfid', 'value' => $file['id'] ); $this->table->delete(self::TABLE_LOCK, null, null, $clause); return '204 No Content'; } /** * Create properties for collection * * @param array $node VFS dir node * @param string $prefix path prefix * @return array */ private function node2DirProps($node, $prefix = '') { if (empty($node)) { $node = array( 'name' => '', 'created' => date('Y-m-d H:i:s'), 'changed' => date('Y-m-d H:i:s') ); } $info = array(); $info['path'] = $prefix . '/' . $node['name']; $props = array(); $props[] = $this->mkprop('name', $node['name']); $props[] = $this->mkprop('displayname', $node['name']); $props[] = $this->mkprop('resourcetype', 'collection'); $props[] = $this->mkprop('getcontenttype', 'httpd/unix-directory'); $props[] = $this->mkprop('creationdate', strtotime($node['created'])); $props[] = $this->mkprop('getlastmodified', strtotime($node['changed'])); $info['props'] = $props; return $info; } /** * Create properties for file * * @param array $node VFS file node * @param string $prefix path prefix * @return array */ private function node2FileProps($node, $prefix = '') { if (empty($node)) { return null; } $file = $this->file->loadByData($node); if (!$file->isOK()) { return null; } $name = $file->getName(); // path file name if (!strstr($name, '.') && 'image' == $file->getMime()) { switch ($file->getMime(WBVFS_File::MIME_MINOR)) { case 'jpeg': $name .= '.jpg'; break; case 'gif': $name .= '.gif'; break; case 'png': $name .= '.png'; break; } } $info = array(); $info['path'] = $prefix . '/' . $name; $props = array(); $props[] = $this->mkprop('name', $name); $props[] = $this->mkprop('displayname', $name); $props[] = $this->mkprop('resourcetype', ''); $props[] = $this->mkprop('getcontenttype', $file->getMime(WBVFS_File::MIME_MAJOR | WBVFS_File::MIME_MINOR)); $props[] = $this->mkprop('creationdate', strtotime($file->getCreated())); $props[] = $this->mkprop('getlastmodified', strtotime($file->getChanged())); $props[] = $this->mkprop('getcontentlength', $file->getSize()); $info['props'] = $props; return $info; } /** * Verify path against VFS * * Find path in VFS, select dir and file * * @param string $path * @param string $partition * @param string $dir id of VFS dir * @param array $file VFS file node * @return int path type: root, dir of file */ protected function checkPath($path, &$partition, &$dir, &$file) { $partition = null; $dir = null; $file = null; $ext = ''; if (empty($path)) { return self::PATH_ROOT; } $path = explode('/', $path); $partition = array_shift($path); $user = $this->getPartition($partition); $this->startVFS($user); if (empty($path)) { return self::PATH_PARTITION; } $path = implode('/', $path); $dir = $this->expl->findPath($path); if ($dir) { return self::PATH_DIR; } $path = explode('/', $path); $name = array_pop($path); if (strstr($name, '.')) { $name = explode('.', $name); $ext = '.' . array_pop($name); $name = implode('.', $name); } $path = implode('/', $path); if (empty($path)) { $dir = null; } else { $dir = $this->expl->findPath($path); if (!$dir) { $dir = null; return self::PATH_NON; } } $files = $this->file->listDir($dir); foreach ($files as $f) { // exact match if ($name . $ext == $f['name']) { $file = $f; break; } // match without extension if ($name == $f['name']) { $file = $f; continue; } } // file not found if (empty($file)) { $dir = null; $file = null; return self::PATH_NON; } return self::PATH_FILE; } /** * Select partition by name * * Check config for patition name and verify user's grants. * Get user id of partition or null of not valid. * * @return string */ private function getPartition($name) { $parts = $this->config->get('partitions'); if (!isset($parts[$name])) { return null; } $p = $parts[$name]; if (!$this->user->isInGroup($p['requiredgroup'])) { return null; } if (isset($p['user'])) { return $p['user']; } return $this->user->getId(); } /** * Get list of partitions * * Get all partitions the current user may access. * Transform partition list to suit webdav collations * * @return array */ private function getPartitions() { $list = array(); $node = array( 'name' => '', 'created' => gmdate('Y-m-d H:i:s'), 'changed' => gmdate('Y-m-d H:i:s') ); $parts = $this->config->get('partitions'); foreach ($parts as $name => $p) { if (!$this->user->isInGroup($p['requiredgroup'])) { continue; } $node['name'] = $name; $list[] = $node; } return $list; } /** * start VFS objects * * Starts explorer and file only once * * @param string $user user id to select partition */ protected function startVFS($user = null) { if ($this->expl) { return; } if (empty($user)) { $user = $this->user->getId(); } $parameter = array( 'user' => $user ); $this->expl = WBClass::create('WBVFS_Explorer', $parameter); $this->file = WBClass::create('WBVFS_File', $parameter); } /** * Check user authentictation * * Login user or return false if user is not logged in * * * @param string $type HTTP Authentication type (Basic, Digest, ...) * @param string $user Username * @param string $pass Password * @return bool */ public function check_auth($type, $user, $pass) { // check for proper user if ($this->user->isAuthenticated()) { $data = $this->user->getData(); if ($user && $user == $data['nickname']) { if (!$this->user->isInGroup($this->config->get('access/requiredgroup', 'vfs'))) { return false; } return true; } $this->user->logout(); } // username and password are required, otherwise login is not possible if (empty($user) || empty($pass)) { return false; } // try to log in. $credential = array( 'nicknameoremail' => $user, 'password' => $pass ); $this->user->login($credential); if (!$this->user->isAuthenticated()) { return false; } if (!$this->user->isInGroup($this->config->get('access/requiredgroup', 'vfs'))) { return false; } return true; } } ?>