Пример #1
0
     header("Allow: PROPFIND,PROPPATCH,OPTIONS,MKCOL,REPORT,DELETE");
     $request->DoResponse(405, translate("GET requests on collections are only supported for calendars."));
 }
 /**
  * The CalDAV specification does not define GET on a collection, but typically this is
  * used as a .ics download for the whole collection, which is what we do also.
  */
 $sql = 'SELECT caldav_data, class, caldav_type, calendar_item.user_no, logged_user ';
 $sql .= 'FROM collection INNER JOIN caldav_data USING(collection_id) INNER JOIN calendar_item USING ( dav_id ) WHERE ';
 if (isset($c->get_includes_subcollections) && $c->get_includes_subcollections) {
     $sql .= '(collection.dav_name ~ :path_match ';
     $sql .= 'OR collection.collection_id IN (SELECT bound_source_id FROM dav_binding WHERE dav_binding.dav_name ~ :path_match)) ';
     $params = array(':path_match' => '^' . $request->path);
 } else {
     $sql .= 'caldav_data.collection_id = :collection_id ';
     $params = array(':collection_id' => $dav_resource->resource_id());
 }
 if (isset($c->strict_result_ordering) && $c->strict_result_ordering) {
     $sql .= ' ORDER BY dav_id';
 }
 $qry = new AwlQuery($sql, $params);
 if (!$qry->Exec("GET", __LINE__, __FILE__)) {
     $request->DoResponse(500, translate("Database Error"));
 }
 /**
  * Here we are constructing a whole calendar response for this collection, including
  * the timezones that are referred to by the events we have selected.
  */
 $vcal = new iCalComponent();
 $vcal->VCalendar();
 $displayname = $dav_resource->GetProperty('displayname');
Пример #2
0
$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)) {
    dbg_log_array('cardquery', 'qry_filters', $qry_filters, true);
    $components = array();
    $filter_fragment = SqlFilterCardDAV($qry_filters, $components);
    if ($filter_fragment !== false) {
        $where .= ' ' . $filter_fragment['sql'];
        $params = $filter_fragment['params'];
    }
} else {
    dbg_error_log('cardquery', 'No query filters');
}
$sql = 'SELECT * FROM caldav_data INNER JOIN addressbook_resource USING(dav_id)' . $where;
if (isset($c->strict_result_ordering) && $c->strict_result_ordering) {
    $sql .= " ORDER BY dav_id";
}
     * anything up to the matching request->path (which will include any http...) and then
     * put the $bound_from prefix back on.
     */
    $rawurl = rawurldecode($v->GetContent());
    $path_pos = strpos($rawurl, $request->path);
    if ($path_pos === false) {
        $href = $bound_from . $rawurl;
    } else {
        $href = $bound_from . substr($rawurl, $path_pos + strlen($request->path));
    }
    @dbg_error_log("REPORT", 'Reporting on href "%s"', $href);
    $href_in .= $href_in == '' ? '' : ', ';
    $href_in .= ':href' . $k;
    $params[':href' . $k] = $href;
}
$where = " WHERE caldav_data.collection_id = " . $collection->resource_id();
$where .= " AND caldav_data.dav_name IN ( {$href_in} ) ";
if ($mode == 'caldav') {
    if ($collection->Privileges() != privilege_to_bits('DAV::all')) {
        $where .= " AND (calendar_item.class != 'PRIVATE' OR calendar_item.class IS NULL) ";
    }
}
$sql = 'SELECT calendar_item.*, addressbook_resource.*, caldav_data.* FROM caldav_data
                  LEFT JOIN calendar_item USING(dav_id, user_no, dav_name, collection_id)
                  LEFT JOIN addressbook_resource USING(dav_id)
                  LEFT JOIN collection USING(collection_id)';
