Add support for PUT on individual resources within a bind.

This commit is contained in:
Andrew McMillan 2010-03-18 20:02:13 +13:00
parent a1c720d92b
commit 688d540cc5
2 changed files with 58 additions and 89 deletions

View File

@ -594,89 +594,6 @@ EOSQL;
}
/**
* Put the resource from this request - does some checking of things before
* calling write_event to do the actual writing (without any checking).
* @param object $request A reference to the request object
* @param int $author The user_no who wants to put this resource on the server
* @param boolean $caldav_context Whether we are responding via CalDAV or interactively
* @return string Either 'INSERT' or 'UPDATE': the type of action that the PUT resulted in
*/
function putCalendarResource( &$request, $author, $caldav_context ) {
$etag = md5($request->raw_post);
$ic = new iCalComponent( $request->raw_post );
dbg_log_array( 'PUT', 'EVENT', $ic->components, true );
/**
* We read any existing object so we can check the ETag.
*/
unset($put_action_type);
$qry = new AwlQuery( 'SELECT * FROM caldav_data WHERE dav_name=:dav_name', array( ':dav_name' => $request->path ) );
if ( !$qry->Exec('PUT',__LINE__,__FILE__) || $qry->rows() > 1 ) {
rollback_on_error( $caldav_context, $request->user_no, $request->path );
}
elseif ( $qry->rows() < 1 ) {
if ( isset($request->etag_if_match) && $request->etag_if_match != '' ) {
/**
* RFC2068, 14.25:
* If none of the entity tags match, or if "*" is given and no current
* entity exists, the server MUST NOT perform the requested method, and
* MUST return a 412 (Precondition Failed) response.
*/
rollback_on_error( $caldav_context, $request->user_no, $request->path, translate('Resource changed on server - not changed.'), 412 );
}
$put_action_type = 'INSERT';
if ( ! $request->AllowedTo('create') ) {
rollback_on_error( $caldav_context, $request->user_no, $request->path, translate('You may not add entries to this calendar.'), 403 );
}
}
elseif ( $qry->rows() == 1 ) {
$icalendar = $qry->Fetch();
if ( ( isset($request->etag_if_match) && $request->etag_if_match != '' && $request->etag_if_match != $icalendar->dav_etag )
|| ( isset($request->etag_none_match) && $request->etag_none_match != '' && ($request->etag_none_match == $icalendar->dav_etag || $request->etag_none_match == '*') ) ) {
/**
* RFC2068, 14.25:
* If none of the entity tags match, or if "*" is given and no current
* entity exists, the server MUST NOT perform the requested method, and
* MUST return a 412 (Precondition Failed) response.
*
* RFC2068, 14.26:
* If any of the entity tags match the entity tag of the entity that
* would have been returned in the response to a similar GET request
* (without the If-None-Match header) on that resource, or if "*" is
* given and any current entity exists for that resource, then the
* server MUST NOT perform the requested method.
*/
if ( isset($request->etag_if_match) && $request->etag_if_match != $icalendar->dav_etag ) {
$error = translate( 'Existing resource does not match "If-Match" header - not accepted.');
}
if ( isset($request->etag_none_match) && $request->etag_none_match != '' && ($request->etag_none_match == $icalendar->dav_etag || $request->etag_none_match == '*') ) {
$error = translate( 'Existing resource matches "If-None-Match" header - not accepted.');
}
$request->DoResponse( 412, $error );
}
$put_action_type = 'UPDATE';
if ( ! $request->AllowedTo('modify') ) {
$request->DoResponse( 403, translate('You may not modify entries on this calendar.') );
}
}
write_resource( $request->user_no, $request->path, $request->raw_post, $request->collection_id,
$author, $etag, $ic, $put_action_type, $caldav_context, $log_action=true );
if ( $caldav_context ) {
header(sprintf('ETag: "%s"', $etag) );
}
return $put_action_type;
}
/**
* Actually write the resource to the database. All checking of whether this is reasonable

View File

@ -10,7 +10,14 @@
*/
dbg_error_log("PUT", "method handler");
if ( ! $request->AllowedTo("read") ) {
require_once('DAVResource.php');
$dav_resource = new DAVResource($request->path);
if ( ! $dav_resource->HavePrivilegeTo('DAV::write-content') ) {
$request->DoResponse(403);
}
if ( ! $dav_resource->Exists() && ! $dav_resource->HavePrivilegeTo('DAV::bind') ) {
$request->DoResponse(403);
}
@ -23,13 +30,13 @@ if ( ! ini_get('open_basedir') && (isset($c->dbg['ALL']) || (isset($c->dbg['put'
}
include_once('caldav-PUT-functions.php');
controlRequestContainer( $request->username, $request->user_no, $request->path, true);
controlRequestContainer( $dav_resource->GetProperty('username'), $dav_resource->GetProperty('user_no'), $dav_resource->bound_from(), true);
$lock_opener = $request->FailIfLocked();
if ( $request->IsCollection() ) {
if ( !isset($c->readonly_webdav_collections) || $c->readonly_webdav_collections == true ) {
if ( $dav_resource->IsCollection() ) {
if ( $dav_resource->IsPrincipal() || $dav_resource->IsBinding() || !isset($c->readonly_webdav_collections) || $c->readonly_webdav_collections == true ) {
$request->DoResponse( 405 ); // Method not allowed
return;
}
@ -43,5 +50,50 @@ if ( $request->IsCollection() ) {
return;
}
$put_action_type = putCalendarResource( $request, $session->user_no, true );
$request->DoResponse( ($put_action_type == 'INSERT' ? 201 : 204) );
$etag = md5($request->raw_post);
$ic = new iCalComponent( $request->raw_post );
if ( ! $dav_resource->Exists() && (isset($request->etag_if_match) && $request->etag_if_match != '') ) {
/**
* RFC2068, 14.25:
* If none of the entity tags match, or if "*" is given and no current
* entity exists, the server MUST NOT perform the requested method, and
* MUST return a 412 (Precondition Failed) response.
*/
$request->PreconditionFailed(412,'if-match');
}
if ( $dav_resource->Exists() && (
(isset($request->etag_if_match) && $request->etag_if_match != '' && $request->etag_if_match != $dav_resource->unique_tag())
|| (isset($request->etag_none_match) && $request->etag_none_match != '' && ($request->etag_none_match == $dav_resource->unique_tag() || $request->etag_none_match == '*') )
) ) {
if ( isset($request->etag_if_match) && $request->etag_if_match != $icalendar->dav_etag ) {
/**
* RFC2068, 14.25:
* If none of the entity tags match, or if "*" is given and no current
* entity exists, the server MUST NOT perform the requested method, and
* MUST return a 412 (Precondition Failed) response.
*/
$request->PreconditionFailed(412,'if-match', translate( 'Existing resource does not match "If-Match" header - not accepted.'));
}
else {
/**
* RFC2068, 14.26:
* If any of the entity tags match the entity tag of the entity that
* would have been returned in the response to a similar GET request
* (without the If-None-Match header) on that resource, or if "*" is
* given and any current entity exists for that resource, then the
* server MUST NOT perform the requested method.
*/
$request->PreconditionFailed(412,'if-none-match', translate( 'Existing resource matches "If-None-Match" header - not accepted.'));
}
}
$put_action_type = ($dav_resource->Exists() ? 'UPDATE' : 'INSERT');
write_resource( $dav_resource->GetProperty('user_no'), $dav_resource->bound_from(), $request->raw_post, $dav_resource->GetProperty('collection_id'),
$session->user_no, $etag, $ic, $put_action_type, true, true );
header(sprintf('ETag: "%s"', $etag) );
$request->DoResponse( ($dav_resource->Exists() ? 204 : 201) );