SabreDAV 1.5 released with CardDAV support

sabredav_200x60.png

Over the last month I've been working hard at the Atmail office in sunny Australia to get CardDAV support built into SabreDAV; and I've finally completed all the steps to do this release.

So there it is, CardDAV. Unfortunately there are not yet a lot of clients who actually use it, and it mainly comes down to iOS and OS/X, but I've been asked about CardDAV a lot and suspect more people will become interested in this protocol (especially if more vendors start supporting it).

So that's pretty much it; head over to download page to fetch a copy. I've had to break a couple of minor api's, you can read about those in the migration document.

I tried my best to write good documentation for the new stuff, but it's always very time consuming, and not as good as I'd like If you have time and the will to write more, let me know!

Lastly, a big thank you to Nick Boutelier for creating the new SabreDAV logo!

SabreDAV 1.4.0-beta released

Last Saturday I put up version SabreDAV 1.4.

It's taken a while to get this one out. Much longer than I thought. The result was that there's been very little released over the past few months. In an effort to change this, I decided to release 1.4.0 as soon as possible, rather than when all the features are ready. I believe this is better for the end-user and for me as well (release early, release often, etc).

So there it is. These are the new major features:

  • WebDAV ACL support. This part is not 100% done. It can be integrated into existing API's, but there's no central ACL store or ability to modify ACL's through the WebDAV protocol yet. These additional features will be added in subsequent versions.
  • CalDAV proxy support. This is a proprietary apple extension, allowing users to delegate calendar access to other users.
  • Integrated the 'VObject' library, which provides an easy way to read and write iCalendar objects with an api similar to SimpleXML.
  • Added the ICSExportPlugin, allowing you to export iCalendar-formatted calendars.

full changelog

To allow for a proper ACL implementation, much of the 'principal' functionality has been moved from Sabre_DAV_Auth to Sabre_DAVACL. There's a Migration guide available with all the details.

As usual, if you're not ready to migrate to 1.4 because of the API breaks or because it's still considered beta, I'll be maintaining 1.3 for at least another year. However, I'll be doing this on a strictly on-demand basis. So if you need a bugfix backported or a release, feel free to ask on the mailing list.

Lastly, thanks to all the users. The number of deployments and feedback is steadily growing and that's very rewarding.

Download here.

iCalendar / vCard parser for PHP

I've just finished an iCalendar vCard parser for PHP. It's done almost completely with a 'natural' simplexml-like interface, so it should (hopefully) be just as easy to parse, and also modify iCalendar / vCard objects (ics/vcf files).

To install using pear, run the following:

  1. pear channel-discover pear.sabredav.org
  2. pear install sabredav/Sabre_VObject-alpha

Or download from pear.sabredav.org.

For testing, I used this iCalendar file: icalendartest.ics.

To load in an object, you use the Reader class:

  1. // Link to the correct path if you manually dowloaded the package
  2. include 'Sabre/VObject/includes.php';
  3.  
  4. // Reading an object
  5. $calendar = Sabre_VObject_Reader::read(file_get_contents('icalendartest.ics'));

iCalendar objects consist of components (VEVENT, VTODO, VTIMEZONE, etc), properties (SUMMARY, DESCRIPTION, DTSTART, etc) and parameters, which are to properties what attributes are to elements in XML. To show a listing of all events in a calendar, this snippet would work:

  1. echo "There are ", count($calendar->vevent), " events in this calendar\n";
  2.  
  3. // Looping through events
  4. foreach($calendar->vevent as $event) {
  5.  
  6. echo (string)$event->dtstart, ": ", $event->summary, "\n";
  7.  
  8. }

You can easily modify properties:

  1. $calendar->vevent[0]->description = "It's a birthday party";

Creating new objects uses the following syntax:

  1. $todo = new Sabre_VObject_Component('vtodo');
  2. $todo->summary = 'Take out the dog';
  3. $calendar->add($todo);

And to turn your newly modified calendar back into an ics file:

  1. file_put_contents('output.ics', $calendar->serialize());

Lastly, parameters are accessible through array-syntax:

  1. echo (string)$calendar->vevent[0]->dtstart['tzid'], "\n";

I had fun building this, I hope it's useful to you as well. It's 100% unittested, but bugs might still appear due to the complex nature of API. Use at your own risk :). This library will be part of the SabreDAV project, which is also where you can go for the source, report bugs or make suggestions.

SabreDAV 1.3.0 released

I just released version 1.3.0 of SabreDAV. Uptake has been very strong, especially for the CalDAV components. The biggest change is a big performance boost for most tree operations.

