コード例 #1
0
/**
* Expand the properties, recursing only once
*/
function expand_properties($urls, $ptree, &$reply, $recurse_again = true)
{
    if (!is_array($urls)) {
        $urls = array($urls);
    }
    if (!is_array($ptree)) {
        $ptree = array($ptree);
    }
    $responses = array();
    foreach ($urls as $m => $url) {
        $resource = new DAVResource($url);
        $props = array();
        $subtrees = array();
        foreach ($ptree as $n => $property) {
            if (!is_object($property)) {
                continue;
            }
            $pname = $property->GetAttribute('name');
            $pns = $property->GetAttribute('namespace');
            if (!isset($pns) || $pns == '') {
                $pns = 'DAV:';
            }
            // Not sure if this is the correct way to default this.
            $pname = $pns . ':' . $pname;
            $props[] = $pname;
            $subtrees[$pname] = $property->GetElements();
        }
        $part_response = $resource->RenderAsXML($props, $reply);
        if (isset($part_response)) {
            if ($recurse_again) {
                $href_containers = get_href_containers($part_response);
                if (isset($href_containers)) {
                    foreach ($href_containers as $h => $property) {
                        $hrefs = $property->GetElements();
                        $pname = $property->GetTag();
                        $pns = $property->GetAttribute('xmlns');
                        if (!isset($pns) || $pns == '') {
                            $pns = 'DAV:';
                        }
                        // Not sure if this is the correct way to default this.
                        $pname = $pns . ':' . $pname;
                        $paths = array();
                        foreach ($hrefs as $k => $v) {
                            $content = $v->GetContent();
                            $paths[] = $content;
                        }
                        //            dbg_error_log('REPORT',' Found property "%s" contains hrefs "%s"', $pname, implode(', ',$paths) );
                        $property->SetContent(expand_properties($paths, $subtrees[$pname], $reply, false));
                    }
                }
                //      else {
                //        dbg_error_log('REPORT',' No href containers in response to "%s"', implode(', ', $props ) );
                //      }
            }
            $responses[] = $part_response;
        }
    }
    return $responses;
}
コード例 #2
0
/**
 * Entry point for scheduling on DELETE, for which there are thee outcomes:
 *  - We don't do scheduling (disabled, no organizer, ...)
 *  - We are an ATTENDEE declining the meeting.
 *  - We are the ORGANIZER canceling the meeting.
 *   
 * @param DAVResource $deleted_resource The resource which has already been deleted
 */
