コード例 #1
0
ファイル: iSchedule.php プロジェクト: derekyu1437/davical
function SRVOk($value, $name, $row)
{
    global $BrowserCurrentRow;
    if (empty($BrowserCurrentRow->domain)) {
        return '';
    }
    // skip empty rows
    $s = new iSchedule();
    $s->domain = $BrowserCurrentRow->domain;
    return translate($s->getServer() ? 'OK' : SRVFormat($s->domain));
}
コード例 #2
0
/**
* Create/Update the scheduling requests for this resource.  This includes updating
* the scheduled user's default calendar.
* @param vComponent $resource The VEVENT/VTODO/... resource we are scheduling
* @param boolean $create true if the scheduling requests are being created.
* @return true If there was any scheduling action
*/
function do_scheduling_requests(vCalendar $resource, $create, $old_data = null, $remoteAttendee = false)
{
    global $request, $c;
    if (!isset($request) || isset($c->enable_auto_schedule) && !$c->enable_auto_schedule) {
        return false;
    }
    if (!is_object($resource)) {
        trace_bug('do_scheduling_requests called with non-object parameter (%s)', gettype($resource));
        return false;
    }
    $organizer = $resource->GetOrganizer();
    if ($organizer === false || empty($organizer)) {
        dbg_error_log('PUT', 'Event has no organizer - no scheduling required.');
        return false;
    }
    $organizer_email = preg_replace('/^mailto:/i', '', $organizer->Value());
    if ($request->principal->email() != $organizer_email) {
        return do_scheduling_reply($resource, $organizer);
    }
    $schedule_request = clone $resource;
    $schedule_request->AddProperty('METHOD', 'REQUEST');
    $old_attendees = array();
    if (!empty($old_data)) {
        $old_resource = new vCalendar($old_data);
        $old_attendees = $old_resource->GetAttendees();
    }
    $attendees = $resource->GetAttendees();
    if (count($attendees) == 0 && count($old_attendees) == 0) {
        dbg_error_log('PUT', 'Event has no attendees - no scheduling required.', count($attendees));
        return false;
    }
    $removed_attendees = array();
    foreach ($old_attendees as $attendee) {
        $email = preg_replace('/^mailto:/i', '', $attendee->Value());
        if ($email == $request->principal->email()) {
            continue;
        }
        $removed_attendees[$email] = $attendee;
    }
    $uids = $resource->GetPropertiesByPath('/VCALENDAR/*/UID');
    if (count($uids) == 0) {
        dbg_error_log('PUT', 'No UID in VCALENDAR - giving up on REPLY.');
        return false;
    }
    $uid = $uids[0]->Value();
    dbg_error_log('PUT', 'Writing scheduling resources for %d attendees', count($attendees));
    $scheduling_actions = false;
    foreach ($attendees as $attendee) {
        $email = preg_replace('/^mailto:/i', '', $attendee->Value());
        if ($email == $request->principal->email()) {
            dbg_error_log("PUT", "not delivering to owner '%s'", $request->principal->email());
            continue;
        }
        if ($create) {
            $attendee_is_new = true;
        } else {
            $attendee_is_new = !isset($removed_attendees[$email]);
            if (!$attendee_is_new) {
                unset($removed_attendees[$email]);
            }
        }
        $agent = $attendee->GetParameterValue('SCHEDULE-AGENT');
        if ($agent && $agent != 'SERVER') {
            dbg_error_log("PUT", "not delivering to %s, schedule agent set to value other than server", $email);
            continue;
        }
        $schedule_target = new Principal('email', $email);
        $response = '3.7';
        // Attendee was not found on server.
        dbg_error_log('PUT', 'Handling scheduling resources for %s on %s which is %s', $email, $create ? 'create' : 'update', $attendee_is_new ? 'new' : 'an update');
        if ($schedule_target->Exists()) {
            // Instead of always writing to schedule-default-calendar, we first try to
            // find a calendar with an existing instance of the event.
            $sql = 'SELECT caldav_data.dav_name, caldav_data.caldav_data, caldav_data.collection_id FROM caldav_data JOIN calendar_item USING(dav_id) ';
            $sql .= 'WHERE caldav_data.collection_id IN (SELECT collection_id FROM collection WHERE is_calendar AND user_no =?) ';
            $sql .= 'AND uid=? LIMIT 1';
            $qry = new AwlQuery($sql, $schedule_target->user_no(), $uid);
            if (!$qry->Exec('PUT', __LINE__, __FILE__) || $qry->rows() < 1) {
                dbg_error_log('PUT', "Could not find event in attendee's calendars");
                $attendee_calendar = new WritableCollection(array('path' => $schedule_target->internal_url('schedule-default-calendar')));
            } else {
                $row = $qry->Fetch();
                $r = new DAVResource($row);
                $attendee_calendar = new WritableCollection(array('path' => $r->parent_path()));
                if ($attendee_calendar->IsCalendar()) {
                    dbg_error_log('XXX', "found the event in attendee's calendar %s", $attendee_calendar->dav_name());
                } else {
                    dbg_error_log('XXX', 'could not find the event in any calendar, using schedule-default-calendar');
                    $attendee_calendar = new WritableCollection(array('path' => $schedule_target->internal_url('schedule-default-calendar')));
                }
            }
            if (!$attendee_calendar->Exists()) {
                dbg_error_log('ERROR', 'Default calendar at "%s" does not exist for user "%s"', $attendee_calendar->dav_name(), $schedule_target->username());
                $response = '5.2';
                // No scheduling support for user
            } else {
                $attendee_inbox = new WritableCollection(array('path' => $schedule_target->internal_url('schedule-inbox')));
                if (!$attendee_inbox->HavePrivilegeTo('schedule-deliver-invite')) {
                    $response = '3.8';
                    // No authority to deliver invitations to user.
                } else {
                    if ($attendee_inbox->WriteCalendarMember($schedule_request, $attendee_is_new) !== false) {
                        $response = '1.2';
                        // Scheduling invitation delivered successfully
                        if ($attendee_calendar->WriteCalendarMember($resource, $attendee_is_new) === false) {
                            dbg_error_log('ERROR', 'Could not write %s calendar member to %s', $attendee_is_new ? 'new' : 'updated', $attendee_calendar->dav_name(), $attendee_calendar->dav_name(), $schedule_target->username());
                            trace_bug('Failed to write scheduling resource.');
                        }
                    }
                }
            }
        } else {
            if ($remoteAttendee) {
                $attendee->is_remote = true;
                $remote = new iSchedule();
                $answer = $remote->sendRequest($email, 'VEVENT/REQUEST', $schedule_request->Render());
            } else {
                $remote = new iSchedule();
                $answer = $remote->sendRequest($email, 'VEVENT/REQUEST', $schedule_request->Render());
                if ($answer === false) {
                    $response = "3.7;Invalid Calendar User";
                } else {
                    foreach ($answer as $a) {
                        if ($a === false) {
                            $response = "3.7;Invalid Calendar User";
                        } elseif (substr($a, 0, 1) >= 1) {
                            $response = $a;
                        } else {
                            $response = "2.0;Success";
                        }
                    }
                }
            }
        }
        dbg_error_log('PUT', 'Status for attendee <%s> set to "%s"', $attendee->Value(), $response);
        $attendee->SetParameterValue('SCHEDULE-STATUS', $response);
        $scheduling_actions = true;
    }
    if (!$create) {
        foreach ($removed_attendees as $attendee) {
            $schedule_target = new Principal('email', $email);
            if ($schedule_target->Exists()) {
                $attendee_calendar = new WritableCollection(array('path' => $schedule_target->internal_url('schedule-default-calendar')));
            }
        }
    }
    return $scheduling_actions;
}
コード例 #3
0
ファイル: iSchedule.php プロジェクト: rossryan/Calico
        global $request;
        if (isset($_SERVER['HTTP_DKIM_SIGNATURE'])) {
            $sig = $_SERVER['HTTP_DKIM_SIGNATURE'];
        } else {
            $request->DoResponse(403, translate('DKIM signature missing'));
        }
        $err = $this->parseDKIM($sig);
        if ($err !== true || $this->failed) {
            $request->DoResponse(403, translate('DKIM signature invalid ') . "\n" . $err . "\n" . $sig);
        }
        if (!$this->getTxt() || $this->failed) {
            $request->DoResponse(403, translate('DKIM signature validation failed(DNS ERROR)'));
        }
        if (!$this->parseTxt() || $this->failed) {
            $request->DoResponse(403, translate('DKIM signature validation failed(KEY Parse ERROR)'));
        }
        if (!$this->validateKey() || $this->failed) {
            $request->DoResponse(403, translate('DKIM signature validation failed(KEY Validation ERROR)'));
        }
        if (!$this->verifySignature() || $this->failed) {
            $request->DoResponse(403, translate('DKIM signature validation failed(Signature verification ERROR)') . $this->verifySignature());
        }
        return true;
    }
}
$d = new iSchedule();
if ($d->validateRequest()) {
    include 'caldav-POST.php';
    // TODO
    // handle request.
}
コード例 #4
0
ファイル: caldav-POST.php プロジェクト: derekyu1437/davical
function handle_freebusy_request($ic)
{
    global $c, $session, $request, $ical;
    $request->NeedPrivilege('CALDAV:schedule-send-freebusy');
    $reply = new XMLDocument(array("DAV:" => "", "urn:ietf:params:xml:ns:caldav" => "C"));
    $responses = array();
    $fbq_start = $ic->GetPValue('DTSTART');
    $fbq_end = $ic->GetPValue('DTEND');
    if (!(isset($fbq_start) || isset($fbq_end))) {
        $request->DoResponse(400, 'All valid freebusy requests MUST contain a DTSTART and a DTEND');
    }
    $range_start = new RepeatRuleDateTime($fbq_start);
    $range_end = new RepeatRuleDateTime($fbq_end);
    $attendees = $ic->GetProperties('ATTENDEE');
    if (preg_match('# iCal/\\d#', $_SERVER['HTTP_USER_AGENT'])) {
        dbg_error_log("POST", "Non-compliant iCal request.  Using X-WR-ATTENDEE property");
        $wr_attendees = $ic->GetProperties('X-WR-ATTENDEE');
        foreach ($wr_attendees as $k => $v) {
            $attendees[] = $v;
        }
    }
    dbg_error_log("POST", "Responding with free/busy for %d attendees", count($attendees));
    foreach ($attendees as $k => $attendee) {
        $attendee_email = preg_replace('/^mailto:/', '', $attendee->Value());
        dbg_error_log("POST", "Calculating free/busy for %s", $attendee_email);
        /** @todo Refactor this so we only do one query here and loop through the results */
        $params = array(':session_principal' => $session->principal_id, ':scan_depth' => $c->permission_scan_depth, ':email' => $attendee_email);
        $qry = new AwlQuery('SELECT pprivs(:session_principal::int8,principal_id,:scan_depth::int) AS p, username FROM usr JOIN principal USING(user_no) WHERE lower(usr.email) = lower(:email)', $params);
        if (!$qry->Exec('POST', __LINE__, __FILE__)) {
            $request->DoResponse(501, 'Database error');
        }
        if ($qry->rows() > 1) {
            // Unlikely, but if we get more than one result we'll do an exact match instead.
            if (!$qry->QDo('SELECT pprivs(:session_principal::int8,principal_id,:scan_depth::int) AS p, username FROM usr JOIN principal USING(user_no) WHERE usr.email = :email', $params)) {
                $request->DoResponse(501, 'Database error');
            }
            if ($qry->rows() == 0) {
                /** Sigh... Go back to the original case-insensitive match */
                $qry->QDo('SELECT pprivs(:session_principal::int8,principal_id,:scan_depth::int) AS p, username FROM usr JOIN principal USING(user_no) WHERE lower(usr.email) = lower(:email)', $params);
            }
        }
        $response = $reply->NewXMLElement("response", false, false, 'urn:ietf:params:xml:ns:caldav');
        $reply->CalDAVElement($response, "recipient", $reply->href($attendee->Value()));
        if ($qry->rows() == 0) {
            $remote = new iSchedule();
            $answer = $remote->sendRequest($attendee->Value(), 'VFREEBUSY/REQUEST', $ical->Render());
            if ($answer === false) {
                $reply->CalDAVElement($response, "request-status", "3.7;Invalid Calendar User");
                $reply->CalDAVElement($response, "calendar-data");
                $responses[] = $response;
                continue;
            }
            foreach ($answer as $a) {
                if ($a === false) {
                    $reply->CalDAVElement($response, "request-status", "3.7;Invalid Calendar User");
                    $reply->CalDAVElement($response, "calendar-data");
                } elseif (substr($a, 0, 1) >= 1) {
                    $reply->CalDAVElement($response, "request-status", $a);
                    $reply->CalDAVElement($response, "calendar-data");
                } else {
                    $reply->CalDAVElement($response, "request-status", "2.0;Success");
                    $reply->CalDAVElement($response, "calendar-data", $a);
                }
                $responses[] = $response;
            }
            continue;
        }
        if (!($attendee_usr = $qry->Fetch())) {
            $request->DoResponse(501, 'Database error');
        }
        if ((privilege_to_bits('schedule-query-freebusy') & bindec($attendee_usr->p)) == 0) {
            $reply->CalDAVElement($response, "request-status", "3.8;No authority");
            $reply->CalDAVElement($response, "calendar-data");
            $responses[] = $response;
            continue;
        }
        $attendee_path_match = '^/' . $attendee_usr->username . '/';
        $fb = get_freebusy($attendee_path_match, $range_start, $range_end, bindec($attendee_usr->p));
        $fb->AddProperty('UID', $ic->GetPValue('UID'));
        $fb->SetProperties($ic->GetProperties('ORGANIZER'), 'ORGANIZER');
        $fb->AddProperty($attendee);
        $vcal = new vCalendar(array('METHOD' => 'REPLY'));
        $vcal->AddComponent($fb);
        $response = $reply->NewXMLElement("response", false, false, 'urn:ietf:params:xml:ns:caldav');
        $reply->CalDAVElement($response, "recipient", $reply->href($attendee->Value()));
        $reply->CalDAVElement($response, "request-status", "2.0;Success");
        // Cargo-cult setting
        $reply->CalDAVElement($response, "calendar-data", $vcal->Render());
        $responses[] = $response;
    }
    $response = $reply->NewXMLElement("schedule-response", $responses, $reply->GetXmlNsArray(), 'urn:ietf:params:xml:ns:caldav');
    $request->XMLResponse(200, $response);
}