Set properties on nodes for virtual file system

138 views
Skip to first unread message

Redlorry

unread,
Oct 23, 2014, 5:24:29 AM10/23/14
to sabredav...@googlegroups.com
Hi all,

I've setup a virtual file system using Sabredav which works great. I've got all the reads, writes, moves, auth etc working via the database however I'd like be able to do 2 more things, which I think are along the same lines:

1) In Windows when the drive is mounted using NetDrive, it shows used and total space on the drive icon. This by default is 1TB. I'd like to control this so I can set this to whatever space the user has. I've found {DAV:}quota-used-bytes & {DAV:}quota-available-bytes properties, but how can I set them? I assume they need set on the root node.

2) A user may only have read only access so I'd like to set all files and directories with a ro property. I currently have a check on each of the sabredav write functions (put, setName, delete etc) which returns a Forbidden Exception, however Windows doesn't handle it very quickly. If I can set each file as read only then windows should handle it better. The read only property I've found is {DAV:}isreadonly.

Some example code so you can see the general structure. I've removed anything which isn't relevant.

class virtualFile extends \Sabre\DAV\File
{
    public $fileObj;

    function __construct($fileObj)
    {
        $this->fileObj = $fileObj;
    }

    function getName()
    {
        return $this->fileObj->originalFilename;
    }

    // call on an edit or file creation (after createFile)
    function put($data)
    {
        // check for rw access
        virtualWebdavHelper::checkUserHasWrite();
        
        // [removed code]...
    }

    function get()
    {
        // [removed code]...
    }

    function getSize()
    {
        return $this->fileObj->fileSize;
    }

    function setName($newName)
    {
        // check for rw access
        virtualWebdavHelper::checkUserHasWrite();
        
        // [removed code]...
    }

    function getContentType()
    {
        return $this->fileObj->fileType;
    }

    function getLastModified()
    {
        return strtotime($this->fileObj->uploadedDate);
    }

    public function getETag()
    {
        if (strlen($this->fileObj->fileHash))
        {
            return '"' . time() . $this->fileObj->fileHash . '"';
        }

        return null;
    }

    public function delete()
    {
        // check for rw access
        virtualWebdavHelper::checkUserHasWrite();
        
        // [removed code]...
    }
}

class virtualCollection extends Sabre\DAV\Collection
{

    public $folderObj;
    private $userId = null;

    function __construct($folderObj = null)
    {
        // [removed code]...
    }

    function getChildren()
    {
        // [removed code]...
    }

    function getFileChild($fileObj)
    {
        // [removed code]...
    }

    function getFolderChild($folderObj)
    {
        // [removed code]...
    }

    function createDirectory($folderName)
    {
        // check for rw access
        virtualWebdavHelper::checkUserHasWrite();
        
        // [removed code]...
    }

    function getName()
    {
        return $this->folderObj->folderName;
    }

    function setName($newName)
    {
        // check for rw access
        virtualWebdavHelper::checkUserHasWrite();
        
        // [removed code]...
    }

    function getLastModified()
    {
        return time();
    }

    public function delete()
    {
        // check for rw access
        virtualWebdavHelper::checkUserHasWrite();
        
        // [removed code]...
    }

    public function createFile($name, $data = null)
    {
        // check for rw access
        virtualWebdavHelper::checkUserHasWrite();
        
        // [removed code]...
    }

}

// root node
$rootNode = new \virtualCollection(null);

// use our own object tree for better performance and data retention, i.e. for moves, copy etc.
$virtualRootNode = new \virtualObjectTree($rootNode);

// the rootNode needs to be passed to the server object
$server = new DAV\Server($virtualRootNode);

// create base url

// set base path
$server->setBaseUri($url);

// make sure there is a 'data' directory, writable by the server. This directory is used to store information about locks
$lockBackend = new DAV\Locks\Backend\File('/tmp/data.dat');
$lockPlugin  = new DAV\Locks\Plugin($lockBackend);
$server->addPlugin($lockPlugin);

