SabreDAV 0.3

Just got a new alpha for this WebDAV library, this version mostly contains bugfixes, and:

I found it hard to figure out all non-standard behaviours for the common WebDAV clients, as there wasn't a lot of information to be found on the net. I documented all my findings, which could perhaps be of use for other implementors of the protocol. I'm hoping this will become a good resource for this stuff.

The package is still very much alpha state. Theo reported a segmentation fault while running the package on OS/X + Apache2 + PHP 5.2.5. My own testing environment is Debian Etch + Apache 2 + PHP 5.2.0-8+etch11, and I got some good results there.

Download here.

SabreDAV 0.2

I just put a new release for SabreDAV up.

The most significant change is that it now has a filter which intercepts common files generated by clients and other application, including:

  • OS/X resource forks (._ files)
  • OS/X .DS_Store file
  • Windows' desktop.ini
  • Windows' Thumbs.db
  • ViM-style temporary files.

This is crucial if you want to connect a WebDAV folder to for example a database-table. This makes sure that you don't end up with for example blog posts named .DS_Store ;). Although not completely sure, I believe SabreDAV is unique in that sense. If there are suggestions for more common 'temporary files', please let me know.

Full list of changes:

  • Documentation
  • Support for Windows XP / Vista clients
  • Quota support (by implementing Sabre_DAV_IQuota).
  • A standard FilterTree, which can be used to intercept or change requests to the File-tree
  • Better implementation for PropPatch.
  • Support for lock-null requests.
  • A TemporaryFileFilter class, which can be used to intercept the temporary files mentioned earlier. Just pass it a regular Sabre_DAV_ObjectTree and it will do its thing.

SabreDAV 0.1

I finished a first alpha release for SabreDAV. I'm quite excited, I might add..

Currently it has all the basic tools to create a WebDAV share using PHP, based on either an existing directory structure on the filesystem, your own custom virtual folder or a combination of both.

It has been tested using DavFS and the OS/X finder. And it supports all of the locking features these clients use, making it a fully read-write DAV server.

Some links:

If you like the idea, please support it by adding it to your ohloh stack.

WebDAV updates

I've made a lot of progress on SabreDAV, and felt like it was time for an update.

I pretty much implemented the entire webdav protocol at one point, but I was unhappy with the end-user API. Because this is a pet project and there's no deadlines attached to it, I felt like I could take my sweet time to absolutely nail the structure.

So, I started over.. I learned a lot about the protocol, and by having a good overview on the entire protocol I felt like I did a much better job.. So right now, we have read-only support for OS/X and DavFS and an easy to use API.

If you're a mac or linux user, give it a shot by connection to the endpoint : http://www.rooftopsolutions.nl/dav/ . If you open it directly from the browser it won't give you a nice response. Also, I noticed that OS/X makes a lot of unnecessary requests when its just read only, so it will be a tad slow there.. In order to fix this OS/X needs a DAV class 2 server, with locking support. It doesn't have to be able to write, it just needs the locking HTTP methods.

SabreDAV in action!

What you see in the shot is a combination of 2 things, A normal file system directory containing the vcard and my resume, and a virtual 'articles' directory, which is based entirely on articles from the database.

SabreDAV currently has some helper classes that allow you to easily integrate with the file system, Sabre_DAV_FS_File and Sabre_DAV_FS_Directory. In order to mix virtual and real files I extended Sabre_DAV_FS_Directory and injected in an extra 'fake' directory..

