/** * Check the username / password against the PAM system */ function SQUID_PAM_check($username, $password) { global $c; $script = $c->authenticate_hook['config']['script']; if (empty($script)) { $script = $c->authenticate_hook['config']['path']; } $cmd = sprintf('echo %s %s | %s -n common-auth', escapeshellarg($username), escapeshellarg($password), $script); $auth_result = exec($cmd); if ($auth_result == "OK") { dbg_error_log('pwauth', 'User %s successfully authenticated', $username); $principal = new Principal('username', $username); if (!$principal->Exists()) { dbg_error_log('pwauth', 'User %s does not exist in local db, creating', $username); $pwent = posix_getpwnam($username); $gecos = explode(',', $pwent['gecos']); $fullname = $gecos[0]; $principal->Create(array('username' => $username, 'user_active' => 't', 'email' => sprintf('%s@%s', $username, $email_base), 'fullname' => $fullname)); if (!$principal->Exists()) { dbg_error_log("PAM", "Unable to create local principal for '%s'", $username); return false; } CreateHomeCalendar($username); } return $principal; } else { dbg_error_log("PAM", "User %s is not a valid username (or password was wrong)", $username); return false; } }
/** * Check the username / password against the IMAP server */ function RIMAP_check($username, $password) { global $c; $imap_username = $username; if (function_exists('mb_convert_encoding')) { $imap_username = mb_convert_encoding($imap_username, "UTF7-IMAP", mb_detect_encoding($imap_username)); } else { $imap_username = imap_utf7_encode($imap_username); } //$imap_url = '{localhost:143/imap/notls}'; //$imap_url = '{localhost:993/imap/ssl/novalidate-cert}'; $imap_url = $c->authenticate_hook['config']['imap_url']; $auth_result = "ERR"; $imap_stream = @imap_open($imap_url, $imap_username, $password, OP_HALFOPEN); //print_r(imap_errors()); if ($imap_stream) { // disconnect imap_close($imap_stream); // login ok $auth_result = "OK"; } if ($auth_result == "OK") { $principal = new Principal('username', $username); if (!$principal->Exists()) { dbg_error_log("PAM", "Principal '%s' doesn't exist in local DB, we need to create it", $username); if (strstr($username, '@')) { $name_arr = explode('@', $username); $fullname = ucfirst(strtolower($name_arr[0])); $email = $username; } else { $fullname = ucfirst(strtolower($username)); $email = $username . "@" . $c->authenticate_hook['config']['email_base']; } $principal->Create(array('username' => $username, 'user_active' => true, 'email' => $email, 'fullname' => ucfirst($fullname))); if (!$principal->Exists()) { dbg_error_log("PAM", "Unable to create local principal for '%s'", $username); return false; } CreateHomeCollections($username); } return $principal; } else { dbg_error_log("PAM", "User %s is not a valid username (or password was wrong)", $username); return false; } }
/** * Authenticate against a different PostgreSQL database which contains a usr table in * the AWL format. * * Use this as in the following example config snippet: * * require_once('auth-functions.php'); * $c->authenticate_hook = array( * 'call' => 'AuthExternalAwl', * 'config' => array( * // A PgSQL database connection string for the database containing user records * 'connection[]' => 'dbname=wrms host=otherhost port=5433 user=general', * // Which columns should be fetched from the database * 'columns' => "user_no, active, email_ok, joined, last_update AS updated, last_used, username, password, fullname, email", * // a WHERE clause to limit the records returned. * 'where' => "active AND org_code=7" * ) * ); * */ function AuthExternalAWL($username, $password) { global $c; $persistent = isset($c->authenticate_hook['config']['use_persistent']) && $c->authenticate_hook['config']['use_persistent']; if (isset($c->authenticate_hook['config']['columns'])) { $cols = $c->authenticate_hook['config']['columns']; } else { $cols = '*'; } if (isset($c->authenticate_hook['config']['where'])) { $andwhere = ' AND ' . $c->authenticate_hook['config']['where']; } else { $andwhere = ''; } $qry = new AwlQuery('SELECT ' . $cols . ' FROM usr WHERE lower(username) = :username ' . $andwhere, array(':username' => strtolower($username))); $authconn = $qry->SetConnection($c->authenticate_hook['config']['connection'], $persistent ? array(PDO::ATTR_PERSISTENT => true) : null); if (!$authconn) { echo <<<EOERRMSG <html><head><title>Database Connection Failure</title></head><body> <h1>Database Error</h1> <h3>Could not connect to PostgreSQL database</h3> </body> </html> EOERRMSG; @ob_flush(); exit(1); } if ($qry->Exec('Login', __LINE__, __FILE__) && $qry->rows() == 1) { $usr = $qry->Fetch(); if (session_validate_password($password, $usr->password)) { $principal = new Principal('username', $username); if ($principal->Exists()) { if ($principal->modified <= $usr->updated) { $principal->Update($usr); } } else { $principal->Create($usr); CreateHomeCollections($username); } /** * We disallow login by inactive users _after_ we have updated the local copy */ if (isset($usr->active) && $usr->active == 'f') { return false; } return $principal; } } return false; }
/** * 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; }
/** * sync LDAP Groups against the DB */ function sync_LDAP_groups() { global $c; $ldapDriver = getStaticLdap(); if (!$ldapDriver->valid) { return; } $mapping = $c->authenticate_hook['config']['group_mapping_field']; //$attributes = array('cn','modifyTimestamp','memberUid'); $attributes = array_values_mapping($mapping); $ldap_groups_tmp = $ldapDriver->getAllGroups($attributes); if (sizeof($ldap_groups_tmp) == 0) { return; } $member_field = $mapping['members']; foreach ($ldap_groups_tmp as $key => $ldap_group) { $group_mapping = $ldap_group[$mapping['username']]; $ldap_groups_info[$group_mapping] = $ldap_group; if (is_array($ldap_groups_info[$group_mapping][$member_field])) { unset($ldap_groups_info[$group_mapping][$member_field]['count']); } else { $ldap_groups_info[$group_mapping][$member_field] = array($ldap_groups_info[$group_mapping][$member_field]); } unset($ldap_groups_tmp[$key]); } $db_groups = array(); $db_group_members = array(); $qry = new AwlQuery("SELECT g.username AS group_name, member.username AS member_name FROM dav_principal g LEFT JOIN group_member ON (g.principal_id=group_member.group_id) LEFT JOIN dav_principal member ON (member.principal_id=group_member.member_id) WHERE g.type_id = 3"); $qry->Exec('sync_LDAP', __LINE__, __FILE__); while ($db_group = $qry->Fetch()) { $db_groups[$db_group->group_name] = $db_group->group_name; $db_group_members[$db_group->group_name][] = $db_group->member_name; } $ldap_groups = array_keys($ldap_groups_info); // users only in ldap $groups_to_create = array_diff($ldap_groups, $db_groups); // users only in db $groups_to_deactivate = array_diff($db_groups, $ldap_groups); // users present in ldap and in the db $groups_to_update = array_intersect($db_groups, $ldap_groups); if (sizeof($groups_to_create)) { $c->messages[] = sprintf(i18n('- creating groups : %s'), join(', ', $groups_to_create)); $validUserFields = get_fields('usr'); foreach ($groups_to_create as $k => $group) { $user = (object) array(); if (isset($c->authenticate_hook['config']['default_value']) && is_array($c->authenticate_hook['config']['default_value'])) { foreach ($c->authenticate_hook['config']['default_value'] as $field => $value) { if (isset($validUserFields[$field])) { $user->{$field} = $value; dbg_error_log("LDAP", "Setting usr->%s to %s from configured defaults", $field, $value); } } } $user->user_no = 0; $ldap_values = $ldap_groups_info[$group]; foreach ($mapping as $field => $value) { dbg_error_log("LDAP", "Considering copying %s", $field); if (isset($validUserFields[$field])) { $user->{$field} = $ldap_values[$value]; dbg_error_log("LDAP", "Setting usr->%s to %s from LDAP field %s", $field, $ldap_values[$value], $value); } } if ($user->fullname == "") { $user->fullname = $group; } if ($user->displayname == "") { $user->displayname = $group; } $user->username = $group; $user->updated = "now"; /** @todo Use the 'updated' timestamp from LDAP for groups too */ $principal = new Principal('username', $group); if ($principal->Exists()) { $principal->Update($user); } else { $principal->Create($user); } $qry = new AwlQuery("UPDATE dav_principal set type_id = 3 WHERE username=:group ", array(':group' => $group)); $qry->Exec('sync_LDAP', __LINE__, __FILE__); Principal::cacheDelete('username', $group); $c->messages[] = sprintf(i18n('- adding users %s to group : %s'), join(',', $ldap_groups_info[$group][$mapping['members']]), $group); foreach ($ldap_groups_info[$group][$mapping['members']] as $member) { $qry = new AwlQuery("INSERT INTO group_member SELECT g.principal_id AS group_id,u.principal_id AS member_id FROM dav_principal g, dav_principal u WHERE g.username=:group AND u.username=:member;", array(':group' => $group, ':member' => $member)); $qry->Exec('sync_LDAP_groups', __LINE__, __FILE__); Principal::cacheDelete('username', $member); } } } if (sizeof($groups_to_update)) { $c->messages[] = sprintf(i18n('- updating groups : %s'), join(', ', $groups_to_update)); foreach ($groups_to_update as $group) { $db_members = array_values($db_group_members[$group]); $ldap_members = array_values($ldap_groups_info[$group][$member_field]); $add_users = array_diff($ldap_members, $db_members); if (sizeof($add_users)) { $c->messages[] = sprintf(i18n('- adding %s to group : %s'), join(', ', $add_users), $group); foreach ($add_users as $member) { $qry = new AwlQuery("INSERT INTO group_member SELECT g.principal_id AS group_id,u.principal_id AS member_id FROM dav_principal g, dav_principal u WHERE g.username=:group AND u.username=:member", array(':group' => $group, ':member' => $member)); $qry->Exec('sync_LDAP_groups', __LINE__, __FILE__); Principal::cacheDelete('username', $member); } } $remove_users = @array_flip(@array_flip(array_diff($db_members, $ldap_members))); if (sizeof($remove_users)) { $c->messages[] = sprintf(i18n('- removing %s from group : %s'), join(', ', $remove_users), $group); foreach ($remove_users as $member) { $qry = new AwlQuery("DELETE FROM group_member USING dav_principal g,dav_principal m WHERE group_id=g.principal_id AND member_id=m.principal_id AND g.username=:group AND m.username=:member", array(':group' => $group, ':member' => $member)); $qry->Exec('sync_LDAP_groups', __LINE__, __FILE__); Principal::cacheDelete('username', $member); } } } } if (sizeof($groups_to_deactivate)) { $c->messages[] = sprintf(i18n('- deactivate groups : %s'), join(', ', $groups_to_deactivate)); foreach ($groups_to_deactivate as $group) { $qry = new AwlQuery('UPDATE dav_principal SET user_active=FALSE WHERE username=:group AND type_id = 3', array(':group' => $group)); $qry->Exec('sync_LDAP', __LINE__, __FILE__); Principal::cacheFlush('username=:group AND type_id = 3', array(':group' => $group)); } } }
/** * Check the username / password against the PAM system */ function PWAUTH_PAM_check($username, $password) { global $c; $program = $c->authenticate_hook['config']['path']; $email_base = $c->authenticate_hook['config']['email_base']; $pipe = popen(escapeshellarg($program), 'w'); $authinfo = sprintf("%s\n%s\n", $username, $password); $written = fwrite($pipe, $authinfo); dbg_error_log('pwauth', 'Bytes written: %d of %d', $written, strlen($authinfo)); $return_status = pclose($pipe); switch ($return_status) { case 0: // STATUS_OK: Authentication succeeded. dbg_error_log('pwauth', 'User %s successfully authenticated', $username); $principal = new Principal('username', $username); if (!$principal->Exists()) { dbg_error_log('pwauth', 'User %s does not exist in local db, creating', $username); $pwent = posix_getpwnam($username); $gecos = explode(',', $pwent['gecos']); $fullname = $gecos[0]; $principal->Create(array('username' => $username, 'user_active' => 't', 'email' => sprintf('%s@%s', $username, $email_base), 'fullname' => $fullname)); if (!$principal->Exists()) { dbg_error_log("PAM", "Unable to create local principal for '%s'", $username); return false; } CreateHomeCalendar($username); } return $principal; break; /* * Note that for system configurations using PAM instead of * reading the password database directly, if PAM is unable to * read the password database, pwauth will return status 1. */ /* * Note that for system configurations using PAM instead of * reading the password database directly, if PAM is unable to * read the password database, pwauth will return status 1. */ case 1: case 2: // (1) STATUS_UNKNOWN: Invalid username or password. // (2) STATUS_INVALID: Invalid password. dbg_error_log('pwauth', 'Invalid username or password (username: %s)', $username); break; case 3: // STATUS_BLOCKED: UID for username is < pwauth's MIN_UNIX_UID dbg_error_log('pwauth', 'UID for username %s is < pwauth MIN_UNIX_UID', $username); break; case 4: // STATUS_EXPIRED: The user account has expired. dbg_error_log('pwauth', 'The account for %s has expired', $username); break; case 5: // STATUS_PW_EXPIRED: The user account's password has expired. dbg_error_log('pwauth', 'The account password for user %s has expired', $username); break; case 6: // STATUS_NOLOGIN: Logins to the system are administratively disabled. dbg_error_log('pwauth', 'Logins administratively disabled (%s)', $username); break; case 7: // STATUS_MANYFAILS: Too many login failures for user account. dbg_error_log('pwauth', 'Login rejected for %s, too many failures', $username); break; case 50: // STATUS_INT_USER: Configuration error, Web server cannot use pwauth dbg_error_log('pwauth', 'config error: see pwauth man page (%s)', 'STATUS_INT_USER'); break; case 51: // STATUS_INT_ARGS: pwauth received no username/passwd to check dbg_error_log('pwauth', 'error: pwauth received no username/password'); break; case 52: // STATUS_INT_ERR: unknown error dbg_error_log('pwauth', 'error: see pwauth man page (%s)', 'STATUS_INT_ERR'); break; case 53: // STATUS_INT_NOROOT: pwauth could not read the password database dbg_error_log('pwauth', 'config error: cannot read password database (%s)', 'STATUS_INT_NOROOT'); break; default: // Unknown error code. dbg_error_log('pwauth', 'An unknown error (%d) has occurred', $return_status); } return FALSE; }
static function importFromDirectory() { global $c; if (empty($_POST["calendar_path"])) { dbg_error_log("importFromDirectory", "calendar path not given"); return; } $path_ics = $_POST["calendar_path"]; if (substr($path_ics, -1, 1) != '/') { $path_ics .= '/'; } // ensure that we target a collection if (substr($path_ics, 0, 1) != '/') { $path_ics = '/' . $path_ics; } // ensure that we target a collection if (empty($_POST["directory_path"])) { dbg_error_log("importFromDirectory", "directory path not given"); return; } $dir = $_POST["directory_path"]; if (!is_readable($dir)) { $c->messages[] = sprintf(i18n('directory %s is not readable'), htmlspecialchars($dir)); dbg_error_log("importFromDirectory", "directory is not readable"); return; } if ($handle = opendir($dir)) { $c->readonly_webdav_collections = false; // Override this setting so we can create collections/events on import. while (false !== ($file = readdir($handle))) { if ($file == "." || $file == ".." || substr($file, -4) != '.ics') { continue; } if (!is_readable($dir . '/' . $file)) { dbg_error_log("importFromDirectory", "ics file '%s' is not readable", $dir . '/' . $file); continue; } $ics = file_get_contents($dir . '/' . $file); $ics = trim($ics); if ($ics != '') { if (!check_string($ics)) { $c->messages[] = sprintf(translate('The file "%s" is not UTF-8 encoded, please check error for more details'), $dir . '/' . $file); continue; } $username = substr($file, 0, -4); $principal = new Principal('username', $username); if (!$principal->Exists()) { $c->messages[] = sprintf(translate('The principal "%s" does not exist'), $username); continue; } $path = "/" . $username . $path_ics; $user_no = $principal->user_no(); if (controlRequestContainer($username, $user_no, $path, false) === -1) { continue; } dbg_error_log("importFromDirectory", "importing to {$path}"); import_collection($ics, $user_no, $path, 1); $c->messages[] = sprintf(translate('All events of user "%s" were deleted and replaced by those from file %s'), substr($file, 0, -4), $dir . '/' . $file); } } closedir($handle); } }
function ischedule_cancel($ic, $attendees, $attendees_fail) { global $c, $session, $request; $reply = new XMLDocument(array("DAV:" => "", "urn:ietf:params:xml:ns:caldav" => "C", "urn:ietf:params:xml:ns:ischedule" => "I")); $responses = array(); $ical = $ic->GetComponents('VEVENT'); $ical = $ical[0]; foreach ($attendees as $k => $attendee) { $XMLresponse = $reply->NewXMLElement("response", false, false, 'urn:ietf:params:xml:ns:ischedule'); dbg_error_log('ischedule', 'scheduling event for ' . $attendee->email); $schedule_target = new Principal('email', $attendee->email); $response = '3.7'; // Attendee was not found on server. if ($schedule_target->Exists()) { $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.3;cannot schedule this user, unknown or access denied'; // 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;denied'; // No authority to deliver invitations to user. } else { if ($attendee_inbox->WriteCalendarMember($ic, false) !== false) { $response = '2.0;delivered'; // Scheduling invitation delivered successfully } } } } dbg_error_log('PUT', 'Status for attendee <%s> set to "%s"', $attendee->email, $response); $XMLresponse->NewElement("recipient", $reply->href('mailto:' . $attendee->email), false, 'urn:ietf:params:xml:ns:ischedule'); $XMLresponse->NewElement("request-status", $response, false, 'urn:ietf:params:xml:ns:ischedule'); $responses[] = $XMLresponse; } foreach ($attendees_fail as $k => $attendee) { $XMLresponse = $reply->NewXMLElement("response", false, false, 'urn:ietf:params:xml:ns:ischedule'); $XMLresponse->NewElement("recipient", $reply->href('mailto:' . $attendee->email), false, 'urn:ietf:params:xml:ns:ischedule'); $XMLresponse->NewElement("request-status", '5.3;cannot schedule this user, unknown or access denied', false, 'urn:ietf:params:xml:ns:ischedule'); $responses[] = $XMLresponse; } $response = $reply->NewXMLElement("schedule-response", $responses, $reply->GetXmlNsArray(), 'urn:ietf:params:xml:ns:ischedule'); $request->XMLResponse(200, $response); }
/** * Handles sending the iTIP CANCEL messages to each ATTENDEE by the ORGANIZER. * @param vCalendar $vcal What's being cancelled. */ function doItipOrganizerCancel(vCalendar $vcal) { global $request; $attendees = $vcal->GetAttendees(); if (count($attendees) == 0 && count($old_attendees) == 0) { dbg_error_log('schedule', 'Event has no attendees - no scheduling required.', count($attendees)); return true; } dbg_error_log('schedule', 'Writing scheduling resources for %d attendees', count($attendees)); $scheduling_actions = false; $iTIP = GetItip($vcal, 'CANCEL', null); foreach ($attendees as $attendee) { $email = preg_replace('/^mailto:/i', '', $attendee->Value()); if ($email == $request->principal->email()) { dbg_error_log('schedule', "not delivering to owner '%s'", $request->principal->email()); continue; } $agent = $attendee->GetParameterValue('SCHEDULE-AGENT'); if ($agent && $agent != 'SERVER') { dbg_error_log('schedule', "not delivering to %s, schedule agent set to value other than server", $email); continue; } $schedule_target = new Principal('email', $email); if (!$schedule_target->Exists()) { if (doImipMessage('CANCEL', $email, $vcal)) { $response = '1.1'; // Scheduling whoosit 'Sent' } else { $response = '3.7'; } } else { $attendee_inbox = new WritableCollection(array('path' => $schedule_target->internal_url('schedule-inbox'))); if (!$attendee_inbox->HavePrivilegeTo('schedule-deliver-invite')) { dbg_error_log('schedule', "No authority to deliver invite to %s", $schedule_target->internal_url('schedule-inbox')); $response = '3.8'; } else { $attendee_calendar = new WritableCollection(array('path' => $schedule_target->internal_url('schedule-default-calendar'))); $response = processItipCancel($vcal, $attendee, $attendee_calendar, $schedule_target); deliverItipCancel($iTIP, $attendee, $attendee_inbox); } } dbg_error_log('schedule', 'Status for attendee <%s> set to "%s"', $attendee->Value(), $response); $attendee->SetParameterValue('SCHEDULE-STATUS', $response); $scheduling_actions = true; } return true; }