To upgrade, download the new file here, or if you installed it using pear:

  1. pear upgrade sabredav/Sabre_DAV
  2. pear upgrade sabredav/Sabre_CalDAV

To install using pear:

  1. pear channel-discover pear.sabredav.org
  2. pear install sabredav/Sabre_DAV
  3. pear install sabredav/Sabre_CalDAV

There is a list of 4 (smallish) backwards compatibility breaks in the API. You can read about it in the migration guide.

Full list of changes:

  • Added: Cache layer in the ObjectTree.
  • Added: childExists method to Sabre_DAV_ICollection. This is an api break, so if you implement Sabre_DAV_ICollection directly, add the method.
  • Changed: Almost all HTTP method implementations now take a uri argument, including events. This allows for internal rerouting of certain calls. If you have custom plugins, make sure they use this argument. If they don't, they will likely still work, but it might get in the way of future changes.
  • Changed: All getETag methods MUST now surround the etag with double-quotes. This was a mistake made in all previous SabreDAV versions. If you don't do this, any If-Match, If-None-Match and If: headers using Etags will work incorrectly. (Issue 85).
  • Added: Sabre_DAV_Auth_Backend_AbstractBasic class, which can be used to easily implement basic authentication.
  • Removed: Sabre_DAV_PermissionDenied class. Use Sabre_DAV_Forbidden instead.
  • Removed: Sabre_DAV_IDirectory interface, use Sabre_DAV_ICollection instead.
  • Added: Browser plugin now uses {DAV:}displayname if this property is available.
  • Added: Tree classes now have a delete and getChildren method.
  • Fixed: If-Modified-Since and If-Unmodified-Since would be incorrect if the date is an exact match.
  • Fixed: Support for multiple ETags in If-Match and If-None-Match headers.
  • Fixed: Improved baseUrl handling.
  • Fixed: Issue 67: Non-seekable stream support in ::put()/::get().
  • Fixed: Issue 65: Invalid dates are now ignored.
  • Updated: Refactoring in Sabre_CalDAV to make everything a bit more ledgable.
  • Fixed: Issue 88, Issue 89: Fixed compatibility for running SabreDAV on Windows.
  • Fixed: Issue 86: Fixed Content-Range top-boundary from 'file size' to 'file size'-1.

I plan to fully keep supporting the 1.2.* branch, but I'll backport bugfixes strictly on an on-demand basis. So far there's been relatively little people stuck on older versions, so I'm only spending time on it in case anyone depends on it.

Thanks to all the people reporting bugs and posting patches!

SabreDAV 1.2 released (with CalDAV support)

It's taken almost 12 months, but I finally finished a CalDAV plugin for SabreDAV. I've stayed within the standard as much as possible, but had to leave out some features that failed to meet the cost/benefit requirement.

Most importantly, there's solid support for Apple iCal, Evolution, Lightning/Sunbird, and the iPhone.

It all uses PDO, and it's tested on both SQLite3 and MySQL.

SabreDAV is primarily intended as a toolkit to implement these protocols in different applications. Despite that, it should be reasonably easy to setup your own CalDAV server. Head over to the instructions to figure out how.

Other changes and additions

  • CalDAV (RFC4791).
  • PDO backends for Locks, Authentication and Calendars.
  • 95% unittesting code coverage. 415 unittests. There's actually more unittesting code now than 'normal' code.
  • ACL (RFC3744) principals. Note that privileges are not yet implemented.
  • Support for Extended MKCOL (RFC5689).
  • Support for current-user-principal (RFC5397).
  • Now throwing an error if you're using Finder on an unsupported server (nginx, apache + fcgi, lighttpd).
  • Support for If-Range, If-Modified-Since, If-Unmodified-Since, If-Match and If-None-Match.
  • There's now 2 distributions. 1 unified zip with all the features, as well as 4 separate pear packages (Sabre, Sabre_HTTP, Sabre_DAV, Sabre_CalDAV).

If you're upgrading from 1.0, some changes have been made. Take a look at the migration guide for more information.

Download.

Future plans

The next big thing will be CardDAV. It won't take nearly as long as CalDAV support, as there are a lot of similarities. In general I feel I should spend a bit less time on this. I've been spending a large portion of my time in developing SabreDAV into a mature project, which can be hard to justify if it's not a source of income. I need to eat, after all.

I'm still enjoying it very much though and the best way to keep me motivated is to let me know you're using it or by requesting a new feature =).

SabreDAV 1.0.9 released & CalDAV news

SabreDAV logo