Here's the code to get this up and running, hope it makes sense:

  1. <?php
  2.  
  3. // This is our root directory. Its a standard FS_Directory, but we're injecting the virtual 'articles' directory.
  4. class RooftopDAV extends Sabre_DAV_FS_Directory {
  5.  
  6. function getChildren() {
  7.  
  8. $children = parent::getChildren();
  9. $children[] = new ArticlesDirectory();
  10. return $children;
  11.  
  12. }
  13.  
  14. function getChild($name) {
  15.  
  16. if ($name=='articles') return new ArticlesDirectory();
  17. return parent::getChild($name);
  18.  
  19. }
  20.  
  21. }
  22.  
  23. // This is our articles directory, its entirely virtual.. The only 2 methods we need to implement are getName and getChildren
  24. class ArticlesDirectory extends Sabre_DAV_Directory {
  25.  
  26. function getChildren() {
  27.  
  28. // This is my database abstraction layer, you can make this work for any database (-library/-layer)
  29. $articles = Sabre_DAL_Manager::init()->getRecordSet('blog_posts');
  30. $children = array();
  31.  
  32. foreach($articles->select() as $article) {
  33.  
  34. $children[] = new Article($article);
  35.  
  36. }
  37. return $children;
  38.  
  39. }
  40.  
  41. function getName() {
  42.  
  43. return 'articles';
  44.  
  45. }
  46.  
  47. }
  48.  
  49. // This is our article class.. We need to implement a couple of methods and we're ignoring all methods that change the file.
  50. // Ideally we throw a 403 here, but for the proof of concept, we don't care
  51. class Article implements Sabre_DAV_IFile {
  52.  
  53. private $article;
  54.  
  55. function __construct($article) {
  56. $this->article = $article;
  57.  
  58. }
  59.  
  60. function put($data) {
  61.  
  62. // we'll just ignore this
  63.  
  64. }
  65.  
  66. function delete() {
  67.  
  68. // ignored
  69.  
  70. }
  71.  
  72. function setName($name) {
  73.  
  74. // ignored
  75.  
  76. }
  77.  
  78. function getName() {
  79.  
  80. return $this->article['title'] . '.html';
  81.  
  82. }
  83.  
  84. function get() {
  85.  
  86. return $this->article['description'];
  87.  
  88. }
  89.  
  90. function getSize() {
  91.  
  92. return strlen($this->article['description']);
  93.  
  94. }
  95.  
  96. function getLastModified() {
  97.  
  98. return strtotime($this->article['time']);
  99.  
  100. }
  101.  
  102. }
  103.  
  104. // Setting up our root object
  105. $root = new RooftopDAV('/home/evert/dev/rooftopsolutions.nl/davfolder');
  106.  
  107. // The tree is responsible for dispatching all http methods to our file and directory objects
  108. $tree = new Sabre_DAV_ObjectTree($root);
  109.  
  110. // The server class does the hardcore protocol work
  111. $server = new Sabre_DAV_Server($tree);
  112.  
  113. // We need to make sure the server knows on what url its located
  114. $server->setBaseUri('/dav/');
  115.  
  116. // And off we go
  117. $server->exec();
  118.  
  119. ?>

You can check out the latest version of the code on the project page. Don't depend your life on the current API, as it is subject to change until there's a 1.0.

PHP WebDAV integration library

I recently started writing a WebDAV integration library for PHP.

WebDAV is a nasty beast for a number of reasons, but its a great tool to integrate your existing web infrastructure with a Desktop filesystem. WebDAV is built into every modern operating system since years, but I think the biggest reason we haven't seen a lot of adoption is because of the difficulties with implementing it.

I intend to make this library as easy as possible to use, without making it a black-box-like system. Focus will not be on everything WebDAV could possibly provide, but instead on the features that are actually supported by the operating systems.

Implementing WebDAV will become as simple as creating an implementation of an abstract 'Directory' and an abstract 'File' class.

I'm kind of debating on the following two questions, perhaps a smart reader can comment on these..

  1. WebDAV supports custom properties, and in order to make the Server fully webdav-compliant, it should support these. I'm going to make this an optional feature, but, should this happen on:
    • A File level with a custom interface.
    • Or a global 'Property manager'
    Reason I'm asking, is because while I was working on the sample implementation, it will not be easy to attach custom properties to physical files. Perhaps I should go for a combination of both?
  2. Same question goes for locking of files and directories. Does it make more sense to have a global Lock manager, or should this implemented on a per-file-class basis?

The project is up on Google Code hosting, and I opened up a discussion group as well. If you feel like helping out, or contributing please drop a line there! I'll be needing people writing docs and tutorials, testers, coders and somebody who has some designing skills (no, it's not just a logo, we're actually going to put down something cool..). If required, you can also contact me directly.


About

My name is Evert, and I've been writing semi-regularly on this blog since 2006.

I'm currently available for contract work.

more info.

Subscribe

Dropbox

Dropbox is a simple cross-platform online backup and sync application. The first 2GB of space is free, and both you and me get an extra 250MB extra space if you sign up through this link.