function do_scheduling_for_delete(DAVResource $deleted_resource)
{
    // By the time we arrive here the resource *has* actually been deleted from disk
    // we can only fail to (de-)schedule the activity...
    global $request, $c;
    if (!isset($request) || isset($c->enable_auto_schedule) && !$c->enable_auto_schedule) {
        return true;
    }
    if ($deleted_resource->IsInSchedulingCollection()) {
        return true;
    }
    $caldav_data = $deleted_resource->GetProperty('dav-data');
    if (empty($caldav_data)) {
        return true;
    }
    $vcal = new vCalendar($caldav_data);
    $organizer = $vcal->GetOrganizer();
    if ($organizer === false || empty($organizer)) {
        dbg_error_log('schedule', 'Event has no organizer - no scheduling required.');
        return true;
    }
    if ($vcal->GetScheduleAgent() != 'SERVER') {
        dbg_error_log('schedule', 'SCHEDULE-AGENT=%s - no scheduling required.', $vcal->GetScheduleAgent());
        return true;
    }
    $organizer_email = preg_replace('/^mailto:/i', '', $organizer->Value());
    if ($request->principal->email() == $organizer_email) {
        return doItipOrganizerCancel($vcal);
    } else {
        if (isset($_SERVER['HTTP_SCHEDULE_REPLY']) && $_SERVER['HTTP_SCHEDULE_REPLY'] == 'F') {
            dbg_error_log('schedule', 'Schedule-Reply header set to "F" - no scheduling required.');
            return true;
        }
        return doItipAttendeeReply($vcal, 'DECLINED', $request->principal->email());
    }
}
コード例 #3
0
                break;
            default:
                /**
                 * @todo We should handle a lot more properties here.  principal-URL seems a likely one to be used.
                 * @todo We should catch the unsupported properties in the query and fire back an error indicating so.
                 */
                dbg_error_log("principal", "Unhandled tag '%s' to match '%s'\n", $v1->GetNSTag(), $match);
        }
    }
    if ($subwhere != "") {
        $where .= sprintf("%s(%s)", $where == "" ? "" : $clause_joiner, $subwhere);
    }
}
if ($where != "") {
    $where = "WHERE {$where}";
}
$sql = "SELECT * FROM dav_principal {$where} ORDER BY principal_id LIMIT 100";
$qry = new AwlQuery($sql, $params);
$get_props = $xmltree->GetPath('/DAV::principal-property-search/DAV::prop/*');
$properties = array();
foreach ($get_props as $k1 => $v1) {
    $properties[] = $v1->GetNSTag();
}
if ($qry->Exec("REPORT", __LINE__, __FILE__) && $qry->rows() > 0) {
    while ($row = $qry->Fetch()) {
        $principal = new DAVResource($row);
        $responses[] = $principal->RenderAsXML($properties, $reply);
    }
}
$multistatus = new XMLElement("multistatus", $responses, $reply->GetXmlNsArray());
$request->XMLResponse(207, $multistatus);
コード例 #4
0
/**
* Get XML response for items in the collection
* If '/' is requested, a list of visible users is given, otherwise
* a list of calendars for the user which are parented by this path.
*/
function get_collection_contents($depth, $collection, $parent_path = null)
{
    global $c, $session, $request, $reply, $property_list;
    $bound_from = $collection->bound_from();
    $bound_to = $collection->dav_name();
    if (!isset($parent_path)) {
        $parent_path = $collection->dav_name();
    }
    dbg_error_log('PROPFIND', 'Getting collection contents: Depth %d, Path: %s, Bound from: %s, Bound to: %s', $depth, $collection->dav_name(), $bound_from, $bound_to);
    $date_format = AwlDatabase::HttpDateFormat;
    $responses = array();
    if (!$collection->IsCalendar() && !$collection->IsAddressbook()) {
        /**
         * Calendar/Addressbook collections may not contain collections, so we are only looking in the other ones
         */
        $params = array(':session_principal' => $session->principal_id, ':scan_depth' => $c->permission_scan_depth);
        if ($bound_from == '/') {
            $sql = "SELECT usr.*, '/' || username || '/' AS dav_name, md5(username || updated::text) AS dav_etag, ";
            $sql .= "to_char(joined at time zone 'GMT',{$date_format}) AS created, ";
            $sql .= "to_char(updated at time zone 'GMT',{$date_format}) AS modified, ";
            $sql .= 'FALSE AS is_calendar, TRUE AS is_principal, FALSE AS is_addressbook, \'principal\' AS type, ';
            $sql .= 'principal_id AS collection_id, ';
            $sql .= 'principal.* ';
            $sql .= 'FROM usr JOIN principal USING (user_no) ';
            $sql .= "WHERE (pprivs(:session_principal::int8,principal.principal_id,:scan_depth::int) & 1::BIT(24))::INT4::BOOLEAN ";
            $sql .= 'ORDER BY usr.user_no';
        } else {
            $qry = new AwlQuery('SELECT * FROM dav_binding WHERE dav_binding.parent_container = :this_dav_name ORDER BY bind_id', array(':this_dav_name' => $bound_from));
            if ($qry->Exec('PROPFIND', __LINE__, __FILE__) && $qry->rows() > 0) {
                while ($binding = $qry->Fetch()) {
                    $resource = new DAVResource($binding->dav_name);
                    if ($resource->IsExternal()) {
                        require_once "external-fetch.php";
                        update_external($resource);
                    }
                    if ($resource->HavePrivilegeTo('DAV::read', false)) {
                        $resource->set_bind_location(str_replace($bound_from, $bound_to, $binding->dav_name));
                        $responses[] = $resource->RenderAsXML($property_list, $reply);
                        if ($depth > 0) {
                            $responses = array_merge($responses, get_collection_contents($depth - 1, $resource, $binding->dav_name));
                        }
                    }
                }
            }
            $sql = 'SELECT principal.*, collection.*, \'collection\' AS type ';
            $sql .= 'FROM collection LEFT JOIN principal USING (user_no) ';
            $sql .= 'WHERE parent_container = :this_dav_name ';
            $sql .= ' ORDER BY collection_id';
            $params[':this_dav_name'] = $bound_from;
            unset($params[':session_principal']);
            unset($params[':scan_depth']);
        }
        $qry = new AwlQuery($sql, $params);
        if ($qry->Exec('PROPFIND', __LINE__, __FILE__) && $qry->rows() > 0) {
            while ($subcollection = $qry->Fetch()) {
                $resource = new DAVResource($subcollection);
                if (!$resource->HavePrivilegeTo('DAV::read')) {
                    continue;
                }
                $resource->set_bind_location(str_replace($bound_from, $bound_to, $subcollection->dav_name));
                $responses[] = $resource->RenderAsXML($property_list, $reply);
                if ($depth > 0) {
                    $responses = array_merge($responses, get_collection_contents($depth - 1, $resource, str_replace($resource->parent_path(), $parent_path, $resource->dav_name())));
                }
            }
        }
        if ((!isset($c->disable_caldav_proxy) || $c->disable_caldav_proxy == false) && $collection->IsPrincipal()) {
            // Caldav Proxy: 5.1 par. 2: Add child resources calendar-proxy-(read|write)
            dbg_error_log('PROPFIND', 'Adding calendar-proxy-read and write. Path: %s', $bound_from);
            $response = add_proxy_response('read', $bound_from);
            if (isset($response)) {
                $responses[] = $response;
            }
            $response = add_proxy_response('write', $bound_from);
            if (isset($response)) {
                $responses[] = $response;
            }
        }
    }
    /**
     * freebusy permission is not allowed to see the items in a collection.  Must have at least read permission.
     */
    if ($collection->HavePrivilegeTo('DAV::read', false)) {
        dbg_error_log('PROPFIND', 'Getting collection items: Depth %d, Path: %s', $depth, $bound_from);
        $privacy_clause = ' ';
        $todo_clause = ' ';
        $time_limit_clause = ' ';
        if ($collection->IsCalendar()) {
            if (!$collection->HavePrivilegeTo('all', false)) {
                $privacy_clause = " AND (calendar_item.class != 'PRIVATE' OR calendar_item.class IS NULL) ";
            }
            if (isset($c->hide_TODO) && ($c->hide_TODO === true || is_string($c->hide_TODO) && preg_match($c->hide_TODO, $_SERVER['HTTP_USER_AGENT'])) && !$collection->HavePrivilegeTo('all')) {
                $todo_clause = " AND caldav_data.caldav_type NOT IN ('VTODO') ";
            }
            if (isset($c->hide_older_than) && intval($c->hide_older_than > 0)) {
                $time_limit_clause = " AND (CASE WHEN caldav_data.caldav_type<>'VEVENT' OR calendar_item.dtstart IS NULL THEN true ELSE calendar_item.dtstart > (now() - interval '" . intval($c->hide_older_than) . " days') END) ";
            }
        }
        $sql = 'SELECT collection.*, principal.*, calendar_item.*, caldav_data.*, ';
        $sql .= "to_char(coalesce(calendar_item.created, caldav_data.created) at time zone 'GMT',{$date_format}) AS created, ";
        $sql .= "to_char(coalesce(calendar_item.last_modified, caldav_data.modified) at time zone 'GMT',{$date_format}) AS modified, ";
        $sql .= 'summary AS dav_displayname ';
        $sql .= 'FROM caldav_data LEFT JOIN calendar_item USING( dav_id, user_no, dav_name, collection_id) ';
        $sql .= 'LEFT JOIN collection USING(collection_id,user_no) LEFT JOIN principal USING(user_no) ';
        $sql .= 'WHERE collection.dav_name = :collection_dav_name ' . $time_limit_clause . ' ' . $todo_clause . ' ' . $privacy_clause;
        if (isset($c->strict_result_ordering) && $c->strict_result_ordering) {
            $sql .= " ORDER BY caldav_data.dav_id";
        }
        $qry = new AwlQuery($sql, array(':collection_dav_name' => $bound_from));
        if ($qry->Exec('PROPFIND', __LINE__, __FILE__) && $qry->rows() > 0) {
            while ($item = $qry->Fetch()) {
                if ($bound_from != $bound_to) {
                    $item->bound_from = $item->dav_name;
                    $item->dav_name = str_replace($bound_from, $bound_to, $item->dav_name);
                }
                $resource = new DAVResource($item);
                $responses[] = $resource->RenderAsXML($property_list, $reply, $parent_path);
            }
        }
    }
    return $responses;
}
コード例 #5
0
ファイル: caldav-GET.php プロジェクト: rossryan/Calico
<?php