// start
$server->exec();

Thanks in advance,
Red.

Evert Pot

unread,
Oct 23, 2014, 1:48:52 PM10/23/14
to sabredav...@googlegroups.com


On Thursday, October 23, 2014 5:24:29 AM UTC-4, Redlorry wrote:
Hi all,

I've setup a virtual file system using Sabredav which works great. I've got all the reads, writes, moves, auth etc working via the database however I'd like be able to do 2 more things, which I think are along the same lines:

1) In Windows when the drive is mounted using NetDrive, it shows used and total space on the drive icon. This by default is 1TB. I'd like to control this so I can set this to whatever space the user has. I've found {DAV:}quota-used-bytes & {DAV:}quota-available-bytes properties, but how can I set them? I assume they need set on the root node.

In your VirtualCollection, implement Sabre\DAV\IQuota:

https://github.com/fruux/sabre-dav/blob/master/lib/DAV/IQuota.php
 

2) A user may only have read only access so I'd like to set all files and directories with a ro property. I currently have a check on each of the sabredav write functions (put, setName, delete etc) which returns a Forbidden Exception, however Windows doesn't handle it very quickly. If I can set each file as read only then windows should handle it better. The read only property I've found is {DAV:}isreadonly.

Some example code so you can see the general structure. I've removed anything which isn't relevant.

The 'standard webdav' way is to use {DAV:}current-user-privilege-set. You can enable this by using Sabre\DAVACL\IACL.
If you enable that, then you also no longer have to do access control checks on every single method, because the ACL plugin will do that for you and send back appropriate error codes (403 really).

However, Windows won't do anything with those properties. (Modern) windows clients use a different property, namely:

{urn:schemas-microsoft-com:}Win32FileAttributes

I don't think they are able to use {DAV:}readonly, but I'm not sure. I'm also not sure what the format is of this Win32FileAttributes property.

To send back custom properties from a Collection or File object, implement Sabre\DAV\IProperties.

Evert

Redlorry

unread,
Oct 24, 2014, 3:02:54 PM10/24/14
to sabredav...@googlegroups.com
Thanks for the info, very useful.

So for the 1st one iQuota, I'm implementing IQuota on my Collection like this:

class yetiCollection extends Sabre\DAV\Collection implements Sabre\DAV\IQuota
{
...
}

Then testing the getQuotaInfo() method like this:

class yetiCollection extends Sabre\DAV\Collection implements Sabre\DAV\IQuota
{
    function getQuotaInfo()
    {
        return array(100000000, 4000000000);
    }
    ...
}

However I'm still getting 1TB available, 0 used on the drive icon. Any idea what I may be doing wrong or if it's a Windows snag?

Thanks,
Adam.

Evert Pot

unread,
Oct 27, 2014, 4:59:53 PM10/27/14
to sabredav...@googlegroups.com
On Friday, October 24, 2014 4:02:54 PM UTC-3, Redlorry wrote:
Thanks for the info, very useful.

So for the 1st one iQuota, I'm implementing IQuota on my Collection like this:

class yetiCollection extends Sabre\DAV\Collection implements Sabre\DAV\IQuota
{
...
}

Then testing the getQuotaInfo() method like this:

class yetiCollection extends Sabre\DAV\Collection implements Sabre\DAV\IQuota
{
    function getQuotaInfo()
    {
        return array(100000000, 4000000000);
    }
    ...
}

However I'm still getting 1TB available, 0 used on the drive icon. Any idea what I may be doing wrong or if it's a Windows snag?

I believe that Windows will only ask for quota information on the collection that you mounted in windows. So if you mounted the root of the dav server, you need to make that property is defined there. Second: make sure you are running a 64bit PHP version, that second number exceeds the maximum size of an integer in 32bit php.

Evert

Reply all
Reply to author
Forward
0 new messages