/**
 * @todo: Add stanzas for missing rows, so we don't just return a blank multistatus but
 * actually return <response> stanzas with a 404 for each absent href.  We could do
 * this relatively easily with an array_flip($params) and remove each matching dav_name
 * as we process it.
Пример #4
0
function export_iCalendar(DAVResource $dav_resource)
{
    global $session, $c, $request;
    if (!$dav_resource->IsCalendar() && !(isset($c->get_includes_subcollections) && $c->get_includes_subcollections)) {
        /** RFC2616 says we must send an Allow header if we send a 405 */
        header("Allow: PROPFIND,PROPPATCH,OPTIONS,MKCOL,REPORT,DELETE");
        $request->DoResponse(405, translate("GET requests on collections are only supported for calendars."));
    }
    /**
     * The CalDAV specification does not define GET on a collection, but typically this is
     * used as a .ics download for the whole collection, which is what we do also.
     */
    if (isset($c->get_includes_subcollections) && $c->get_includes_subcollections) {
        $where = 'caldav_data.collection_id IN ';
        $where .= '(SELECT bound_source_id FROM dav_binding WHERE dav_binding.dav_name ~ :path_match ';
        $where .= 'UNION ';
        $where .= 'SELECT collection_id FROM collection WHERE collection.dav_name ~ :path_match) ';
        $params = array(':path_match' => '^' . $dav_resource->dav_name());
        $distinct = 'DISTINCT ON (calendar_item.uid) ';
    } else {
        $where = 'caldav_data.collection_id = :collection_id ';
        $params = array(':collection_id' => $dav_resource->resource_id());
        $distinct = '';
    }
    $sql = 'SELECT ' . $distinct . ' caldav_data, class, caldav_type, calendar_item.user_no, logged_user ';
    $sql .= 'FROM collection INNER JOIN caldav_data USING(collection_id) ';
    $sql .= 'INNER JOIN calendar_item USING ( dav_id ) WHERE ' . $where;
    if (isset($c->strict_result_ordering) && $c->strict_result_ordering) {
        $sql .= ' ORDER BY calendar_item.uid, calendar_item.dav_id';
    }
    $qry = new AwlQuery($sql, $params);
    if (!$qry->Exec("GET", __LINE__, __FILE__)) {
        $request->DoResponse(500, translate("Database Error"));
    }
    /**
     * Here we are constructing a whole calendar response for this collection, including
     * the timezones that are referred to by the events we have selected.
     */
    $vcal = new iCalComponent();
    $vcal->VCalendar();
    $displayname = $dav_resource->GetProperty('displayname');
    if (isset($displayname)) {
        $vcal->AddProperty("X-WR-CALNAME", $displayname);
    }
    if (!empty($c->auto_refresh_duration)) {
        $vcal->AddProperty("X-APPLE-AUTO-REFRESH-INTERVAL", $c->auto_refresh_duration);
        $vcal->AddProperty("AUTO-REFRESH", $c->auto_refresh_duration);
        $vcal->AddProperty("X-PUBLISHED-TTL", $c->auto_refresh_duration);
    }
    $need_zones = array();
    $timezones = array();
    while ($event = $qry->Fetch()) {
        $ical = new iCalComponent($event->caldav_data);
        /** Save the timezone component(s) into a minimal set for inclusion later */
        $event_zones = $ical->GetComponents('VTIMEZONE', true);
        foreach ($event_zones as $k => $tz) {
            $tzid = $tz->GetPValue('TZID');
            if (!isset($tzid)) {
                continue;
            }
            if ($tzid != '' && !isset($timezones[$tzid])) {
                $timezones[$tzid] = $tz;
            }
        }
        /** Work out which ones are actually used here */
        $comps = $ical->GetComponents('VTIMEZONE', false);
        foreach ($comps as $k => $comp) {
            $tzid = $comp->GetPParamValue('DTSTART', 'TZID');
            if (isset($tzid) && !isset($need_zones[$tzid])) {
                $need_zones[$tzid] = 1;
            }
            $tzid = $comp->GetPParamValue('DUE', 'TZID');
            if (isset($tzid) && !isset($need_zones[$tzid])) {
                $need_zones[$tzid] = 1;
            }
            $tzid = $comp->GetPParamValue('DTEND', 'TZID');
            if (isset($tzid) && !isset($need_zones[$tzid])) {
                $need_zones[$tzid] = 1;
            }
            if ($dav_resource->HavePrivilegeTo('all', false) || $session->user_no == $event->user_no || $session->user_no == $event->logged_user || isset($session->email) && $c->allow_get_email_visibility && $comp->IsAttendee($session->email)) {
                /**
                 * These people get to see all of the event, and they should always
                 * get any alarms as well.
                 */
                $vcal->AddComponent($comp);
                continue;
            }
            /** No visibility even of the existence of these events if they aren't admin/owner/attendee */
            if ($event->class == 'PRIVATE') {
                continue;
            }
            if (!$dav_resource->HavePrivilegeTo('DAV::read') || $event->class == 'CONFIDENTIAL') {
                $vcal->AddComponent(obfuscated_event($comp));
            } elseif (isset($c->hide_alarm) && $c->hide_alarm) {
                // Otherwise we hide the alarms (if configured to)
                $comp->ClearComponents('VALARM');
                $vcal->AddComponent($comp);
            } else {
                $vcal->AddComponent($comp);
            }
        }
    }
    /** Put the timezones on there that we need */
    foreach ($need_zones as $tzid => $v) {
        if (isset($timezones[$tzid])) {
            $vcal->AddComponent($timezones[$tzid]);
        }
    }
    return $vcal->Render();
}
Пример #5
0
    $qry = new AwlQuery('SELECT child.collection_id AS child_id FROM collection child JOIN collection parent ON (parent.dav_name = child.parent_container) WHERE parent.collection_id = :collection_id', $params);
    if ($qry->Exec('DELETE', __LINE__, __FILE__) && $qry->rows() > 0) {
        while ($row = $qry->Fetch()) {
            delete_collection($row->child_id);
        }
    }
    if ($qry->QDo("SELECT write_sync_change(collection_id, 404, caldav_data.dav_name) FROM caldav_data WHERE collection_id = :collection_id", $params) && $qry->QDo("DELETE FROM property WHERE dav_name LIKE (SELECT dav_name FROM collection WHERE collection_id = :collection_id) || '%'", $params) && $qry->QDo("DELETE FROM locks WHERE dav_name LIKE (SELECT dav_name FROM collection WHERE collection_id = :collection_id) || '%'", $params) && $qry->QDo("DELETE FROM caldav_data WHERE collection_id = :collection_id", $params) && $qry->QDo("DELETE FROM collection WHERE collection_id = :collection_id", $params)) {
        @dbg_error_log("DELETE", "DELETE (collection): User: %d, ETag: %s, Path: %s", $session->user_no, $request->etag_if_match, $request->path);
        return true;
    }
    return false;
}
if (!$dav_resource->Exists()) {
    $request->DoResponse(404);
}
if (!($dav_resource->resource_id() > 0)) {
    $request->DoResponse(403);
}
$qry = new AwlQuery();
$qry->Begin();
if ($dav_resource->IsCollection()) {
    if ($dav_resource->IsBinding()) {
        $params = array(':dav_name' => $dav_resource->dav_name());
        if ($qry->QDo("DELETE FROM dav_binding WHERE dav_name = :dav_name", $params) && $qry->Commit()) {
            @dbg_error_log("DELETE", "DELETE: Binding: %d, ETag: %s, Path: %s", $session->user_no, $request->etag_if_match, $request->path);
            $request->DoResponse(204);
        }
    } else {
        if (delete_collection($dav_resource->resource_id()) && $qry->Commit()) {
            // Uncache anything to do with the collection
            $cache = getCacheInstance();
Пример #6
0
    $qry = new AwlQuery('SELECT child.collection_id AS child_id FROM collection child JOIN collection parent ON (parent.dav_name = child.parent_container) WHERE parent.collection_id = :collection_id', $params);
    if ($qry->Exec('DELETE', __LINE__, __FILE__) && $qry->rows() > 0) {
        while ($row = $qry->Fetch()) {
            delete_collection($row->child_id);
        }
    }
    if ($qry->QDo("SELECT write_sync_change(collection_id, 404, caldav_data.dav_name) FROM caldav_data WHERE collection_id = :collection_id", $params) && $qry->QDo("DELETE FROM property WHERE dav_name LIKE (SELECT dav_name FROM collection WHERE collection_id = :collection_id) || '%'", $params) && $qry->QDo("DELETE FROM locks WHERE dav_name LIKE (SELECT dav_name FROM collection WHERE collection_id = :collection_id) || '%'", $params) && $qry->QDo("DELETE FROM caldav_data WHERE collection_id = :collection_id", $params) && $qry->QDo("DELETE FROM collection WHERE collection_id = :collection_id", $params)) {
        @dbg_error_log("DELETE", "DELETE (collection): User: %d, ETag: %s, Path: %s", $session->user_no, $request->etag_if_match, $request->path);
        return true;
    }
    return false;
}
if (!$dav_resource->Exists()) {
    $request->DoResponse(404);
}
if (!($dav_resource->resource_id() > 0)) {
    $request->DoResponse(403);
}
$qry = new AwlQuery();
$qry->Begin();
if ($dav_resource->IsBinding()) {
    $params = array(':dav_name' => $dav_resource->dav_name());
    if ($qry->QDo("DELETE FROM dav_binding WHERE dav_name = :dav_name", $params) && $qry->Commit()) {
        @dbg_error_log("DELETE", "DELETE: Binding: %d, ETag: %s, Path: %s", $session->user_no, $request->etag_if_match, $request->path);
        $request->DoResponse(204);
    }
} else {
    if ($dav_resource->IsCollection()) {
        if (delete_collection($dav_resource->resource_id()) && $qry->Commit()) {
            $request->DoResponse(204);
        }