/**
* 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');
コード例 #6
0
* 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);
コード例 #7
0
                    }
                }
                /** Else:
                 *    the object existed at start and we have multiple modifications,
                 *  or,
                 *    the object didn't exist at start and we have subsequent modifications,
                 *  but:
                 *    in either case we simply stick with our existing report.
                 */
            } else {
                /** The simple case: this is the first one for this dav_id */
                if ($object->sync_status == 404) {
                    $resultset = array(new XMLElement('href', ConstructURL($object->dav_name)), new XMLElement('status', display_status($object->sync_status)));
                    $first_status = 404;
                } else {
                    $dav_resource = new DAVResource($object);
                    $resultset = $dav_resource->GetPropStat($proplist, $reply);
                    array_unshift($resultset, new XMLElement('href', ConstructURL($object->dav_name)));
                    $first_status = $object->sync_status;
                }
                $responses[] = new XMLElement('response', $resultset);
                $last_dav_name = $object->dav_name;
            }
        }
        $responses[] = new XMLElement('sync-token', 'data:,' . $new_token);
    } else {
        $request->DoResponse(500, translate("Database error"));
    }
}
$multistatus = new XMLElement("multistatus", $responses, $reply->GetXmlNsArray());
$request->XMLResponse(207, $multistatus);
コード例 #8
0
ファイル: caldav-OPTIONS.php プロジェクト: rossryan/Calico
<?php