The last SabreDAV announcement I made here was 1.0.4, which happened in January. Just today I've released 1.0.9, so I figured it's time for a small update.

A public demo site

I've bought the sabredav.org domain, and placed a live demo on it for people to try out. Give it a shot:

Please note that OS/X Finder will not be able to upload files here, because it uses the Chunked Transfer Encoding, which is not supported by sourceforge's webserver Nginx. Read more here.

Bugfixes

There's been a number of small(ish) bugfixes.

  1. Fixed fatal error when a malformed url was called.
  2. Issue 19: Better responses to HEAD requests on collections, improving compatibility with MS Office.
  3. Issue 23: Fixed Allow header, improving compatibility with Evolution.
  4. Issue 21: Typo.
  5. Issue 27: Incorrect encoding of entities in properties.
  6. Issue 29: Missing constant causing fatal error on lock requests with infinite timeouts.

So there it is. You can download the latest version on the googlecode project page.

CalDAV

CalDAV support is going well. Currently iCal, Evolution and Lightning/Sunbird are supported. If you want to test it out, be sure to download the alpha version (1.1.x), and read the related documentation.

IRC

I've also setup an irc channel on freenode.net. If you feel like idling somewhere new, head over to #sabredav.

CalDAV server for PHP

It's been a long time coming, but I finally have some working CalDAV code. The server has been tested with iCal 3.0 and 4.0 (Leopard and Snow leopard), Sunbird 1.0 pre-release and Evolution.

My main goal is to create a general-purpose CalDAV library, rather than a consumer-ready server app. I'm hoping people will be able to use this library to enable CalDAV functionality in their existing applications.

If you're interested in hacking around or testing, you'll have to grab a copy from subversion. Full installation instructions are available. Because of the alpha-stability nature of the code data-loss can occur, so beware!

CalDAV - it's hard!

Over the past little while I've been working on a CalDAV library, and it's tough!

It appears that the spec is very much implemented with the client, rather than the server in mind. The spec writers have left no stone unturned, and it's technically possible to query the server for any odd dataset you might need. Aside from that the authors made absolutely sure there were no duplicated efforts, and built heavily upon the existing WebDAV, WebDAV ACL extensions and iCalendar.

While I generally agree it's a wise thing to not reinvent the wheel, I'm a bit of a pragmatist and feel the complexity of all these layers make it hard to understand, and must have played/will play a factor in the arguably slow adoption rate.

To keep it short, I feel the authors have over-engineered/abstracted the specification. Instead of making simple API's that work for 90% of the usecases, they have gone a much more generic route. This makes it very hard to predict how CalDAV clients will be using the server. Also, it makes it quite difficult to optimize and fit in a simple relational database or existing calendaring software. CalDAV should IMHO just have been a simple CRUD system. Advanced features and reports could have been made optional, and should have been specialized for common usecases.

Incomplete view of Web/CalDAV dependencies

DAV dependencies

This was a graph I used in an earlier post. There's actually a few more specs that are relevant to the implementor.

GroupDAV

GroupDAV deserves a mention here, as it attempts to address most of the issues I have. What it lacks is adoption from ICal, Sunbird and MS Outlook. The only issue I have is the frowned upon use of the PUT method (spec), where POST really should have been used.

Some examples

These will be highly uninteresting unless you have an intimate knowledge of the specs.

New calendars/events/todo's are created using PUT. This means the client now determines the unique id given to any of these objects. Most people will want to integrate CalDAV with systems which already have a different primary key, these people will be required maintaining 2 different id's and ensure there are never any duplicates. The id generated by the client can be any url encoded string. Note that this wouldn't have to be a problem if some POST statement would have been used.

CalDAV requires support for the expand-properties report from rfc 3253. In a nutshell the expand-properties report will look for WebDAV properties containing url, follow these locally and add specified properties from these resources to the DOM. The benefit of this REPORT query is that less HTTP requests/roundtrips have to be made to make this work. The usecase for CalDAV specifically might be a lot simpler though, as it could mean something like 'get me the information of the user owning this calendar'. If it was instead simply required to add functionality that meets exactly that (and a few other usecases), it would be reasonably easy for me to write an optimized SQL query for those cases. Now I should support these lookup queries everywhere, because there's no good way to restrict how clients might use it.

CalDAV also requires fully implementing the ACL spec. The main usecase for this is calendar sharing. While the ACL specification will give you infinite complexity in how to setup your access control, it's quite a bit of work to even send back all the appropriate information and error messaging if you're not actually interested in this feature. Making ACL an optional extension to CalDAV would have been easier for implementers IMHO.

 1

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.