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