/**
* CalDAV Server - handle OPTIONS 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("OPTIONS", "method handler");
include_once 'DAVResource.php';
$resource = new DAVResource($request->path);
$resource->NeedPrivilege('DAV::read', true);
if (!$resource->Exists()) {
    $request->DoResponse(404, translate("No collection found at that location."));
}
$allowed = implode(', ', array_keys($resource->FetchSupportedMethods()));
header('Allow: ' . $allowed);
$request->DoResponse(200, "");
コード例 #9
0
ファイル: caldav-PROPPATCH.php プロジェクト: rossryan/Calico
<?php

/**
* CalDAV Server - handle PROPPATCH method
*
* @package   davical
* @subpackage   caldav
* @author    Andrew McMillan <*****@*****.**>
* @copyright Morphoss Ltd - http://www.morphoss.com/
* @license   http://gnu.org/copyleft/gpl.html GNU GPL v2
*/
dbg_error_log("PROPPATCH", "method handler");
require_once 'iCalendar.php';
require_once 'DAVResource.php';
$dav_resource = new DAVResource($request->path);
if (!($dav_resource->HavePrivilegeTo('DAV::write-properties') || $dav_resource->IsBinding())) {
    $request->DoResponse(403);
}
$position = 0;
$xmltree = BuildXMLTree($request->xml_tags, $position);
// echo $xmltree->Render();
if ($xmltree->GetTag() != "DAV::propertyupdate") {
    $request->DoResponse(403);
}
/**
* Find the properties being set, and the properties being removed
*/
$setprops = $xmltree->GetPath("/DAV::propertyupdate/DAV::set/DAV::prop/*");
$rmprops = $xmltree->GetPath("/DAV::propertyupdate/DAV::remove/DAV::prop/*");
/**
* We build full status responses for failures.  For success we just record
コード例 #10
0
ファイル: caldav-DELETE.php プロジェクト: derekyu1437/davical
<?php

/**
* CalDAV Server - handle DELETE 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("delete", "DELETE method handler");
require_once 'DAVResource.php';
$dav_resource = new DAVResource($request->path);
$container = $dav_resource->GetParentContainer();
$container->NeedPrivilege('DAV::unbind');
$lock_opener = $request->FailIfLocked();
require_once 'schedule-functions.php';
function delete_collection($id)
{
    $params = array(':collection_id' => $id);
    $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;
    }
コード例 #11
0
ファイル: load_calendar.php プロジェクト: derekyu1437/davical
            $this->{$k} = $v;
        }
        $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');
コード例 #12
0
    $vcalendar->SetUID($uid);
}
if ($add_member) {
    $request->path = $request->dav_name() . $uid . '.ics';
    $dav_resource = new DAVResource($request->path);
    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);
コード例 #13
0
/**
* Deliver scheduling replies to organizer and other attendees
* @param iCalComponent $ical the VCALENDAR to deliver
* @return false on error
*/
function handle_schedule_reply($ical)
{
    global $c, $session, $request;
    $resources = $ical->GetComponents('VTIMEZONE', false);
    $ic = $resources[0];
    $etag = md5($request->raw_post);
    $organizer = $ic->GetProperties('ORGANIZER');
    // for now we treat events with out organizers as an error
    if (count($organizer) < 1) {
        return false;
    }
    $attendees = array_merge($organizer, $ic->GetProperties('ATTENDEE'));
    $wr_attendees = $ic->GetProperties('X-WR-ATTENDEE');
    if (count($wr_attendees) > 0) {
        dbg_error_log("POST", "Non-compliant iCal request.  Using X-WR-ATTENDEE property");
        foreach ($wr_attendees as $k => $v) {
            $attendees[] = $v;
        }
    }
    dbg_error_log("POST", "Attempting to deliver scheduling request for %d attendees", count($attendees));
    foreach ($attendees as $k => $attendee) {
        $attendee_email = preg_replace('/^mailto:/', '', $attendee->Value());
        dbg_error_log("POST", "Delivering to %s", $attendee_email);
        $attendee_principal = new CalDAVPrincipal(array('email' => $attendee_email, 'options' => array('allow_by_email' => true)));
        $deliver_path = preg_replace('/^.*caldav.php/', '', $attendee_principal->schedule_inbox_url);
        $attendee_email = preg_replace('/^mailto:/', '', $attendee->Value());
        if ($attendee_email == $request->principal->email) {
            dbg_error_log("POST", "not delivering to owner");
            continue;
        }
        $ar = new DAVResource($deliver_path);
        if (!$ar->HavePrivilegeTo('schedule-deliver-reply')) {
            $reply = new XMLDocument(array('DAV:' => ''));
            $privnodes = array($reply->href(ConstructURL($attendee_principal->schedule_inbox_url)), new XMLElement('privilege'));
            // RFC3744 specifies that we can only respond with one needed privilege, so we pick the first.
            $reply->NSElement($privnodes[1], 'schedule-deliver-reply');
            $xml = new XMLElement('need-privileges', new XMLElement('resource', $privnodes));
            $xmldoc = $reply->Render('error', $xml);
            $request->DoResponse(403, $xmldoc, 'text/xml; charset="utf-8"');
            continue;
        }
        $ncal = new iCalComponent();
        $ncal->VCalendar();
        $ncal->AddProperty('METHOD', 'REPLY');
        $ncal->AddComponent(array_merge($ical->GetComponents('VEVENT', false), array($ic)));
        $content = $ncal->Render();
        write_resource($attendee_principal->user_no, $deliver_path . $etag . '.ics', $content, $ar->GetProperty('collection_id'), $request->user_no, md5($content), $ncal, $put_action_type = 'INSERT', $caldav_context = true, $log_action = true, $etag);
    }
    $request->DoResponse(201, 'Created');
}
コード例 #14
0
ファイル: caldav-ACL.php プロジェクト: derekyu1437/davical
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;
    }
}
コード例 #15
0
ファイル: caldav-GET.php プロジェクト: derekyu1437/davical
<?php

