* A fresh lock */ $lock_token = uuid(); $sql = 'INSERT INTO locks ( dav_name, opaquelocktoken, type, scope, depth, owner, timeout, start ) VALUES( :dav_name, :lock_token, :type, :scope, :request_depth, :owner, :timeout::interval, current_timestamp )'; $params = array(':dav_name' => $request->path, ':lock_token' => $lock_token, ':type' => $lockinfo['type'], ':scope' => $lockinfo['scope'], ':request_depth' => $request->depth, ':owner' => $lockinfo['owner'], ':timeout' => $request->timeout . ' seconds'); header("Lock-Token: <opaquelocktoken:{$lock_token}>"); } $qry = new AwlQuery($sql, $params); $qry->Exec("LOCK", __LINE__, __FILE__); $lock_row = $request->GetLockRow($lock_token); $activelock = array(new XMLElement('locktype', new XMLElement($lock_row->type)), new XMLElement('lockscope', new XMLElement($lock_row->scope)), new XMLElement('depth', $request->GetDepthName()), new XMLElement('owner', new XMLElement('href', $lock_row->owner)), new XMLElement('timeout', 'Second-' . $request->timeout), new XMLElement('locktoken', new XMLElement('href', 'opaquelocktoken:' . $lock_token))); $response = new XMLElement("lockdiscovery", new XMLElement("activelock", $activelock), array("xmlns" => "DAV:")); } elseif ($request->method == "UNLOCK") { /** * @TODO: respond with preconditionfailed(409,'lock-token-matches-request-uri') if * there is no lock to be deleted. */ dbg_error_log("LOCK", "Attempting to unlock resource '%s'", $request->path); if ($lock_token = $request->IsLocked()) { // NOTE Assignment in if() is expected here. $sql = 'DELETE FROM locks WHERE opaquelocktoken = :lock_token'; $qry = new AwlQuery($sql, array(':lock_token' => $lock_token)); $qry->Exec("LOCK", __LINE__, __FILE__); } $request->DoResponse(204); } $prop = new XMLElement("prop", $response, array('xmlns' => 'DAV:')); // dbg_log_array( "LOCK", "XML", $response, true ); $xmldoc = $prop->Render(0, '<?xml version="1.0" encoding="utf-8" ?>'); $request->DoResponse(200, $xmldoc, 'text/xml; charset="utf-8"');
/** * Send an XML Response. This function will never return. * * @param int $status The HTTP status to respond * @param XMLElement $xmltree An XMLElement tree to be rendered */ function XMLResponse($status, $xmltree) { $xmldoc = $xmltree->Render(0, '<?xml version="1.0" encoding="utf-8" ?>'); $etag = md5($xmldoc); if (!headers_sent()) { header("ETag: \"{$etag}\""); } $this->DoResponse($status, $xmldoc, 'text/xml; charset="utf-8"'); exit(0); // Unecessary, but might clarify things }
} /** * If we have encountered any instances of failure, the whole damn thing fails. */ if (count($failure) > 0) { foreach ($success as $tag => $v) { // Unfortunately although these succeeded, we failed overall, so they didn't happen... $failure[] = new XMLElement('propstat', array(new XMLElement('prop', new XMLElement($tag)), new XMLElement('status', 'HTTP/1.1 424 Failed Dependency'))); } $url = ConstructURL($request->path); array_unshift($failure, new XMLElement('href', $url)); $failure[] = new XMLElement('responsedescription', translate("Some properties were not able to be changed.")); $qry->Rollback(); $multistatus = new XMLElement("multistatus", new XMLElement('response', $failure), array('xmlns' => 'DAV:')); $request->DoResponse(207, $multistatus->Render(0, '<?xml version="1.0" encoding="utf-8" ?>'), 'text/xml; charset="utf-8"'); } /** * Otherwise we will try and do the SQL. This is inside a transaction, so PostgreSQL guarantees the atomicity */ if ($qry->Commit()) { $url = ConstructURL($request->path); $href = new XMLElement('href', $url); $desc = new XMLElement('responsedescription', translate("All requested changes were made.")); $multistatus = new XMLElement("multistatus", new XMLElement('response', array($href, $desc)), array('xmlns' => 'DAV:')); $request->DoResponse(200, $multistatus->Render(0, '<?xml version="1.0" encoding="utf-8" ?>'), 'text/xml; charset="utf-8"'); } /** * Or it was all crap. */ $request->DoResponse(500); exit(0);
if ($qry->Exec() && $qry->rows > 0) { while ($dav = $qry->Fetch()) { $response = new XMLElement("response"); $prop = new XMLElement("prop"); $url = sprintf("http://%s:%d%s%s", $_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT'], $_SERVER['SCRIPT_NAME'], $dav->dav_name); if (isset($report[$i]['include_href']) && $report[$i]['include_href'] > 0) { $response->NewElement("href", $url); } if (isset($report[$i]['include_data']) && $report[$i]['include_data'] > 0) { $prop->NewElement("calendar-data", $dav->caldav_data, array("xmlns" => "urn:ietf:params:xml:ns:caldav")); } if (isset($report[$i]['properties']['GETETAG'])) { $prop->NewElement("getetag", '"' . $dav->dav_etag . '"'); } $status = new XMLElement("status", "HTTP/1.1 200 OK"); $response->NewElement("propstat", array($prop, $status)); $responses[] = $response; dbg_error_log("REPORT", "DAV Response: ETag >>%s<< >>%s<<", $dav->dav_etag, $url); } } } $multistatus = new XMLElement("multistatus", $responses, array('xmlns' => 'DAV:')); // dbg_log_array( "REPORT", "XML", $multistatus, true ); $xmldoc = $multistatus->Render(); $etag = md5($xmldoc); header("HTTP/1.1 207 Multi-Status"); header("Content-type: text/xml;charset=UTF-8"); header("DAV: 1, 2, calendar-schedule"); header("ETag: \"{$etag}\""); echo '<?xml version="1.0" encoding="UTF-8" ?>' . "\n"; echo $xmldoc;
/** * Sometimes it's a perfectly formed request, but we just don't do that :-( * @param array $unsupported An array of the properties we don't support. */ function UnsupportedRequest($unsupported) { if (isset($unsupported) && count($unsupported) > 0) { $badprops = new XMLElement("prop"); foreach ($unsupported as $k => $v) { // Not supported at this point... dbg_error_log("ERROR", " %s: Support for {$v}:{$k} properties is not implemented yet", $this->method); $badprops->NewElement(strtolower($k), false, array("xmlns" => strtolower($v))); } $error = new XMLElement("error", new XMLElement("LOCK", $badprops), array("xmlns" => "DAV:")); $this->DoResponse(422, $error->Render(0, '<?xml version="1.0" ?>'), 'text/xml; charset="utf-8"'); } }
dbg_error_log("PROPFIND", "Getting item: Path: %s", $item_path); $sql = "SELECT caldav_data.dav_name, caldav_data, caldav_data.dav_etag "; $sql .= "FROM caldav_data WHERE dav_name = ?"; $qry = new PgQuery($sql, PgQuery::Plain(iCalendar::HttpDateFormat()), PgQuery::Plain(iCalendar::HttpDateFormat()), $item_path); if ($qry->Exec("PROPFIND", __LINE__, __FILE__) && $qry->rows > 0) { while ($item = $qry->Fetch()) { $responses[] = item_to_xml($item); } } return $responses; } $request->UnsupportedRequest($unsupported); // Won't return if there was unsupported stuff. /** * Something that we can handle, at least roughly correctly. */ $url = $c->protocol_server_port_script . $request->path; $url = preg_replace('#/$#', '', $url); if ($request->IsCollection()) { $responses = get_collection($request->depth, $request->user_no, $request->path); } elseif ($request->AllowedTo('read')) { $responses = get_item($request->path); } else { $request->DoResponse(403, translate("You do not have appropriate rights to view that resource.")); } $multistatus = new XMLElement("multistatus", $responses, array('xmlns' => 'DAV:')); // dbg_log_array( "PROPFIND", "XML", $multistatus, true ); $xmldoc = $multistatus->Render(0, '<?xml version="1.0" encoding="utf-8" ?>'); $etag = md5($xmldoc); header("ETag: \"{$etag}\""); $request->DoResponse(207, $xmldoc, 'text/xml; charset="utf-8"');