2013-10-26 21:48:03 +00:00
< ? php /** @file */
use Sabre\DAV ;
2014-01-02 00:07:36 +00:00
require_once ( 'vendor/autoload.php' );
2013-10-26 21:48:03 +00:00
class RedInode implements DAV\INode {
private $attach ;
function __construct ( $attach ) {
$this -> attach = $attach ;
}
function delete () {
2013-10-28 01:35:40 +00:00
if ( ! perm_is_allowed ( $this -> channel_id , '' , 'view_storage' ))
return ;
2013-10-29 01:43:49 +00:00
/**
* Since I don ' t believe this is documented elsewhere -
* ATTACH_FLAG_OS means that the file contents are stored in the OS
* rather than in the DB - as is the case for attachments .
* Exactly how they are stored ( what path and filename ) are still
* TBD . We will probably not be using the original filename but
* instead the attachment 'hash' as this will prevent folks from
* uploading PHP code onto misconfigured servers and executing it .
* It ' s easy to misconfigure servers because we can provide a
* rule for Apache , but folks using nginx will then be susceptible .
* Then there are those who don ' t understand these kinds of exploits
* and don ' t have any idea allowing uploaded PHP files to be executed
* by the server could be a problem . We also don ' t have any idea what
* executable types are served on their system - like . py , . pyc , . pl , . sh
* . cgi , . exe , . bat , . net , whatever .
*/
2013-10-28 01:35:40 +00:00
if ( $this -> attach [ 'flags' ] & ATTACH_FLAG_OS ) {
// FIXME delete physical file
}
if ( $this -> attach [ 'flags' ] & ATTACH_FLAG_DIR ) {
// FIXME delete contents (recursive?)
}
q ( " delete from attach where id = %d limit 1 " ,
intval ( $this -> attach [ 'id' ])
);
2013-10-26 21:48:03 +00:00
}
function getName () {
return $this -> attach [ 'filename' ];
}
function setName ( $newName ) {
2013-10-28 01:35:40 +00:00
if (( ! $newName ) || ( ! perm_is_allowed ( $this -> channel_id , '' , 'view_storage' )))
return ;
2013-10-26 21:48:03 +00:00
$this -> attach [ 'filename' ] = $newName ;
2013-10-28 01:35:40 +00:00
$r = q ( " update attach set filename = '%s' where id = %d limit 1 " ,
dbesc ( $this -> attach [ 'filename' ]),
intval ( $this -> attach [ 'id' ])
);
2013-10-26 21:48:03 +00:00
}
function getLastModified () {
return $this -> attach [ 'edited' ];
}
}
2014-01-02 00:07:36 +00:00
class RedDirectory extends DAV\Node implements DAV\ICollection {
2013-10-26 21:48:03 +00:00
private $red_path ;
2014-01-02 09:09:57 +00:00
private $ext_path ;
2014-01-02 00:07:36 +00:00
private $root_dir = '' ;
2013-10-26 21:48:03 +00:00
private $auth ;
2014-01-03 01:49:39 +00:00
2013-10-26 21:48:03 +00:00
2014-01-02 00:07:36 +00:00
2014-01-02 09:09:57 +00:00
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 = '/' ;
2013-10-26 21:48:03 +00:00
$this -> auth = $auth_plugin ;
2014-01-02 09:09:57 +00:00
logger ( 'Red_Directory: ' . print_r ( $this , true ));
2014-01-02 00:07:36 +00:00
2013-10-26 21:48:03 +00:00
}
function getChildren () {
2014-01-02 09:09:57 +00:00
logger ( 'RedDirectory::getChildren : ' . print_r ( $this , true ));
2014-01-02 00:07:36 +00:00
2014-01-02 09:09:57 +00:00
if ( get_config ( 'system' , 'block_public' ) && ( ! $this -> auth -> channel_id ) && ( ! $this -> auth -> observer )) {
throw new DAV\Exception\Forbidden ( 'Permission denied.' );
return ;
2014-01-02 00:07:36 +00:00
}
2014-01-03 01:49:39 +00:00
if ( ! perm_is_allowed ( $this -> auth -> channel_id , $this -> auth -> observer , 'view_storage' )) {
throw new DAV\Exception\Forbidden ( 'Permission denied.' );
return ;
}
2014-01-02 00:07:36 +00:00
2014-01-02 09:09:57 +00:00
return RedCollectionData ( $this -> red_path , $this -> auth );
2013-10-26 21:48:03 +00:00
}
function getChild ( $name ) {
2014-01-02 00:07:36 +00:00
logger ( 'RedDirectory::getChild : ' . $name );
2014-01-02 09:09:57 +00:00
logger ( 'RedDirectory::getChild : ' . print_r ( $this , true ));
2014-01-02 00:07:36 +00:00
2014-01-02 09:09:57 +00:00
if ( get_config ( 'system' , 'block_public' ) && ( ! $this -> auth -> channel_id ) && ( ! $this -> auth -> observer )) {
2013-10-28 01:35:40 +00:00
throw new DAV\Exception\Forbidden ( 'Permission denied.' );
2013-10-26 21:48:03 +00:00
return ;
}
2014-01-02 09:09:57 +00:00
if ( ! perm_is_allowed ( $this -> auth -> channel_id , $this -> auth -> observer , 'view_storage' )) {
throw new DAV\Exception\Forbidden ( 'Permission denied.' );
return ;
2014-01-02 00:07:36 +00:00
}
2014-01-02 09:09:57 +00:00
if ( $this -> red_path === '/' && $name === 'cloud' ) {
return new RedDirectory ( '/cloud' , $this -> auth );
2014-01-02 00:07:36 +00:00
}
2014-01-03 01:49:39 +00:00
$x = RedFileData ( $this -> ext_path . '/' . $name , $this -> auth );
2014-01-02 09:09:57 +00:00
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' );
2013-10-26 21:48:03 +00:00
2014-01-02 00:07:36 +00:00
}
function getName () {
2014-01-02 09:09:57 +00:00
logger ( 'RedDirectory::getName : ' . print_r ( $this , true ));
2014-01-03 01:49:39 +00:00
logger ( 'RedDirectory::getName returns: ' . basename ( $this -> red_path ));
2014-01-02 09:09:57 +00:00
return ( basename ( $this -> red_path ));
2013-10-26 21:48:03 +00:00
}
2014-01-03 01:49:39 +00:00
2013-10-26 21:48:03 +00:00
function createFile ( $name , $data = null ) {
2014-01-03 01:49:39 +00:00
if ( ! perm_is_allowed ( $this -> auth -> channel_id , $this -> auth -> observer , 'write_storage' )) {
throw new DAV\Exception\Forbidden ( 'Permission denied.' );
return ;
}
2013-10-26 21:48:03 +00:00
}
function createDirectory ( $name ) {
2014-01-03 01:49:39 +00:00
if ( ! perm_is_allowed ( $this -> auth -> channel_id , $this -> auth -> observer , 'write_storage' )) {
throw new DAV\Exception\Forbidden ( 'Permission denied.' );
return ;
}
2013-10-26 21:48:03 +00:00
}
function childExists ( $name ) {
2014-01-02 00:07:36 +00:00
logger ( 'RedDirectory::childExists : ' . print_r ( $this -> auth , true ));
2014-01-03 01:49:39 +00:00
if ( $this -> red_path === '/' && $name === 'cloud' ) {
return true ;
}
$x = RedFileData ( $this -> ext_path . '/' . $name , $this -> auth );
logger ( 'RedFileData returns: ' . print_r ( $x , true ));
if ( $x )
2013-10-28 01:35:40 +00:00
return true ;
return false ;
2013-10-26 21:48:03 +00:00
}
}
2014-01-02 00:07:36 +00:00
class RedFile extends DAV\Node implements DAV\IFile {
2013-10-26 21:48:03 +00:00
private $data ;
2014-01-02 00:07:36 +00:00
private $auth ;
private $name ;
2013-10-26 21:48:03 +00:00
2014-01-03 01:49:39 +00:00
function __construct ( $name , $data , & $auth ) {
2014-01-02 00:07:36 +00:00
logger ( 'RedFile::_construct: ' . $name );
$this -> name = $name ;
2014-01-03 01:49:39 +00:00
$this -> data = $data ;
2014-01-02 00:07:36 +00:00
$this -> auth = $auth ;
2013-10-26 21:48:03 +00:00
2014-01-02 00:07:36 +00:00
logger ( 'RedFile::_construct: ' . print_r ( $this -> data , true ));
2013-10-26 21:48:03 +00:00
}
2014-01-02 00:07:36 +00:00
function getName () {
2014-01-03 01:49:39 +00:00
logger ( 'RedFile::getName: ' . basename ( $this -> name ));
return basename ( $this -> name );
2014-01-02 00:07:36 +00:00
}
2013-10-26 21:48:03 +00:00
2014-01-03 01:49:39 +00:00
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' ])
);
2013-10-26 21:48:03 +00:00
}
2014-01-03 01:49:39 +00:00
function put ( $data ) {
logger ( 'RedFile::put: ' . basename ( $this -> name ));
$r = q ( " update attach set data = '%s' where hash = '%s' and uid = %d limit 1 " ,
dbesc ( $data ),
dbesc ( $this -> data [ 'hash' ]),
intval ( $this -> data [ 'uid' ])
);
}
2013-10-26 21:48:03 +00:00
function get () {
2014-01-03 01:49:39 +00:00
logger ( 'RedFile::get: ' . basename ( $this -> name ));
2013-10-26 21:48:03 +00:00
2014-01-03 01:49:39 +00:00
$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' ];
2013-10-26 21:48:03 +00:00
}
function getETag () {
2014-01-03 01:49:39 +00:00
logger ( 'RedFile::getETag: ' . basename ( $this -> name ));
return $this -> data [ 'hash' ];
2013-10-26 21:48:03 +00:00
}
function getContentType () {
2014-01-03 01:49:39 +00:00
return $this -> data [ 'filetype' ];
2013-10-26 21:48:03 +00:00
}
function getSize () {
2014-01-03 01:49:39 +00:00
return $this -> data [ 'filesize' ];
2013-10-26 21:48:03 +00:00
}
2014-01-03 01:49:39 +00:00
function getLastModified () {
logger ( 'RedFile::getLastModified: ' . basename ( $this -> name ));
return $this -> data [ 'edited' ];
}
2013-10-26 21:48:03 +00:00
}
2014-01-02 09:09:57 +00:00
function RedChannelList ( & $auth ) {
2013-10-26 21:48:03 +00:00
2014-01-02 09:09:57 +00:00
$ret = array ();
2014-01-02 00:07:36 +00:00
2014-01-03 01:49:39 +00:00
$r = q ( " select channel_id, channel_address from channel where not (channel_pageflags & %d) " ,
2014-01-02 09:09:57 +00:00
intval ( PAGE_REMOVED )
);
2013-10-26 21:48:03 +00:00
2014-01-02 09:09:57 +00:00
if ( $r ) {
foreach ( $r as $rr ) {
2014-01-03 01:49:39 +00:00
if ( perm_is_allowed ( $rr [ 'channel_id' ], $auth -> observer , 'view_storage' )) {
$ret [] = new RedDirectory ( '/cloud/' . $rr [ 'channel_address' ], $auth );
}
2014-01-02 09:09:57 +00:00
}
}
return $ret ;
}
function RedCollectionData ( $file , & $auth ) {
$ret = array ();
$x = strpos ( $file , '/cloud' );
if ( $x === 0 ) {
$file = substr ( $file , 6 );
}
2014-01-03 01:49:39 +00:00
logger ( 'RedCollectionData: ' . $file );
2014-01-02 09:09:57 +00:00
if (( ! $file ) || ( $file === '/' )) {
return RedChannelList ( $auth );
}
$file = trim ( $file , '/' );
$path_arr = explode ( '/' , $file );
2014-01-02 00:07:36 +00:00
if ( ! $path_arr )
return null ;
$channel_name = $path_arr [ 0 ];
2014-01-03 01:49:39 +00:00
$r = q ( " select channel_id from channel where channel_address = '%s' limit 1 " ,
2014-01-02 09:09:57 +00:00
dbesc ( $channel_name )
);
2014-01-03 01:49:39 +00:00
logger ( 'dbg1: ' . print_r ( $r , true ));
2014-01-02 09:09:57 +00:00
if ( ! $r )
return null ;
$channel_id = $r [ 0 ][ 'channel_id' ];
$path = '/' . $channel_name ;
2014-01-02 00:07:36 +00:00
$folder = '' ;
2014-01-02 09:09:57 +00:00
for ( $x = 1 ; $x < count ( $path_arr ); $x ++ ) {
2014-01-03 01:49:39 +00:00
$r = q ( " select id, hash, filename, flags from attach where folder = '%s' and (flags & %d) " ,
2014-01-02 00:07:36 +00:00
dbesc ( $folder ),
2014-01-02 09:09:57 +00:00
intval ( $channel_id ),
intval ( ATTACH_FLAG_DIR )
2014-01-02 00:07:36 +00:00
);
2014-01-02 09:09:57 +00:00
if ( $r && ( $r [ 0 ][ 'flags' ] & ATTACH_FLAG_DIR )) {
$folder = $r [ 0 ][ 'hash' ];
$path = $path . '/' . $r [ 0 ][ 'filename' ];
}
}
2014-01-02 00:07:36 +00:00
2014-01-03 01:49:39 +00:00
logger ( 'dbg2: ' . print_r ( $r , true ));
2014-01-02 09:09:57 +00:00
if ( $path !== '/' . $file ) {
logger ( " RedCollectionData: Path mismatch: $path !== / $file " );
return NULL ;
}
$ret = array ();
2014-01-03 01:49:39 +00:00
$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 " ,
2014-01-02 09:09:57 +00:00
dbesc ( $folder ),
2014-01-03 01:49:39 +00:00
intval ( $channel_id )
2014-01-02 09:09:57 +00:00
);
2014-01-03 01:49:39 +00:00
logger ( 'dbg2: ' . print_r ( $r , true ));
2014-01-02 09:09:57 +00:00
foreach ( $r as $rr ) {
if ( $rr [ 'flags' ] & ATTACH_FLAG_DIR )
$ret [] = new RedDirectory ( '/cloud' . $path . '/' . $rr [ 'filename' ], $auth );
else
2014-01-03 01:49:39 +00:00
$ret [] = new RedFile ( '/cloud' . $path . '/' . $rr [ 'filename' ], $rr , $auth );
2014-01-02 09:09:57 +00:00
}
return $ret ;
}
function RedFileData ( $file , & $auth ) {
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 ];
2014-01-03 01:49:39 +00:00
2014-01-02 09:09:57 +00:00
$r = q ( " select channel_id from channel where channel_address = '%s' limit 1 " ,
dbesc ( $channel_name )
);
2014-01-03 01:49:39 +00:00
logger ( 'dbg0: ' . print_r ( $r , true ));
2014-01-02 09:09:57 +00:00
if ( ! $r )
return null ;
$channel_id = $r [ 0 ][ 'channel_id' ];
$path = '/' . $channel_name ;
$folder = '' ;
//dbg(1);
2014-01-03 01:49:39 +00:00
require_once ( 'include/security.php' );
$perms = permissions_sql ( $channel_id );
$errors = false ;
2014-01-02 09:09:57 +00:00
for ( $x = 1 ; $x < count ( $path_arr ); $x ++ ) {
2014-01-03 01:49:39 +00:00
dbg ( 1 );
$r = q ( " select id, hash, filename, flags from attach where folder = '%s' and uid = %d and (flags & %d) $perms " ,
2014-01-02 09:09:57 +00:00
dbesc ( $folder ),
intval ( $channel_id ),
intval ( ATTACH_FLAG_DIR )
);
2014-01-03 01:49:39 +00:00
dbg ( 0 );
logger ( 'dbg1: ' . print_r ( $r , true ));
2014-01-02 09:09:57 +00:00
if ( $r && ( $r [ 0 ][ 'flags' ] & ATTACH_FLAG_DIR )) {
$folder = $r [ 0 ][ 'hash' ];
$path = $path . '/' . $r [ 0 ][ 'filename' ];
}
2014-01-03 01:49:39 +00:00
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 ;
2014-01-02 09:09:57 +00:00
}
2014-01-03 01:49:39 +00:00
logger ( 'dbg1: ' . print_r ( $r , true ));
2014-01-02 09:09:57 +00:00
if ( $path === '/' . $file ) {
// final component was a directory.
return new RedDirectory ( '/cloud/' . $file , $auth );
}
2014-01-03 01:49:39 +00:00
if ( $errors ) {
throw new DAV\Exception\Forbidden ( 'Permission denied.' );
return ;
2014-01-02 00:07:36 +00:00
}
2014-01-03 01:49:39 +00:00
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 );
2014-01-02 00:07:36 +00:00
}
2013-10-26 21:48:03 +00:00