/**
* 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 "caldav-GET-functions.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->IsExternal()) {
    require_once "external-fetch.php";
    update_external($dav_resource);
}
if (!$dav_resource->Exists()) {
    $request->DoResponse(404, translate("Resource Not Found."));
}
if ($dav_resource->IsCollection()) {
    $response = export_iCalendar($dav_resource);
    header('Etag: ' . $dav_resource->unique_tag());
    $request->DoResponse(200, $request->method == 'HEAD' ? '' : $response, 'text/calendar; charset="utf-8"');
}
// Just a single event then
$resource = $dav_resource->resource();
$ic = new iCalComponent($resource->caldav_data);
$resource->caldav_data = preg_replace('{(?<!\\r)\\n}', "\r\n", $resource->caldav_data);
コード例 #16
0
 */
function BuildSqlFilter($filter)
{
    $components = array();
    if ($filter->GetNSTag() == "urn:ietf:params:xml:ns:caldav:comp-filter" && $filter->GetAttribute("name") == "VCALENDAR") {
        $filter = $filter->GetContent();
    } else {
        dbg_error_log("calquery", "Got bizarre CALDAV:FILTER[%s=%s]] which does not contain comp-filter = VCALENDAR!!", $filter->GetNSTag(), $filter->GetAttribute("name"));
    }
    return SqlFilterFragment($filter, $components);
}
/**
* 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);
}
$params = array();
if (!($target_collection->IsCalendar() || $target_collection->IsSchedulingCollection())) {
    if (!(isset($c->allow_recursive_report) && $c->allow_recursive_report)) {
        $request->DoResponse(403, translate('The calendar-query report must be run against a calendar or a scheduling collection'));
    } else {
        if ($request->path == '/' || $target_collection->IsPrincipal() || $target_collection->IsAddressbook()) {
            $request->DoResponse(403, translate('The calendar-query report may not be run against that URL.'));
        }
    }
    /**
     * We're here because they allow recursive reports, and this appears to be such a location.
コード例 #17
0
* @subpackage   caldav
* @author    Andrew McMillan <*****@*****.**>
* @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 ($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'));
    }
コード例 #18
0
ファイル: caldav-MKCOL.php プロジェクト: derekyu1437/davical
dbg_error_log('MKCOL', 'method handler');
require_once 'AwlQuery.php';
$request->NeedPrivilege('DAV::bind');
$displayname = $request->path;
// Enforce trailling '/' on collection name
if (!preg_match('#/$#', $request->path)) {
    dbg_error_log('MKCOL', 'Add trailling "/" to "%s"', $request->path);
    $request->path .= '/';
}
$parent_container = '/';
if (preg_match('#^(.*/)([^/]+)(/)?$#', $request->path, $matches)) {
    $parent_container = $matches[1];
    $displayname = $matches[2];
}
require_once 'DAVResource.php';
$parent = new DAVResource($parent_container);
if ($parent->IsSchedulingCollection('inbox')) {
    $request->PreconditionFailed(403, 'urn:ietf:params:xml:ns:caldav:no-mkcol-in-inbox');
}
$request_type = $request->method;
$is_calendar = $request_type == 'MKCALENDAR';
$is_addressbook = false;
$resourcetypes = '<DAV::collection/>';
if ($is_calendar) {
    $resourcetypes .= '<urn:ietf:params:xml:ns:caldav:calendar/>';
}
require_once 'XMLDocument.php';
$reply = new XMLDocument(array('DAV:' => '', 'urn:ietf:params:xml:ns:caldav' => 'C'));
$failure_code = null;
$failure = array();
$dav_properties = array();
コード例 #19
0
ファイル: caldav-MOVE.php プロジェクト: derekyu1437/davical
$lock_opener = $request->FailIfLocked();
$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:
コード例 #20
0
ファイル: caldav-BIND.php プロジェクト: derekyu1437/davical
        }
        fetch_external($row->bind_id, '');
        $request->DoResponse(201);
    } else {
        $request->DoResponse(500, translate('Database Error'));
    }
} else {
    $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.'));
    }
    if ($source->IsBinding()) {
        $source = new DAVResource($source->bound_from());
    }
    /*
      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,
      external_url TEXT,
      type 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 )';
    $params = array(':target_id' => $source->GetProperty('collection_id'), ':ticket_id' => isset($request->ticket) ? $request->ticket->id() : null, ':parent_container' => $parent->dav_name(), ':session_principal' => $session->principal_id, ':dav_name' => $destination_path, ':displayname' => $source->GetProperty('displayname'));
    $qry = new AwlQuery($sql, $params);
コード例 #21
0
            }
            break;
            */
            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();
