diff --git a/inc/caldav-PROPPATCH.php b/inc/caldav-PROPPATCH.php
index 5ec43e16..882b1e3d 100644
--- a/inc/caldav-PROPPATCH.php
+++ b/inc/caldav-PROPPATCH.php
@@ -89,15 +89,20 @@ foreach( $setprops AS $k => $setting ) {
case 'DAV::resourcetype':
/**
- * We don't allow a collection to change to/from a resource. Only collections may be CalDAV calendars.
+ * We only allow resourcetype setting on a normal collection, and not on a resource, a principal or a bind.
+ * Only collections may be CalDAV calendars or addressbooks, and they may not be both.
*/
- $setcollection = count($setting->GetPath('DAV::resourcetype/DAV::collection'));
- $setcalendar = count($setting->GetPath('DAV::resourcetype/urn:ietf:params:xml:ns:caldav:calendar'));
- if ( $request->IsCollection() && $setcollection && ! $dav_resource->IsBinding() ) {
+ $setcollection = count($setting->GetPath('DAV::resourcetype/DAV::collection'));
+ $setcalendar = count($setting->GetPath('DAV::resourcetype/urn:ietf:params:xml:ns:caldav:calendar'));
+ $setaddressbook = count($setting->GetPath('DAV::resourcetype/urn:ietf:params:xml:ns:carddav:addressbook'));
+ if ( $request->IsCollection() && $setcollection && ! $dav_resource->IsPrincipal()
+ && ! $dav_resource->IsBinding() && ! ($setaddressbook && $setcalendar) ) {
$resourcetypes = $setting->GetPath('DAV::resourcetype/*');
$resourcetypes = str_replace( "\n", "", implode('',$resourcetypes));
- $qry->QDo('UPDATE collection SET is_calendar = :is_calendar::boolean, resourcetypes = :resourcetypes WHERE dav_name = :dav_name',
- array( ':dav_name' => $dav_resource->dav_name(), ':is_calendar' => $setcalendar, ':resourcetypes' => $resourcetypes) );
+ $qry->QDo('UPDATE collection SET is_calendar = :is_calendar::boolean, is_addressbook = :is_addressbook::boolean,
+ resourcetypes = :resourcetypes WHERE dav_name = :dav_name',
+ array( ':dav_name' => $dav_resource->dav_name(), ':resourcetypes' => $resourcetypes,
+ ':is_calendar' => $setcalendar, ':is_addressbook' => $setaddressbook ) );
$success[$tag] = 1;
}
else {
@@ -190,27 +195,14 @@ foreach( $rmprops AS $k => $setting ) {
switch( $tag ) {
case 'DAV::resourcetype':
- /**
- * We don't allow a collection to change to/from a resource. Only collections may be CalDAV calendars.
- */
- $rmcollection = (count($setting->GetPath('DAV::resourcetype/DAV::collection')) > 0);
- $rmcalendar = (count($setting->GetPath('DAV::resourcetype/urn:ietf:params:xml:ns:caldav:calendar')) > 0);
- if ( $request->IsCollection() && !$rmcollection ) {
- dbg_error_log( 'PROPPATCH', ' RMProperty %s : IsCollection=%d, rmcoll=%d, rmcal=%d', $tag, $request->IsCollection(), $rmcollection, $rmcalendar );
- if ( $rmcalendar ) {
- $qry->QDo('UPDATE collection SET is_calendar = FALSE, resourcetypes = :resourcetypes WHERE dav_name = :dav_name',
- array( ':dav_name' => $dav_resource->dav_name(), ':resourcetypes' => '') );
- }
- $success[$tag] = 1;
- }
- else {
- $failure['rm-'.$tag] = new XMLElement( 'propstat', array(
- new XMLElement( 'prop', new XMLElement($tag)),
- new XMLElement( 'status', 'HTTP/1.1 409 Conflict' ),
- new XMLElement( 'responsedescription', translate("Resources may not be changed to / from collections.") )
- ));
- dbg_error_log( 'PROPPATCH', ' RMProperty %s Resources may not be changed to / from Collections.', $tag);
- }
+ $failure['rm-'.$tag] = new XMLElement( 'propstat', array(
+ new XMLElement( 'prop', new XMLElement($tag)),
+ new XMLElement( 'status', 'HTTP/1.1 403 Forbidden' ),
+ new XMLElement( 'responsedescription', array(
+ new XMLElement( 'error', new XMLElement( 'cannot-modify-protected-property') ),
+ translate("DAV::resourcetype may only be set to a new value, it may not be removed.") )
+ )
+ ));
break;
case 'urn:ietf:params:xml:ns:caldav:calendar-timezone':
diff --git a/testing/tests/regression-suite/840-Spec-PROPPATCH-1.result b/testing/tests/regression-suite/840-Spec-PROPPATCH-1.result
index a95be63e..e930d7be 100644
--- a/testing/tests/regression-suite/840-Spec-PROPPATCH-1.result
+++ b/testing/tests/regression-suite/840-Spec-PROPPATCH-1.result
@@ -1,21 +1,44 @@
-HTTP/1.1 200 OK
+HTTP/1.1 207 Multi-Status
Date: Dow, 01 Jan 2000 00:00:00 GMT
DAV: 1, 2, access-control, calendar-access, calendar-schedule, extended-mkcol, calendar-proxy
-Content-Length: 224
+Content-Length: 742
Content-Type: text/xml; charset="utf-8"
/caldav.php/user1/home/
- All requested changes were made.
+
+
+
+
+ HTTP/1.1 403 Forbidden
+
+
+
+
+
+
+
+
+
+
+ HTTP/1.1 424 Failed Dependency
+
+
+
+
+
+ HTTP/1.1 424 Failed Dependency
+
+ Some properties were not able to be changed.
changed_last_60se: >1<
- dav_displayname: >User One's Not Calendar<
- is_calendar: >0<
- resourcetypes: ><
+ dav_displayname: >user1 home<
+ is_calendar: >1<
+ resourcetypes: ><
changed_by: >10<
changed_last_30se: >1<
@@ -29,9 +52,3 @@ changed_last_30se: >1<
property_name: >http://apple.com/ns/ical/:calendar-order<
property_value: >1<
- changed_by: >10<
-changed_last_30se: >1<
- dav_name: >/user1/home/<
- property_name: >urn:mcmillan:bogus:xml:ns:davical:arbitrary<
- property_value: >A completely bogus property which should be saved.<
-
diff --git a/testing/tests/regression-suite/842-Spec-PROPPATCH-3.result b/testing/tests/regression-suite/842-Spec-PROPPATCH-3.result
index 740150d2..6ddd7b78 100644
--- a/testing/tests/regression-suite/842-Spec-PROPPATCH-3.result
+++ b/testing/tests/regression-suite/842-Spec-PROPPATCH-3.result
@@ -1,7 +1,7 @@
HTTP/1.1 207 Multi-Status
Date: Dow, 01 Jan 2000 00:00:00 GMT
DAV: 1, 2, access-control, calendar-access, calendar-schedule, extended-mkcol, calendar-proxy
-Content-Length: 449
+Content-Length: 469
Content-Type: text/xml; charset="utf-8"
@@ -12,8 +12,12 @@ Content-Type: text/xml; charset="utf-8"
- HTTP/1.1 409 Conflict
- Resources may not be changed to / from collections.
+ HTTP/1.1 403 Forbidden
+
+
+
+
+
Some properties were not able to be changed.
diff --git a/testing/tests/regression-suite/844-Spec-PROPPATCH-addressbook.result b/testing/tests/regression-suite/844-Spec-PROPPATCH-addressbook.result
new file mode 100644
index 00000000..db52722a
--- /dev/null
+++ b/testing/tests/regression-suite/844-Spec-PROPPATCH-addressbook.result
@@ -0,0 +1,20 @@
+HTTP/1.1 200 OK
+Date: Dow, 01 Jan 2000 00:00:00 GMT
+DAV: 1, 2, access-control, calendar-access, calendar-schedule, extended-mkcol, calendar-proxy
+Content-Length: 224
+Content-Type: text/xml; charset="utf-8"
+
+
+
+
+ /caldav.php/user1/home/
+ All requested changes were made.
+
+
+
+ changed_last_5m: >1<
+ dav_displayname: >User One's addressbook<
+ is_addressbook: >1<
+ is_calendar: >0<
+ resourcetypes: ><
+
diff --git a/testing/tests/regression-suite/844-Spec-PROPPATCH-addressbook.test b/testing/tests/regression-suite/844-Spec-PROPPATCH-addressbook.test
new file mode 100644
index 00000000..e599f4f9
--- /dev/null
+++ b/testing/tests/regression-suite/844-Spec-PROPPATCH-addressbook.test
@@ -0,0 +1,32 @@
+#
+# Check for support of PROPPATCH method
+#
+# Convert the collection to an addressbook, and change the displayname
+# again
+#
+TYPE=PROPPATCH
+URL=http://regression.host/caldav.php/user1/home/
+HEADER=User-agent: SpecTest PROPPATCH
+HEADER=Content-type: text/xml
+HEAD
+
+BEGINDATA
+
+
+
+
+
+
+
+
+ User One's addressbook
+
+
+
+ENDDATA
+
+QUERY
+SELECT dav_displayname, is_calendar, is_addressbook, resourcetypes,
+ modified > (current_timestamp - '5 minutes'::interval) AS changed_last_5m
+ FROM collection WHERE dav_name = '/user1/home/';
+ENDQUERY
diff --git a/testing/tests/regression-suite/845-Spec-PROPPATCH-both-fail.result b/testing/tests/regression-suite/845-Spec-PROPPATCH-both-fail.result
new file mode 100644
index 00000000..2153d66a
--- /dev/null
+++ b/testing/tests/regression-suite/845-Spec-PROPPATCH-both-fail.result
@@ -0,0 +1,31 @@
+HTTP/1.1 207 Multi-Status
+Date: Dow, 01 Jan 2000 00:00:00 GMT
+DAV: 1, 2, access-control, calendar-access, calendar-schedule, extended-mkcol, calendar-proxy
+Content-Length: 469
+Content-Type: text/xml; charset="utf-8"
+
+
+
+
+ /caldav.php/user1/home/
+
+
+
+
+ HTTP/1.1 403 Forbidden
+
+
+
+
+
+
+ Some properties were not able to be changed.
+
+
+
+ changed_last_5m: >1<
+ dav_displayname: >User One's addressbook<
+ is_addressbook: >1<
+ is_calendar: >0<
+ resourcetypes: ><
+
diff --git a/testing/tests/regression-suite/845-Spec-PROPPATCH-both-fail.test b/testing/tests/regression-suite/845-Spec-PROPPATCH-both-fail.test
new file mode 100644
index 00000000..8447f9c4
--- /dev/null
+++ b/testing/tests/regression-suite/845-Spec-PROPPATCH-both-fail.test
@@ -0,0 +1,31 @@
+#
+# Check for support of PROPPATCH method
+#
+# Try (and fail) to set the collection to be both an addressbook and a calendar.
+#
+TYPE=PROPPATCH
+URL=http://regression.host/caldav.php/user1/home/
+HEADER=User-agent: SpecTest PROPPATCH
+HEADER=Content-type: text/xml
+HEAD
+
+BEGINDATA
+
+
+
+
+
+
+
+
+
+
+
+
+ENDDATA
+
+QUERY
+SELECT dav_displayname, is_calendar, is_addressbook, resourcetypes,
+ modified > (current_timestamp - '5 minutes'::interval) AS changed_last_5m
+ FROM collection WHERE dav_name = '/user1/home/';
+ENDQUERY
diff --git a/testing/tests/regression-suite/846-Spec-PROPPATCH-calendar.result b/testing/tests/regression-suite/846-Spec-PROPPATCH-calendar.result
new file mode 100644
index 00000000..47ef5a8e
--- /dev/null
+++ b/testing/tests/regression-suite/846-Spec-PROPPATCH-calendar.result
@@ -0,0 +1,20 @@
+HTTP/1.1 200 OK
+Date: Dow, 01 Jan 2000 00:00:00 GMT
+DAV: 1, 2, access-control, calendar-access, calendar-schedule, extended-mkcol, calendar-proxy
+Content-Length: 224
+Content-Type: text/xml; charset="utf-8"
+
+
+
+
+ /caldav.php/user1/home/
+ All requested changes were made.
+
+
+
+ changed_last_5m: >1<
+ dav_displayname: >User 1's Calendaranza<
+ is_addressbook: >0<
+ is_calendar: >1<
+ resourcetypes: ><
+
diff --git a/testing/tests/regression-suite/846-Spec-PROPPATCH-calendar.test b/testing/tests/regression-suite/846-Spec-PROPPATCH-calendar.test
new file mode 100644
index 00000000..ecc1a9a0
--- /dev/null
+++ b/testing/tests/regression-suite/846-Spec-PROPPATCH-calendar.test
@@ -0,0 +1,32 @@
+#
+# Check for support of PROPPATCH method
+#
+# Try (and fail) to set the collection to be both an addressbook and a calendar.
+#
+TYPE=PROPPATCH
+URL=http://regression.host/caldav.php/user1/home/
+HEADER=User-agent: SpecTest PROPPATCH
+HEADER=Content-type: text/xml
+HEAD
+
+BEGINDATA
+
+
+
+
+
+
+
+
+
+ User 1's Calendaranza
+
+
+
+ENDDATA
+
+QUERY
+SELECT dav_displayname, is_addressbook, is_calendar, resourcetypes,
+ modified > (current_timestamp - '5 minutes'::interval) AS changed_last_5m
+ FROM collection WHERE dav_name = '/user1/home/';
+ENDQUERY