/** * CalDAV Server - handle PUT method * * @package davical * @subpackage caldav * @author Andrew McMillan <*****@*****.**> * @copyright Catalyst .Net Ltd, Morphoss Ltd * @license http://gnu.org/copyleft/gpl.html GNU GPL v2 or later */ dbg_error_log("PUT", "method handler"); 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); } if (!ini_get('open_basedir') && (isset($c->dbg['ALL']) || isset($c->dbg['put']) && $c->dbg['put'])) { $fh = fopen('/tmp/PUT.txt', 'w'); if ($fh) { fwrite($fh, $request->raw_post); fclose($fh); } } include_once 'caldav-PUT-functions.php'; controlRequestContainer($dav_resource->GetProperty('username'), $dav_resource->GetProperty('user_no'), $dav_resource->bound_from(), true); $lock_opener = $request->FailIfLocked(); if ($dav_resource->IsCollection()) { if ($dav_resource->IsPrincipal() || $dav_resource->IsBinding() || !isset($c->readonly_webdav_collections) || $c->readonly_webdav_collections == true) { $request->DoResponse(405);
* @copyright Morphoss Ltd * @license http://gnu.org/copyleft/gpl.html GNU GPL v2 or later */ dbg_error_log("PUT", "method handler"); require_once 'DAVResource.php'; if (!ini_get('open_basedir') && (isset($c->dbg['ALL']) || isset($c->dbg['put']) && $c->dbg['put'])) { $fh = fopen('/tmp/PUT.txt', 'w'); if ($fh) { fwrite($fh, $request->raw_post); fclose($fh); } } $lock_opener = $request->FailIfLocked(); $dest = new DAVResource($request->path); $container = $dest->FetchParentContainer(); if (!$dest->Exists()) { if ($container->IsPrincipal()) { $request->PreconditionFailed(405, 'method-not-allowed', translate('A DAViCal principal collection may only contain collections')); } if (!$container->Exists()) { $request->PreconditionFailed(409, 'collection-must-exist', translate('The destination collection does not exist')); } $container->NeedPrivilege('DAV::bind'); } else { if ($dest->IsCollection()) { if (!isset($c->readonly_webdav_collections) || $c->readonly_webdav_collections) { $request->PreconditionFailed(405, 'method-not-allowed', translate('You may not PUT to a collection URL')); } $request->DoResponse(403, translate('PUT on a collection is only allowed for text/calendar content against a calendar collection')); } $dest->NeedPrivilege('DAV::write-content');
/** * CalDAV Server - handle GET method * * @package davical * @subpackage caldav * @author Andrew McMillan <*****@*****.**> * @copyright Catalyst .Net Ltd, Morphoss Ltd <http://www.morphoss.com/> * @license http://gnu.org/copyleft/gpl.html GNU GPL v2 or later */ dbg_error_log("get", "GET method handler"); require_once "iCalendar.php"; require_once "DAVResource.php"; $dav_resource = new DAVResource($request->path); $dav_resource->NeedPrivilege(array('urn:ietf:params:xml:ns:caldav:read-free-busy', 'DAV::read')); if (!$dav_resource->Exists()) { $request->DoResponse(404, translate("Resource Not Found.")); } function obfuscated_event($icalendar) { // The user is not admin / owner of this calendar looking at his calendar and can not admin the other cal, // or maybe they don't have *read* access but they got here, so they must at least have free/busy access // so we will present an obfuscated version of the event that just says "Busy" (translated :-) $confidential = new iCalComponent(); $confidential->SetType($icalendar->GetType()); $confidential->AddProperty('SUMMARY', translate('Busy')); $confidential->AddProperty('CLASS', 'CONFIDENTIAL'); $confidential->SetProperties($icalendar->GetProperties('DTSTART'), 'DTSTART'); $confidential->SetProperties($icalendar->GetProperties('RRULE'), 'RRULE'); $confidential->SetProperties($icalendar->GetProperties('DURATION'), 'DURATION'); $confidential->SetProperties($icalendar->GetProperties('DTEND'), 'DTEND');
*/ default: dbg_error_log("cardquery", "Could not handle unknown tag '%s' in calendar query report", $tag); break; } } dbg_error_log("cardquery", "Generated SQL was '%s'", $sql); return array('sql' => $sql, 'params' => $params); } /** * Something that we can handle, at least roughly correctly. */ $responses = array(); $target_collection = new DAVResource($request->path); $bound_from = $target_collection->bound_from(); if (!$target_collection->Exists()) { $request->DoResponse(404); } if (!($target_collection->IsAddressbook() || $target_collection->IsSchedulingCollection())) { $request->DoResponse(403, translate('The addressbook-query report must be run against an addressbook collection')); } /** * @todo Once we are past DB version 1.2.1 we can change this query more radically. The best performance to * date seems to be: * SELECT caldav_data.*,address_item.* FROM collection JOIN address_item USING (collection_id,user_no) * JOIN caldav_data USING (dav_id) WHERE collection.dav_name = '/user1/home/' * AND caldav_data.caldav_type = 'VEVENT' ORDER BY caldav_data.user_no, caldav_data.dav_name; */ $params = array(); $where = ' WHERE caldav_data.collection_id = ' . $target_collection->resource_id(); if (is_array($qry_filters)) {
* we use the xmlns="http://www.xythos.com/namespaces/StorageServer" rather * than the DAV: namespace. * * @package davical * @subpackage caldav * @author Andrew McMillan <*****@*****.**> * @copyright Morphoss Ltd - http://www.morphoss.com/ * @license http://gnu.org/copyleft/gpl.html GNU GPL v2 or later */ dbg_error_log('DELTICKET', 'method handler'); require_once 'DAVResource.php'; if (!$request->HavePrivilegeTo('DAV::unbind') && $request->ticket->owner() != $session->principal_id) { $request->NeedPrivilege('DAV::unbind'); } if (!isset($request->ticket)) { if (isset($_GET['ticket']) || isset($_SERVER['HTTP_TICKET'])) { $r = new DAVResource($request->path); if (!$r->Exists()) { $request->PreconditionFailed(404, 'not-found'); } else { $request->PreconditionFailed(412, 'ticket-does-not-exist', 'The specified ticket does not exist'); } } else { $request->MalformedRequest('No ticket specified'); } } $qry = new AwlQuery('DELETE FROM access_ticket WHERE ticket_id=:ticket_id', array(':ticket_id' => $request->ticket->id())); if ($qry->Exec('DELTICKET', __LINE__, __FILE__)) { $request->DoResponse(204); } $request->DoResponse(500);
$position = 0; $xmltree = BuildXMLTree($request->xml_tags, $position); $segment = $xmltree->GetElements('DAV::segment'); $segment = $segment[0]->GetContent(); if (preg_match('{[/\\\\]}', $segment)) { $request->PreconditionFailed(403, 'DAV::name-allowed', translate('That destination name contains invalid characters.')); } $href = $xmltree->GetElements('DAV::href'); $href = $href[0]->GetContent(); $destination_path = $parent_container . $segment . '/'; $destination = new DAVResource($destination_path); if ($destination->Exists()) { $request->PreconditionFailed(403, 'DAV::can-overwrite', translate('A resource already exists at the destination.')); } $source = new DAVResource($href); if (!$source->Exists()) { $request->PreconditionFailed(403, 'DAV::bind-source-exists', translate('The BIND Request MUST identify an existing resource.')); } if ($source->IsPrincipal() || !$source->IsCollection()) { $request->PreconditionFailed(403, 'DAV::binding-allowed', translate('DAViCal only allows BIND requests for collections at present.')); } /* bind_id INT8 DEFAULT nextval('dav_id_seq') PRIMARY KEY, bound_source_id INT8 REFERENCES collection(collection_id) ON UPDATE CASCADE ON DELETE CASCADE, access_ticket_id TEXT REFERENCES access_ticket(ticket_id) ON UPDATE CASCADE ON DELETE SET NULL, parent_container TEXT NOT NULL, dav_name TEXT UNIQUE NOT NULL, dav_displayname TEXT */ $sql = 'INSERT INTO dav_binding ( bound_source_id, access_ticket_id, dav_owner_id, parent_container, dav_name, dav_displayname ) VALUES( :target_id, :ticket_id, :session_principal, :parent_container, :dav_name, :displayname )';
} $sync_token = intval(str_ireplace('data:,', '', $sync_token)); dbg_error_log('sync', " sync-token: %s", $sync_token); $proplist = array(); $props = $xmltree->GetPath('/DAV::sync-collection/DAV::prop/*'); if (!empty($props)) { foreach ($props as $k => $v) { $proplist[] = $v->GetNSTag(); } } function display_status($status_code) { return sprintf('HTTP/1.1 %03d %s', intval($status_code), getStatusMessage($status_code)); } $collection = new DAVResource($request->path); if (!$collection->Exists()) { $request->DoResponse(404); } $bound_from = $collection->bound_from(); $collection_path = $collection->dav_name(); $request_via_binding = $bound_from != $collection_path; $params = array(':collection_id' => $collection->GetProperty('collection_id'), ':sync_token' => $sync_token); $sql = "SELECT new_sync_token( :sync_token, :collection_id)"; $qry = new AwlQuery($sql, $params); if (!$qry->Exec("REPORT", __LINE__, __FILE__) || $qry->rows() <= 0) { $request->DoResponse(500, translate("Database error")); } $row = $qry->Fetch(); if (!isset($row->new_sync_token)) { /** If we got a null back then they gave us a sync token we know not of, so provide a full sync */ $sync_token = 0;
$request->PreconditionFailed(403, 'DAV::method-not-allowed', translate('The BIND method is not allowed at that location.')); } require_once 'XMLDocument.php'; $reply = new XMLDocument(array('DAV:' => '')); $position = 0; $xmltree = BuildXMLTree($request->xml_tags, $position); $segment = $xmltree->GetElements('DAV::segment'); $segment = $segment[0]->GetContent(); if (preg_match('{[/\\\\]}', $segment)) { $request->PreconditionFailed(403, 'DAV::name-allowed', translate('That destination name contains invalid characters.')); } $href = $xmltree->GetElements('DAV::href'); $href = $href[0]->GetContent(); $destination_path = $parent_container . $segment . '/'; $destination = new DAVResource($destination_path); if ($destination->Exists()) { $request->PreconditionFailed(403, 'DAV::can-overwrite', translate('A resource already exists at the destination.')); } // external binds shouldn't ever point back to ourselves but they should be a valid http[s] url if (preg_match('{^https?://([^/]+)(:[0-9]\\+)?/.+$}', $href, $matches) && strcasecmp($matches[0], 'localhost') !== 0 && strcasecmp($matches[0], '127.0.0.1') !== 0 && strcasecmp($matches[0], $_SERVER['SERVER_NAME']) !== 0 && strcasecmp($matches[0], $_SERVER['SERVER_ADDR']) !== 0) { require_once 'external-fetch.php'; $qry = new AwlQuery(); $qry->QDo('SELECT collection_id FROM collection WHERE dav_name = :dav_name ', array(':dav_name' => '/.external/' . md5($href))); if ($qry->rows() == 1 && ($row = $qry->Fetch())) { $dav_id = $row->collection_id; } else { create_external('/.external/' . md5($href), true, false); $qry->QDo('SELECT collection_id FROM collection WHERE dav_name = :dav_name ', array(':dav_name' => '/.external/' . md5($href))); if ($qry->rows() != 1 || !($row = $qry->Fetch())) { $request->DoResponse(500, translate('Database Error')); }
if ($fh) { fwrite($fh, $request->raw_post); fclose($fh); } } $lock_opener = $request->FailIfLocked(); $dest = new DAVResource($request->path); $container = $dest->FetchParentContainer(); if ($container->IsCalendar()) { $request->PreconditionFailed(412, 'urn:ietf:params:xml:ns:caldav:supported-calendar-data', translate('Incorrect content type for calendar: ') . $request->content_type); } else { if ($container->IsAddressbook()) { $request->PreconditionFailed(412, 'urn:ietf:params:xml:ns:carddav:supported-address-data', translate('Incorrect content type for addressbook: ') . $request->content_type); } } if (!$dest->Exists()) { if ($container->IsPrincipal()) { $request->DoResponse(403, translate('A DAViCal principal collection may only contain collections')); } if (!$container->Exists()) { $request->DoResponse(409, translate('Destination collection does not exist')); } $container->NeedPrivilege('DAV::bind'); } else { if ($dest->IsCollection()) { if (!isset($c->readonly_webdav_collections) || $c->readonly_webdav_collections) { $request->DoResponse(403, translate('You may not PUT to a collection URL')); } $request->DoResponse(403, translate('PUT on a collection is only allowed for text/calendar content against a calendar collection')); } $dest->NeedPrivilege('DAV::write-content');
} $this->username = $principal->username(); $this->principal_id = $principal->principal_id(); $this->email = $principal->email(); $this->dav_name = $principal->dav_name(); $this->principal = $principal; $this->logged_in = true; } function AllowedTo($do_something) { return $this->logged_in; } } $session = new FakeSession(); $dest = new DAVResource($target); $session = new FakeSession($dest->user_no()); if ($mode == 'append' && !$dest->Exists()) { printf("The target '%s' does not exist.\n", $target); exit(1); } if (!$dest->IsCollection()) { printf("The target '%s' is not a collection.\n", $target); exit(1); } $user_no = $dest->user_no(); $username = $session->username; param_to_global('mode'); include_once 'caldav-PUT-functions.php'; controlRequestContainer($session->username, $dest->user_no(), $target, false, $dest->IsPublic() ? true : false); import_collection($ics, $dest->user_no(), $target, $session->user_no, $mode == 'append'); printf(translate("Calendar '%s' was loaded from file.\n"), $target);
if ($dest->Exists()) { throw new Exception("Failed to generate unique segment name for add-member!"); } } } else { $dest = new DAVResource($request->path); } $container = $dest->GetParentContainer(); if ($container->IsCalendar()) { $request->PreconditionFailed(412, 'urn:ietf:params:xml:ns:caldav:supported-calendar-data', translate('Incorrect content type for calendar: ') . $request->content_type); } else { if ($container->IsAddressbook()) { $request->PreconditionFailed(412, 'urn:ietf:params:xml:ns:carddav:supported-address-data', translate('Incorrect content type for addressbook: ') . $request->content_type); } } if (!$dest->Exists()) { if ($container->IsPrincipal()) { $request->DoResponse(403, translate('A DAViCal principal collection may only contain collections')); } if (!$container->Exists()) { $request->DoResponse(409, translate('Destination collection does not exist')); } $container->NeedPrivilege('DAV::bind'); } else { if ($dest->IsCollection()) { if (!isset($c->readonly_webdav_collections) || $c->readonly_webdav_collections) { $request->DoResponse(403, translate('You may not PUT to a collection URL')); } $request->DoResponse(403, translate('PUT on a collection is only allowed for text/calendar content against a calendar collection')); } $dest->NeedPrivilege('DAV::write-content');
if ($dav_resource->Exists()) { $uid = uuid(); $vcalendar->SetUID($uid); $request->path = $request->dav_name() . $uid . '.ics'; $dav_resource = new DAVResource($request->path); if ($dav_resource->Exists()) { throw new Exception("Failed to generate unique segment name for add-member!"); } } } else { $dav_resource = new DAVResource($request->path); } if (!$dav_resource->HavePrivilegeTo('DAV::write-content')) { $request->DoResponse(403, 'No write permission'); } if (!$dav_resource->Exists() && !$dav_resource->HavePrivilegeTo('DAV::bind')) { $request->DoResponse(403, 'No bind permission.'); } if (!ini_get('open_basedir') && (isset($c->dbg['ALL']) || isset($c->dbg['put']) && $c->dbg['put'])) { $fh = fopen('/var/log/davical/PUT.debug', 'w'); if ($fh) { fwrite($fh, $request->raw_post); fclose($fh); } } controlRequestContainer($dav_resource->GetProperty('username'), $dav_resource->GetProperty('user_no'), $dav_resource->bound_from(), true); $lock_opener = $request->FailIfLocked(); 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
function process_ace($grantor, $by_principal, $by_collection, $ace) { global $cache_delete_list, $request; $elements = $ace->GetContent(); $principal_node = $elements[0]; $grant = $elements[1]; if ($principal_node->GetNSTag() != 'DAV::principal') { $request->MalformedRequest('ACL request must contain a principal, not ' . $principal->GetNSTag()); } $grant_tag = $grant->GetNSTag(); if ($grant_tag == 'DAV::deny') { $request->PreconditionFailed(403, 'grant-only'); } if ($grant_tag == 'DAV::invert') { $request->PreconditionFailed(403, 'no-invert'); } if ($grant->GetNSTag() != 'DAV::grant') { $request->MalformedRequest('ACL request must contain a principal for each ACE'); } $privilege_names = array(); $xml_privs = $grant->GetPath("/DAV::grant/DAV::privilege/*"); foreach ($xml_privs as $k => $priv) { $privilege_names[] = $priv->GetNSTag(); } $privileges = privilege_to_bits($privilege_names); $principal_content = $principal_node->GetContent(); if (count($principal_content) != 1) { $request->MalformedRequest('ACL request must contain exactly one principal per ACE'); } $principal_content = $principal_content[0]; switch ($principal_content->GetNSTag()) { case 'DAV::property': $principal_property = $principal_content->GetContent(); if ($principal_property[0]->GetNSTag() != 'DAV::owner') { $request->PreconditionFailed(403, 'recognized-principal'); } if (privilege_to_bits('all') != $privileges) { $request->PreconditionFailed(403, 'no-protected-ace-conflict', 'Owner must always have all permissions'); } continue; // and then we ignore it, since it's protected break; case 'DAV::unauthenticated': $request->PreconditionFailed(403, 'allowed-principal', 'May not set privileges for unauthenticated users'); break; case 'DAV::href': $principal_type = 'href'; $grantee = new DAVResource(DeconstructURL($principal_content->GetContent())); $grantee_id = $grantee->getProperty('principal_id'); if (!$grantee->Exists() || !$grantee->IsPrincipal()) { $request->PreconditionFailed(403, 'recognized-principal', 'Principal "' + $principal_content->GetContent() + '" not found.'); } $sqlparms = array(':to_principal' => $grantee_id); $where = 'WHERE to_principal=:to_principal AND '; if (isset($by_principal)) { $sqlparms[':by_principal'] = $by_principal; $where .= 'by_principal = :by_principal'; } else { $sqlparms[':by_collection'] = $by_collection; $where .= 'by_collection = :by_collection'; } $qry = new AwlQuery('SELECT privileges FROM grants ' . $where, $sqlparms); if ($qry->Exec('ACL', __LINE__, __FILE__) && $qry->rows() == 1 && ($current = $qry->Fetch())) { $sql = 'UPDATE grants SET privileges=:privileges::INT::BIT(24) ' . $where; } else { $sqlparms[':by_principal'] = $by_principal; $sqlparms[':by_collection'] = $by_collection; $sql = 'INSERT INTO grants (by_principal, by_collection, to_principal, privileges) VALUES(:by_principal, :by_collection, :to_principal, :privileges::INT::BIT(24))'; } $sqlparms[':privileges'] = $privileges; $qry = new AwlQuery($sql, $sqlparms); if ($qry->Exec('ACL', __LINE__, __FILE__)) { Principal::cacheDelete('dav_name', $grantee->dav_name()); Principal::cacheFlush('principal_id IN (SELECT member_id FROM group_member WHERE group_id = ?)', array($grantee_id)); } break; case 'DAV::authenticated': $principal_type = 'authenticated'; if (bindec($grantor->GetProperty('default_privileges')) == $privileges) { continue; } // There is no change, so skip it $sqlparms = array(':privileges' => $privileges); if (isset($by_collection)) { $sql = 'UPDATE collection SET default_privileges=:privileges::INT::BIT(24) WHERE collection_id=:by_collection'; $sqlparms[':by_collection'] = $by_collection; } else { $sql = 'UPDATE principal SET default_privileges=:privileges::INT::BIT(24) WHERE principal_id=:by_principal'; $sqlparms[':by_principal'] = $by_principal; } $qry = new AwlQuery($sql, $sqlparms); if ($qry->Exec('ACL', __LINE__, __FILE__)) { /** * Basically this has changed everyone's permissions now, so... */ Principal::cacheFlush('TRUE'); } break; case 'DAV::all': // $principal_type = 'all'; $request->PreconditionFailed(403, 'allowed-principal', 'May not set privileges for unauthenticated users'); break; default: $request->PreconditionFailed(403, 'recognized-principal'); break; } }
$request->path = $request->dav_name() . $uid . '.vcf'; $dest = new DAVResource($request->path); if ($dest->Exists()) { $uid = uuid(); $vcard->AddProperty('UID', $uid); $request->path = $request->dav_name() . $uid . '.vcf'; $dest = new DAVResource($request->path); if ($dest->Exists()) { throw new Exception("Failed to generate unique segment name for add-member!"); } } } else { $dest = new DAVResource($request->path); } $container = $dest->GetParentContainer(); if (!$dest->Exists()) { if ($container->IsPrincipal()) { $request->PreconditionFailed(405, 'method-not-allowed', translate('A DAViCal principal collection may only contain collections')); } if (!$container->Exists()) { $request->PreconditionFailed(409, 'collection-must-exist', translate('The destination collection does not exist')); } $container->NeedPrivilege('DAV::bind'); } else { if ($dest->IsCollection()) { if (!isset($c->readonly_webdav_collections) || $c->readonly_webdav_collections) { $request->PreconditionFailed(405, 'method-not-allowed', translate('You may not PUT to a collection URL')); } $request->DoResponse(403, translate('PUT on a collection is only allowed for text/vcard content against an addressbook collection')); } $dest->NeedPrivilege('DAV::write-content');
} } return $responses; } /** * Something that we can handle, at least roughly correctly. */ $responses = array(); if ($request->IsProxyRequest()) { $response = add_proxy_response($request->proxy_type, $request->principal->dav_name()); if (isset($response)) { $responses[] = $response; } } else { $resource = new DAVResource($request->path); if (!$resource->Exists()) { $request->PreconditionFailed(404, 'must-exist', translate('That resource is not present on this server.')); } $resource->NeedPrivilege('DAV::read'); if ($resource->IsExternal()) { require_once "external-fetch.php"; update_external($resource); } if ($resource->IsCollection()) { dbg_error_log('PROPFIND', 'Getting collection contents: Depth %d, Path: %s', $request->depth, $resource->dav_name()); $responses[] = $resource->RenderAsXML($property_list, $reply); if ($request->depth > 0) { $responses = array_merge($responses, get_collection_contents($request->depth - 1, $resource)); } } elseif ($request->HavePrivilegeTo('DAV::read', false)) { $responses[] = $resource->RenderAsXML($property_list, $reply);
$dest = new DAVResource($request->destination); if ($dest->dav_name() == '/' || $dest->IsPrincipal()) { $dest->NeedPrivilege('DAV::bind'); } if (!$dest->ContainerExists()) { $request->DoResponse(409, translate('Destination collection does not exist')); } if (!$request->overwrite && $dest->Exists()) { $request->DoResponse(412, translate('Not overwriting existing destination resource')); } if (isset($request->etag_none_match) && $request->etag_none_match != '*') { $request->DoResponse(412); /** request to move, but only if there is no source? WTF! */ } $src = new DAVResource($request->path); if (!$src->Exists()) { $request->DoResponse(412, translate('Source resource does not exist.')); } if ($src->IsCollection()) { switch ($dest->ContainerType()) { case 'calendar': case 'addressbook': case 'schedule-inbox': case 'schedule-outbox': $request->DoResponse(412, translate('Special collections may not contain a calendar or other special collection.')); } } else { if (isset($request->etag_if_match) && $request->etag_if_match != '' || isset($request->etag_none_match) && $request->etag_none_match != '') { /** * RFC2068, 14.25: * If none of the entity tags match, or if "*" is given and no current
* we use the xmlns="http://www.xythos.com/namespaces/StorageServer" rather * than the DAV: namespace. * * @package davical * @subpackage caldav * @author Andrew McMillan <*****@*****.**> * @copyright Morphoss Ltd - http://www.morphoss.com/ * @license http://gnu.org/copyleft/gpl.html GNU GPL v2 or later */ dbg_error_log('MKTICKET', 'method handler'); require_once 'DAVResource.php'; $request->NeedPrivilege('DAV::bind'); require_once 'XMLDocument.php'; $reply = new XMLDocument(array('DAV:' => '', 'http://www.xythos.com/namespaces/StorageServer' => 'T')); $target = new DAVResource($request->path); if (!$target->Exists()) { $request->XMLResponse(404, new XMLElement('error', new XMLElement('resource-must-not-be-null'), $reply->GetXmlNsArray())); } if (!isset($request->xml_tags)) { $request->XMLResponse(400, new XMLElement('error', new XMLElement('missing-xml-for-request'), $reply->GetXmlNsArray())); } $xmltree = BuildXMLTree($request->xml_tags, $position); if ($xmltree->GetTag() != 'http://www.xythos.com/namespaces/StorageServer:ticketinfo' && $xmltree->GetTag() != 'DAV::ticketinfo') { $request->XMLResponse(400, new XMLElement('error', new XMLElement('invalid-xml-for-request'), $reply->GetXmlNsArray())); } $ticket_timeout = 'Seconds-3600'; $ticket_privs_array = array('read-free-busy'); foreach ($xmltree->GetContent() as $k => $v) { // <!ELEMENT ticketinfo (id?, owner?, timeout, visits, privilege)> switch ($v->GetTag()) { case 'DAV::timeout':
if ($principal_property[0]->GetTag() != 'DAV::owner') { $request->PreconditionFailed(403, 'recognized-principal'); } if (privilege_to_bits('all') != $privileges) { $request->PreconditionFailed(403, 'no-protected-ace-conflict', 'Owner must always have all permissions'); } continue; // and then we ignore it, since it's protected break; case 'DAV::unauthenticated': $request->PreconditionFailed(403, 'allowed-principal', 'May not set privileges for unauthenticated users'); break; case 'DAV::href': $principal_type = 'href'; $principal = new DAVResource(DeconstructURL($principal_content->GetContent())); if (!$principal->Exists() || !$principal->IsPrincipal()) { $request->PreconditionFailed(403, 'recognized-principal', 'Principal "' + $principal_content->GetContent() + '" not found.'); } $sqlparms = array(':to_principal' => $principal->GetProperty('principal_id')); $where = 'WHERE to_principal=:to_principal AND '; if (isset($by_principal)) { $sqlparms[':by_principal'] = $by_principal; $where .= 'by_principal = :by_principal'; } else { $sqlparms[':by_collection'] = $by_collection; $where .= 'by_collection = :by_collection'; } $qry = new AwlQuery('SELECT privileges FROM grants ' . $where, $sqlparms); if ($qry->Exec('ACL', __LINE__, __FILE__) && $qry->rows() == 1 && ($current = $qry->Fetch())) { $sql = 'UPDATE grants SET privileges=:privileges::INT::BIT(24) ' . $where; } else {