コード例 #22
0
 * elements of the filter which are implemented in the SQL will be removed.
 *
 * @param arrayref &$filter A reference to an array of XMLElement defining the filter
 *
 * @return string A string suitable for use as an SQL 'WHERE' clause selecting the desired records.
 */
function BuildSqlFilter($filter)
{
    $components = array();
    return SqlFilterFragment($filter, $components);
}
/**
* 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);
}
$params = array();
$where = ' WHERE caldav_data.collection_id = ' . $target_collection->resource_id();
if (!($target_collection->IsCalendar() || $target_collection->IsSchedulingCollection())) {
    if (!(isset($c->allow_recursive_report) && $c->allow_recursive_report) || $target_collection->IsSchedulingCollection()) {
        $request->DoResponse(403, translate('The calendar-query report must be run against a calendar or a scheduling collection'));
    }
    /**
     * We're here because they allow recursive reports, and this appears to be such a location.
     */
    $where = 'WHERE (collection.dav_name ~ :path_match ';
    $where .= 'OR collection.collection_id IN (SELECT bound_source_id FROM dav_binding WHERE dav_binding.dav_name ~ :path_match)) ';
コード例 #23
0
ファイル: caldav-PUT-vcard.php プロジェクト: rossryan/Calico
* @subpackage   caldav
* @author    Andrew McMillan <*****@*****.**>
* @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'));
コード例 #24
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();
}
コード例 #25
0
ファイル: caldav-PUT.php プロジェクト: rossryan/Calico
<?php

