diff options
Diffstat (limited to 'include/reddav.php')
-rw-r--r-- | include/reddav.php | 424 |
1 files changed, 384 insertions, 40 deletions
diff --git a/include/reddav.php b/include/reddav.php index c24414610..79c68a000 100644 --- a/include/reddav.php +++ b/include/reddav.php @@ -1,7 +1,9 @@ <?php /** @file */ use Sabre\DAV; - require_once('vendor/autoload.php'); +require_once('vendor/autoload.php'); + +require_once('include/attach.php'); class RedInode implements DAV\INode { @@ -70,65 +72,146 @@ class RedInode implements DAV\INode { } -abstract class RedDirectory extends DAV\Node implements DAV\ICollection { +class RedDirectory extends DAV\Node implements DAV\ICollection { private $red_path; - private $dir_key; + private $ext_path; + private $root_dir = ''; private $auth; - private $channel_id; - function __construct($red_path,$auth_plugin) { - $this->red_path = $red_path; + + + function __construct($ext_path,&$auth_plugin) { + logger('RedDirectory::__construct() ' . $ext_path); + $this->ext_path = $ext_path; + $this->red_path = ((strpos($ext_path,'/cloud') === 0) ? substr($ext_path,6) : $ext_path); + if(! $this->red_path) + $this->red_path = '/'; $this->auth = $auth_plugin; + logger('Red_Directory: ' . print_r($this,true)); + + } function getChildren() { - if(! perm_is_allowed($this->channel_id,'','view_storage')) - return array(); + logger('RedDirectory::getChildren : ' . print_r($this,true)); - $ret = array(); - $r = q("select distinct filename from attach where folder = '%s' and uid = %d group by filename", - dbesc($this->dir_key), - intval($this->channel_id) - ); - if($r) { - foreach($r as $rr) { - $ret[] = $rr['filename']; - } + if(get_config('system','block_public') && (! $this->auth->channel_id) && (! $this->auth->observer)) { + throw new DAV\Exception\Forbidden('Permission denied.'); + return; + } + + if(! perm_is_allowed($this->auth->channel_id,$this->auth->observer,'view_storage')) { + throw new DAV\Exception\Forbidden('Permission denied.'); + return; } - return $ret; + + return RedCollectionData($this->red_path,$this->auth); } function getChild($name) { - if(! perm_is_allowed($this->channel_id,'','view_storage')) { + + + logger('RedDirectory::getChild : ' . $name); + logger('RedDirectory::getChild : ' . print_r($this,true)); + + if(get_config('system','block_public') && (! $this->auth->channel_id) && (! $this->auth->observer)) { + throw new DAV\Exception\Forbidden('Permission denied.'); + return; + } + + if(! perm_is_allowed($this->auth->channel_id,$this->auth->observer,'view_storage')) { throw new DAV\Exception\Forbidden('Permission denied.'); return; } -// FIXME check revisions - - $r = q("select * from attach where folder = '%s' and filename = '%s' and uid = %d limit 1", - dbesc($this->dir_key), - dbesc($name), - dbesc($this->channel_id) - ); - if(! $r) { - throw new DAV\Exception\NotFound('The file with name: ' . $name . ' could not be found'); - } + if($this->red_path === '/' && $name === 'cloud') { + return new RedDirectory('/cloud', $this->auth); + } + $x = RedFileData($this->ext_path . '/' . $name, $this->auth); + logger('RedFileData returns: ' . print_r($x,true)); + if($x) + return $x; + throw new DAV\Exception\NotFound('The file with name: ' . $name . ' could not be found'); } + function getName() { + logger('RedDirectory::getName : ' . print_r($this,true)); + logger('RedDirectory::getName returns: ' . basename($this->red_path)); + + return (basename($this->red_path)); + } + + + function createFile($name,$data = null) { + logger('RedDirectory::createFile : ' . $name); + logger('RedDirectory::createFile : ' . print_r($this,true)); + + logger('createFile():' . stream_get_contents($data)); + + + if(! perm_is_allowed($this->auth->channel_id,$this->auth->observer,'write_storage')) { + logger('createFile: permission denied'); + throw new DAV\Exception\Forbidden('Permission denied.'); + return; + } + + $mimetype = z_mime_content_type($name); + + + $c = q("select * from channel where channel_id = %d limit 1", + intval($this->auth->channel_id) + ); + + + $filesize = 0; + $hash = random_string(); +dbg(1); + $r = q("INSERT INTO attach ( aid, uid, hash, filename, filetype, filesize, revision, data, created, edited ) + VALUES ( %d, %d, '%s', '%s', '%s', %d, %d, '%s', '%s', '%s' ) ", + intval($c[0]['channel_account_id']), + intval($c[0]['channel_id']), + dbesc($hash), + dbesc($name), + dbesc($mimetype), + intval($filesize), + intval(0), + dbesc(stream_get_contents($data)), + dbesc(datetime_convert()), + dbesc(datetime_convert()) + ); + + $r = q("update attach set filesize = length(data) where hash = '%s' and uid = %d limit 1", + dbesc($hash), + intval($c[0]['channel_id']) + ); + + +dbg(0); + } + function createDirectory($name) { + if(! perm_is_allowed($this->auth->channel_id,$this->auth->observer,'write_storage')) { + throw new DAV\Exception\Forbidden('Permission denied.'); + return; + } + + + + + + @@ -136,12 +219,17 @@ abstract class RedDirectory extends DAV\Node implements DAV\ICollection { function childExists($name) { - $r = q("select distinct filename from attach where folder = '%s' and filename = '%s' and uid = %d group by filename", - dbesc($this->dir_key), - dbesc($name), - intval($this->channel_id) - ); - if($r) + + logger('RedDirectory::childExists : ' . print_r($this->auth,true)); + + if($this->red_path === '/' && $name === 'cloud') { + logger('RedDirectory::childExists /cloud: true'); + return true; + } + + $x = RedFileData($this->ext_path . '/' . $name, $this->auth,true); + logger('RedFileData returns: ' . print_r($x,true)); + if($x) return true; return false; @@ -150,31 +238,81 @@ abstract class RedDirectory extends DAV\Node implements DAV\ICollection { } -abstract class RedFile extends DAV\Node implements DAV\IFile { +class RedFile extends DAV\Node implements DAV\IFile { private $data; + private $auth; + private $name; - - function __construct($data) { + function __construct($name, $data, &$auth) { + logger('RedFile::_construct: ' . $name); + $this->name = $name; $this->data = $data; + $this->auth = $auth; + + logger('RedFile::_construct: ' . print_r($this->data,true)); + } + + + function getName() { + logger('RedFile::getName: ' . basename($this->name)); + return basename($this->name); + + } + + + function setName($newName) { + logger('RedFile::setName: ' . basename($this->name) . ' -> ' . $newName); + + if((! $newName) || (! perm_is_allowed($this->auth->channel_id,$this->auth->observer,'write_storage'))) { + throw new DAV\Exception\Forbidden('Permission denied.'); + return; + } + + $newName = str_replace('/','%2F',$newName); + + $r = q("update attach set filename = '%s' where hash = '%s' and id = %d limit 1", + dbesc($this->data['filename']), + intval($this->data['id']) + ); } function put($data) { + logger('RedFile::put: ' . basename($this->name)); + logger('put():' . stream_get_contents($data)); + +dbg(1); + $r = q("update attach set data = '%s' where hash = '%s' and uid = %d limit 1", + dbesc(stream_get_contents($data)), + dbesc($this->data['hash']), + intval($this->data['uid']) + ); + $r = q("update attach set filesize = length(data) where hash = '%s' and uid = %d limit 1", + dbesc($this->data['hash']), + intval($this->data['uid']) + ); +dbg(0); } function get() { + logger('RedFile::get: ' . basename($this->name)); + $r = q("select data from attach where hash = '%s' and uid = %d limit 1", + dbesc($this->data['hash']), + intval($this->data['uid']) + ); + if($r) return $r[0]['data']; } function getETag() { - - + logger('RedFile::getETag: ' . basename($this->name)); + return $this->data['hash']; } @@ -188,9 +326,215 @@ abstract class RedFile extends DAV\Node implements DAV\IFile { return $this->data['filesize']; } + + function getLastModified() { + logger('RedFile::getLastModified: ' . basename($this->name)); + return $this->data['edited']; + } + + +} + +function RedChannelList(&$auth) { + + $ret = array(); + + $r = q("select channel_id, channel_address from channel where not (channel_pageflags & %d)", + intval(PAGE_REMOVED) + ); + + if($r) { + foreach($r as $rr) { + if(perm_is_allowed($rr['channel_id'],$auth->observer,'view_storage')) { + $ret[] = new RedDirectory('/cloud/' . $rr['channel_address'],$auth); + } + } + } + return $ret; + } +function RedCollectionData($file,&$auth) { + + $ret = array(); + + $x = strpos($file,'/cloud'); + if($x === 0) { + $file = substr($file,6); + } + + +logger('RedCollectionData: ' . $file); + + if((! $file) || ($file === '/')) { + return RedChannelList($auth); + + } + + $file = trim($file,'/'); + $path_arr = explode('/', $file); + + if(! $path_arr) + return null; + + $channel_name = $path_arr[0]; + + $r = q("select channel_id from channel where channel_address = '%s' limit 1", + dbesc($channel_name) + ); + +logger('dbg1: ' . print_r($r,true)); + + if(! $r) + return null; + + $channel_id = $r[0]['channel_id']; + + $path = '/' . $channel_name; + + $folder = ''; + + for($x = 1; $x < count($path_arr); $x ++) { + $r = q("select id, hash, filename, flags from attach where folder = '%s' and (flags & %d)", + dbesc($folder), + intval($channel_id), + intval(ATTACH_FLAG_DIR) + ); + if($r && ( $r[0]['flags'] & ATTACH_FLAG_DIR)) { + $folder = $r[0]['hash']; + $path = $path . '/' . $r[0]['filename']; + } + } + +logger('dbg2: ' . print_r($r,true)); + + if($path !== '/' . $file) { + logger("RedCollectionData: Path mismatch: $path !== /$file"); + return NULL; + } + + $ret = array(); + + + $r = q("select id, uid, hash, filename, filetype, filesize, revision, folder, flags, created, edited from attach where folder = '%s' and uid = %d group by filename", + dbesc($folder), + intval($channel_id) + ); + +logger('dbg2: ' . print_r($r,true)); + foreach($r as $rr) { + if($rr['flags'] & ATTACH_FLAG_DIR) + $ret[] = new RedDirectory('/cloud' . $path . '/' . $rr['filename'],$auth); + else + $ret[] = new RedFile('/cloud' . $path . '/' . $rr['filename'],$rr,$auth); + } + + return $ret; + +} + +function RedFileData($file, &$auth,$test = false) { + +logger('RedFileData:' . $file); + + + $x = strpos($file,'/cloud'); + if($x === 0) { + $file = substr($file,6); + } + +logger('RedFileData2: ' . $file); + + if((! $file) || ($file === '/')) { + return RedDirectory('/',$auth); + + } + + $file = trim($file,'/'); + +logger('file=' . $file); + + $path_arr = explode('/', $file); + + if(! $path_arr) + return null; + + logger("file = $file - path = " . print_r($path_arr,true)); + + $channel_name = $path_arr[0]; + + + $r = q("select channel_id from channel where channel_address = '%s' limit 1", + dbesc($channel_name) + ); + + logger('dbg0: ' . print_r($r,true)); + + if(! $r) + return null; + + $channel_id = $r[0]['channel_id']; + + $path = '/' . $channel_name; + + $folder = ''; +//dbg(1); + + require_once('include/security.php'); + $perms = permissions_sql($channel_id); + + $errors = false; + + for($x = 1; $x < count($path_arr); $x ++) { +dbg(1); + $r = q("select id, hash, filename, flags from attach where folder = '%s' and uid = %d and (flags & %d) $perms", + dbesc($folder), + intval($channel_id), + intval(ATTACH_FLAG_DIR) + ); +dbg(0); + logger('dbg1: ' . print_r($r,true)); + + if($r && ( $r[0]['flags'] & ATTACH_FLAG_DIR)) { + $folder = $r[0]['hash']; + $path = $path . '/' . $r[0]['filename']; + } + if(! $r) { + $r = q("select id, uid, hash, filename, filetype, filesize, revision, folder, flags, created, edited from attach + where folder = '%s' and filename = '%s' and uid = %d $perms group by filename limit 1", + dbesc($folder), + basename($file), + intval($channel_id) + + ); + } + if(! $r) + $errors = true; + } + + logger('dbg1: ' . print_r($r,true)); + + if($path === '/' . $file) { + // final component was a directory. + return new RedDirectory('/cloud/' . $file,$auth); + } + + if($errors) { + if($test) + return false; + throw new DAV\Exception\Forbidden('Permission denied.'); + return; + } + + if($r) { + if($r[0]['flags'] & ATTACH_FLAG_DIR) + return new RedDirectory('/cloud' . $path . '/' . $r[0]['filename'],$auth); + else + return new RedFile('/cloud' . $path . '/' . $r[0]['filename'],$r[0],$auth); + } + return false; +} |