Upgrading from SabreDAV 1.3 to 1.4

In order to add the new SabreDAV features in 1.4, it was needed to break API compatibility in a number of places.

This document describes each. Items in this list are ordered by how likely you are to be affected by it. Every section starts with a paragraph explaining why it would be relevant to you.

Changed handing of 'guessing the base uri'

Every SabreDAV version before 1.4.2 had a bug where in some circumstances it would be possible for users to delete an entire directory tree, if no fixed base uri was set and the user tried to access a file ending in ".php".

This functionality has been changed to be a bit 'dumber' in guessing the base uri. For some users an error might occur when the server is accessed directly through a server.php (or similar named file) and no / is set at the end.

You are strongly encouraged to simply set the base uri manually by calling setBaseUri on the Sabre_DAV_Server object.

Sabre_DAV_Auth_Backend* API changed

This is important if you created a custom authentication backend.

The Sabre_DAV_Auth_Backend_Abstract class is now removed. If you extended that class directly, you must now implement the Sabre_DAV_Auth_IBackend interface instead.

The interface no longer has a getUsers method, and you can remove this method as well.

The 'getCurrentUser' method must now no longer return an array with user information, but only a single username instead.

If you extended Sabre_DAV_Auth_Backend_AbstractDigest, the API has also slightly changed. The getUserInfo() method has been removed, and a getDigestHash method has been added to replace it.

This method must return the 'A1' digest hash. Before this was returned by getUserInfo as part of the array, but this method must only return this string.

New security model for CalDAV

This section is relevant to you if you're a CalDAV user and you're not using Sabre_CalDAV_Server, but a customized setup instead.

SabreDAV now has partly support for WebDAV ACL (rfc3744). This is added through a plugin (Sabre_DAVACL_Plugin). If this plugin is not added to your server, all users will be able to access and modify all other users' calendars. If this is an issue for you, simply add the ACL plugin to your server:

$server->addPlugin(new Sabre_DAVACL_Plugin());

Note again: Sabre_CalDAV_Server adds this plugin by default, so you won't have to worry about it.

Locks backends API changes

This is relevant to you if you built your own locks backend class.

There were a few bugs in how SabreDAV handled looks in child objects. In order to fix this an API change was needed.

The getLocks() method in Sabre_DAV_Locks_Backend_Abstract now takes a second argument, $returnChildLocks.

If this argument is set to true, your backend should also return any lock that's deep within the tree.

For example, a node at uri directory/sub/file.txt has a write lock. If getLocks('directory',true) is called, your backend should also return the child's lock.

Sabre_DAV_Locks_Backend_FS now deprecated

This is relevant to you, if you use Sabre_DAV_Locks_Backend_FS.

Due to a locking bug it was needed to recursively look for locks on nodes. Because of how Sabre_DAV_Locks_Backend_FS works, this was very hard to implement without a major performance penalty.

So this backend still contains the locking bug, that can be described as follows:

If a file is locked deep in a directory tree, it's possible still to delete (any of) it's parents.

To remedy this, you should switch to one of the following backends:

The 'File' backend was created to replace the FS backend, and stores all the locking information in a single file. For performance and stability reasons you are highly encouraged to use PDO instead. PDO stores locks in a MySQL or SQLite database, and is therefore much more robust.

Office 2000 & 2003 compatibility

This is relevant to you if you use Office as a WebDAV client.

Since 1.4 SabreDAV returns the {DAV:}lockroot element, according to the specification. It was reported that Office doesn't like this property very much, and breaks.

We want to be compliant with the standard, so SabreDAV does return the {DAV:}lockroot element by default. If you want to turn this off, you can do so with the following line of code:

Sabre_DAV_Property_LockDiscovery::$hideLockRoot = true;

Principal system and Authentication system are decoupled (part 1)

This is important to you, if you're using the CalDAV system, and you're using the standard PDO backends, or Sabre_CalDAV_Server.

This change was needed, because principals needed many new features, and it seemed like a bad idea to build it into the Sabre_DAV_Auth system. The result is that if you don't use principals (basically if you don't use CalDAV) the authentication system is more lightweight.

There are two new database tables. principals and groupmembers. Both MUST exist.

MySQL:

CREATE TABLE principals (
        id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
        uri VARCHAR(100) NOT NULL,
        email VARCHAR(80),
        displayname VARCHAR(80),
        UNIQUE(uri)
);

CREATE TABLE groupmembers (
        id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
        principal_id INTEGER UNSIGNED NOT NULL,
        member_id INTEGER UNSIGNED NOT NULL,
        UNIQUE(principal_id, member_id)
);

SQLite:

CREATE TABLE principals (
        id INTEGER PRIMARY KEY ASC, 
        uri TEXT,
        email TEXT,
        displayname TEXT,
        UNIQUE(uri)
);

CREATE TABLE groupmembers (
        id INTEGER PRIMARY KEY ASC,
        principal_id INTEGER,
        member_id INTEGER,
        UNIQUE(principal_id, member_id)
);

Your users also require entries in the principals table now.

The easiest way to go about this (if you used the standard PDO classes) is a query like this (mysql example):

INSERT INTO principals (uri, email, displayname)
  SELECT CONCAT('principals/', username), email, username FROM users 

So also keep in mind for the future that if you add a new user to your system, an entry must be added to the users table for your user to log in, and an entry must be added for the principals table for the user to show up in the tree.

Principal and Authentication systems are decoupled (part 2)

If you either constructed a custom authentication backend, or if you instantiated Sabre_DAV_Auth_Backend yourself and you are a CalDAV user, this is relevant to you.

The principal system (which is responsible for listing users) is now no longer managed by Sabre_DAV_Auth_Backend_, but Sabre_DAVACL_PrincipalBackend_ instead.

If you used Sabre_DAV_Auth_Backend_PDO, you must now also instantiate Sabre_DAVACL_PrincipalBackend_PDO.

If you created your own Authentication backend, you must now also create your own Principal backend. Implement Sabre_DAVACL_IPrincipalBackend for this.

Note that the principal system also has group support (the membership methods). Implementing this is optional, but required if you'd like calendar delegation support.

Principal and Authentication systems are decoupled (part 3)

If you used any of the following classes, this is relevant to you.

The following classes have been renamed and moved from Sabre_DAV_Auth to Sabre_DAVACL:

From To
Sabre_DAV_Auth_Principal Sabre_DAVACL_IPrincipal if you have custom-built principal classes.
Sabre_DAV_Auth_Principal Sabre_DAVACL_Principal If you need the default principal class.
Sabre_DAV_Auth_Principal Sabre_CalDAV_Principal_User For the CalDAV specific principal (with delegation suport).
Sabre_DAV_Auth_PrincipalCollection Sabre_DAVACL_PrincipalCollection For the standard principal collection.
Sabre_DAV_Auth_PrincipalCollection Sabre_CalDAV_Principal_Collection For the CalDAV-specific principal collection (with delegation support).

Principal and Authentication systems are decoupled (part 4)

This section is relevant to you, if you're instantiating either of the following classes yourself:

In short, if you instantiated any of these objects yourself, the constructor signature slightly changed.

Before it needed an instance of Sabre_DAV_Auth_Backend_Abstract, but now it needs an instance of Sabre_DAVACL_IPrincipalBackend.