/**
* 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()) {
コード例 #26
0
            foreach ($qry_content[1]->GetElements() as $k => $v) {
                $include_properties[] = $v->GetNSTag();
                /** $include_properties is referenced in DAVResource where allprop is expanded */
                if ($v->GetNSTag() == 'urn:ietf:params:xml:ns:caldav:calendar-data') {
                    check_for_expansion($v);
                }
            }
        }
        break;
    default:
        $properties[$proptype] = 1;
}
if (empty($properties)) {
    $properties['DAV::allprop'] = 1;
}
$collection = new DAVResource($request->path);
$bound_from = $collection->bound_from();
/**
 * Build the href list for the IN ( href, href, href, ... ) clause.
 */
$mg_hrefs = $xmltree->GetPath('/*/DAV::href');
$href_in = '';
$params = array();
foreach ($mg_hrefs as $k => $v) {
    /**
     * We need this to work if they specified a relative *or* a full path, so we strip off
     * 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);
コード例 #27
0
ファイル: caldav-REPORT.php プロジェクト: rossryan/Calico
if (!ini_get('open_basedir') && (isset($c->dbg['ALL']) || isset($c->dbg['report']) && $c->dbg['report'])) {
    $fh = fopen('/tmp/REPORT.txt', 'w');
    if ($fh) {
        fwrite($fh, $request->raw_post);
        fclose($fh);
    }
}
if (!isset($request->xml_tags)) {
    $request->DoResponse(406, translate("REPORT body contains no XML data!"));
}
$position = 0;
$xmltree = BuildXMLTree($request->xml_tags, $position);
if (!is_object($xmltree)) {
    $request->DoResponse(406, translate("REPORT body is not valid XML data!"));
}
$target = new DAVResource($request->path);
if ($xmltree->GetTag() != 'DAV::principal-property-search' && $xmltree->GetTag() != 'DAV::principal-property-search-set') {
    $target->NeedPrivilege(array('DAV::read', 'urn:ietf:params:xml:ns:caldav:read-free-busy'), true);
    // They may have either
}
require_once "iCalendar.php";
$reportnum = -1;
$report = array();
$denied = array();
$unsupported = array();
if (isset($prop_filter)) {
    unset($prop_filter);
}
if ($xmltree->GetTag() == 'urn:ietf:params:xml:ns:caldav:free-busy-query') {
    include "caldav-REPORT-freebusy.php";
    exit;
コード例 #28
0
/**
* A slightly simpler version of write_resource which will make more sense for calling from
* an external program.  This makes assumptions that the collection and user do exist
* and bypasses all checks for whether it is reasonable to write this here.
* @param string $path The path to the resource being written
* @param string $caldav_data The actual resource to be written
* @param string $put_action_type INSERT or UPDATE depending on what we are to do
* @return boolean True for success, false for failure.
*/
function simple_write_resource($path, $caldav_data, $put_action_type, $write_action_log = false)
{
    global $session;
    /**
     * We pull the user_no & collection_id out of the collection table, based on the resource path
     */
    $dav_resource = new DAVResource($path);
    $etag = md5($caldav_data);
    $collection_path = preg_replace('#/[^/]*$#', '/', $path);
    $collection = new DAVResource($collection_path);
    if ($collection->IsCollection() || $collection->IsSchedulingCollection()) {
        return write_resource($dav_resource, $caldav_data, $collection, $session->user_no, $etag, $put_action_type, false, $write_action_log);
    }
    return false;
}
コード例 #29
0
ファイル: caldav-MKTICKET.php プロジェクト: rossryan/Calico
* with some documented variations, which we will also follow.  In particular
* 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()) {
コード例 #30
0
ファイル: caldav-MOVE.php プロジェクト: rossryan/Calico
$lock_opener = $request->FailIfLocked();
$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: