/** * resolve imap or smtp credentials * * @param boolean $_onlyUsername * @param boolean $_throwException * @param boolean $_smtp * @return boolean */ public function resolveCredentials($_onlyUsername = TRUE, $_throwException = FALSE, $_smtp = FALSE) { if ($_smtp) { $passwordField = 'smtp_password'; $userField = 'smtp_user'; $credentialsField = 'smtp_credentials_id'; } else { $passwordField = 'password'; $userField = 'user'; $credentialsField = 'credentials_id'; } if (!$this->{$userField} || !($this->{$passwordField} && !$_onlyUsername)) { $credentialsBackend = Tinebase_Auth_CredentialCache::getInstance(); $userCredentialCache = Tinebase_Core::getUserCredentialCache(); if ($userCredentialCache !== NULL) { try { $credentialsBackend->getCachedCredentials($userCredentialCache); } catch (Exception $e) { return FALSE; } } else { Tinebase_Core::getLogger()->crit(__METHOD__ . '::' . __LINE__ . ' Something went wrong with the CredentialsCache'); return FALSE; } if ($this->type == self::TYPE_USER) { if (!$this->{$credentialsField}) { if ($_throwException) { throw new Felamimail_Exception('Could not get credentials, no ' . $credentialsField . ' given.'); } else { return FALSE; } } try { // NOTE: cache cleanup process might have removed the cache $credentials = $credentialsBackend->get($this->{$credentialsField}); $credentials->key = substr($userCredentialCache->password, 0, 24); $credentialsBackend->getCachedCredentials($credentials); } catch (Exception $e) { if ($_throwException) { throw $e; } else { return FALSE; } } } else { // just use tine user credentials to connect to mailserver / or use credentials from config if set $imapConfig = Tinebase_Config::getInstance()->get(Tinebase_Config::IMAP, new Tinebase_Config_Struct())->toArray(); $credentials = $userCredentialCache; // allow to set credentials in config if ((isset($imapConfig['user']) || array_key_exists('user', $imapConfig)) && (isset($imapConfig['password']) || array_key_exists('password', $imapConfig)) && !empty($imapConfig['user'])) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Using credentials from config for system account.'); } $credentials->username = $imapConfig['user']; $credentials->password = $imapConfig['password']; } // allow to set pw suffix in config if ((isset($imapConfig['pwsuffix']) || array_key_exists('pwsuffix', $imapConfig)) && !preg_match('/' . preg_quote($imapConfig['pwsuffix']) . '$/', $credentials->password)) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Appending configured pwsuffix to system account password.'); } $credentials->password .= $imapConfig['pwsuffix']; } if (!empty($imapConfig['domain']) && strpos($credentials->username, $imapConfig['domain']) === false) { $credentials->username .= '@' . $imapConfig['domain']; } } if (!$this->{$userField}) { $this->{$userField} = $credentials->username; } $this->{$passwordField} = $credentials->password; } return TRUE; }
/** * update user credential cache * * - fires Tinebase_Event_User_ChangeCredentialCache * * @param string $password * @return array */ public function updateCredentialCache($password) { $oldCredentialCache = Tinebase_Core::getUserCredentialCache(); $credentialCache = Tinebase_Auth_CredentialCache::getInstance()->cacheCredentials(Tinebase_Core::getUser()->accountLoginName, $password); Tinebase_Core::set(Tinebase_Core::USERCREDENTIALCACHE, $credentialCache); $success = $this->_setCredentialCacheCookie(); if ($success) { // close session to allow other requests Tinebase_Session::writeClose(true); $event = new Tinebase_Event_User_ChangeCredentialCache($oldCredentialCache); Tinebase_Event::fireEvent($event); } return array('success' => $success); }
/** * set new password & credentials * * @param string $_username * @param string $_password */ protected function _setCredentials($_username, $_password) { Tinebase_User::getInstance()->setPassword(Tinebase_Core::getUser(), $_password, true, false); $oldCredentialCache = Tinebase_Core::getUserCredentialCache(); // update credential cache $credentialCache = Tinebase_Auth_CredentialCache::getInstance()->cacheCredentials($_username, $_password); Tinebase_Core::set(Tinebase_Core::USERCREDENTIALCACHE, $credentialCache); $event = new Tinebase_Event_User_ChangeCredentialCache($oldCredentialCache); Tinebase_Event::fireEvent($event); $this->_pwChanged = true; }
/** * login from HTTP post * * redirects the tine main screen if authentication is successful * otherwise redirects back to login url */ public function loginFromPost($username, $password) { Tinebase_Core::startCoreSession(); if (!empty($username)) { // try to login user $success = Tinebase_Controller::getInstance()->login($username, $password, Tinebase_Core::get(Tinebase_Core::REQUEST), self::REQUEST_TYPE) === TRUE; } else { $success = FALSE; } if ($success === TRUE) { $this->_setJsonKeyCookie(); $ccAdapter = Tinebase_Auth_CredentialCache::getInstance()->getCacheAdapter(); if (Tinebase_Core::isRegistered(Tinebase_Core::USERCREDENTIALCACHE)) { $ccAdapter->setCache(Tinebase_Core::getUserCredentialCache()); } else { Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' Something went wrong with the CredentialCache / no CC registered.'); $success = FALSE; $ccAdapter->resetCache(); } } $request = new Sabre\HTTP\Request(); $redirectUrl = str_replace('index.php', '', $request->getAbsoluteUri()); // authentication failed if ($success !== TRUE) { $_SESSION = array(); Tinebase_Session::destroyAndRemoveCookie(); // redirect back to loginurl if needed $redirectUrl = Tinebase_Config::getInstance()->get(Tinebase_Config::REDIRECTURL, $redirectUrl); } // load the client with GET header('Location: ' . $redirectUrl); }
/** * connects to request tracker * * @return void */ protected function _connect() { if (!$this->_config->rest || $this->_config->rest->url) { throw new Tinebase_Exception_NotFound('Could not connect to RequestTracker: No REST url given!'); } $config = array('url' => $this->_config->rest->url, 'useragent' => 'Tine 2.0 remote client (rv: 0.2)', 'keepalive' => true); $this->_httpClient = new Zend_Http_Client($this->_config->rest->url, $config); $this->_httpClient->setCookieJar(); // login $this->_httpClient->setMethod(Zend_Http_Client::POST); $this->_httpClient->setUri($this->_config->rest->url . "/REST/1.0/ticket/"); $loginName = Tinebase_Core::getUser()->accountLoginName; if ($this->_config->useCustomCredendials) { $this->_httpClient->setAuth($this->_config->customCredentials->{$loginName}->username, $this->_config->customCredentials->{$loginName}->password); } else { $credentialCache = Tinebase_Core::getUserCredentialCache(); Tinebase_Auth_CredentialCache::getInstance()->getCachedCredentials($credentialCache); $this->_httpClient->setAuth(Tinebase_Core::getUser()->accountLoginName, $credentialCache->password); } $response = $this->_httpClient->request(); if ($response->getStatus() != 200) { throw new Tinebase_Exception_Record_NotAllowed($response->getMessage(), $response->getStatus()); } }
/** * create account credentials and return new credentials id * * @param string $_username * @param string $_password * @return string */ protected function _createCredentials($_username = NULL, $_password = NULL, $_userCredentialCache = NULL) { if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { $message = 'Create new account credentials'; if ($_username !== NULL) { $message .= ' for username ' . $_username; } Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . $message); } if (Tinebase_Core::isRegistered(Tinebase_Core::USERCREDENTIALCACHE)) { $userCredentialCache = Tinebase_Core::getUserCredentialCache(); Tinebase_Auth_CredentialCache::getInstance()->getCachedCredentials($userCredentialCache); } else { Tinebase_Core::getLogger()->crit(__METHOD__ . '::' . __LINE__ . ' Something went wrong with the CredentialsCache / use given username/password instead.'); $userCredentialCache = new Tinebase_Model_CredentialCache(array('username' => $_username, 'password' => $_password)); } $accountCredentials = Tinebase_Auth_CredentialCache::getInstance()->cacheCredentials($_username !== NULL ? $_username : $userCredentialCache->username, $_password !== NULL ? $_password : $userCredentialCache->password, $userCredentialCache->password, TRUE); return $accountCredentials->getId(); }
/** * resolve imap or smtp credentials * * @param boolean $_onlyUsername * @param boolean $_throwException * @param boolean $_smtp * @return boolean */ public function resolveCredentials($_onlyUsername = TRUE, $_throwException = FALSE, $_smtp = FALSE) { if ($_smtp) { $passwordField = 'smtp_password'; $userField = 'smtp_user'; $credentialsField = 'smtp_credentials_id'; } else { $passwordField = 'password'; $userField = 'user'; $credentialsField = 'credentials_id'; } if (!$this->{$userField} || !($this->{$passwordField} && !$_onlyUsername)) { $credentialsBackend = Tinebase_Auth_CredentialCache::getInstance(); $userCredentialCache = Tinebase_Core::getUserCredentialCache(); if ($userCredentialCache !== NULL) { try { $credentialsBackend->getCachedCredentials($userCredentialCache); } catch (Exception $e) { return FALSE; } } else { Tinebase_Core::getLogger()->crit(__METHOD__ . '::' . __LINE__ . ' Something went wrong with the CredentialsCache / use given imap username/password instead.'); $userCredentialCache = new Tinebase_Model_CredentialCache(array('username' => $this->user, 'password' => $this->password)); } if ($this->type == self::TYPE_USER) { if (!$this->{$credentialsField}) { if ($_throwException) { throw new Expressomail_Exception('Could not get credentials, no ' . $credentialsField . ' given.'); } else { return FALSE; } } try { // NOTE: cache cleanup process might have removed the cache $credentials = $credentialsBackend->get($this->{$credentialsField}); $credentials->key = substr($userCredentialCache->password, 0, 24); $credentialsBackend->getCachedCredentials($credentials); } catch (Exception $e) { if ($_throwException) { throw $e; } else { return FALSE; } } } else { // just use tine user credentials to connect to mailserver / or use credentials from config if set $imapConfig = Tinebase_Config::getInstance()->get(Tinebase_Config::IMAP, new Tinebase_Config_Struct())->toArray(); $credentials = $userCredentialCache; if (array_key_exists('user', $imapConfig) && array_key_exists('password', $imapConfig) && !empty($imapConfig['user'])) { $credentials->username = $imapConfig['user']; $credentials->password = $imapConfig['password']; } } $this->{$userField} = $credentials->username; $this->{$passwordField} = $credentials->password; } return TRUE; }
/** * get an adapter instance according to the path * * pathParts: * [0] => * [1] => external * [2] => accountLogin * [3] => adapterName * [4..] => path in backend * * @param string $_path * @return Expressodriver_Backend_Adapter_Interface * @throws Expressodriver_Exception */ public function getAdapterBackend($_path) { $pathParts = explode('/', $_path); $adapterName = $pathParts[1]; if (!isset(self::$_backends[$adapterName])) { $adapter = null; $config = Expressodriver_Controller::getInstance()->getConfigSettings(); foreach ($config['adapters'] as $adapterConfig) { if ($adapterName === $adapterConfig['name']) { $adapter = $adapterConfig; } } if (!is_null($adapter)) { $credentialsBackend = Tinebase_Auth_CredentialCache::getInstance(); $userCredentialCache = Tinebase_Core::getUserCredentialCache(); $credentialsBackend->getCachedCredentials($userCredentialCache); $username = $adapter['useEmailAsLoginName'] ? Tinebase_Core::getUser()->accountEmailAddress : Tinebase_Core::getUser()->accountLoginName; $options = array('host' => $adapter['url'], 'user' => $username, 'password' => $userCredentialCache->password, 'root' => '/', 'name' => $adapter['name'], 'useCache' => $config['default']['useCache'], 'cacheLifetime' => $config['default']['cacheLifetime']); self::$_backends[$adapterName] = Expressodriver_Backend_Storage_Abstract::factory($adapter['adapter'], $options); } else { throw new Expressodriver_Exception('Adapter config does not exists'); } } return self::$_backends[$adapterName]; }
/** * parse VEVENT part of VCALENDAR * * @param \Sabre\VObject\Component\VEvent $vevent the VEVENT to parse * @param Calendar_Model_Event $event the Tine 2.0 event to update * @param array $options */ protected function _convertVevent(\Sabre\VObject\Component\VEvent $vevent, Calendar_Model_Event $event, $options) { if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' vevent ' . $vevent->serialize()); } $newAttendees = array(); $attachments = new Tinebase_Record_RecordSet('Tinebase_Model_Tree_Node'); $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm'); $skipFieldsIfOnlyBasicData = array('ATTENDEE', 'UID', 'ORGANIZER', 'VALARM', 'ATTACH', 'CATEGORIES'); foreach ($vevent->children() as $property) { if (isset($this->_options['onlyBasicData']) && $this->_options['onlyBasicData'] && in_array((string) $property->name, $skipFieldsIfOnlyBasicData)) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Skipping ' . $property->name . ' (using option onlyBasicData)'); } continue; } switch ($property->name) { case 'CREATED': case 'DTSTAMP': if (!isset($options[self::OPTION_USE_SERVER_MODLOG]) || $options[self::OPTION_USE_SERVER_MODLOG] !== true) { $event->{$property->name == 'CREATED' ? 'creation_time' : 'last_modified_time'} = $this->_convertToTinebaseDateTime($property); } break; case 'LAST-MODIFIED': $event->last_modified_time = new Tinebase_DateTime($property->getValue()); break; case 'ATTENDEE': $newAttendee = $this->_getAttendee($property); if ($newAttendee) { $newAttendees[] = $newAttendee; } break; case 'CLASS': if (in_array($property->getValue(), array(Calendar_Model_Event::CLASS_PRIVATE, Calendar_Model_Event::CLASS_PUBLIC))) { $event->class = $property->getValue(); } else { $event->class = Calendar_Model_Event::CLASS_PUBLIC; } break; case 'STATUS': if (in_array($property->getValue(), array(Calendar_Model_Event::STATUS_CONFIRMED, Calendar_Model_Event::STATUS_TENTATIVE, Calendar_Model_Event::STATUS_CANCELED))) { $event->status = $property->getValue(); } else { if ($property->getValue() == 'CANCELLED') { $event->status = Calendar_Model_Event::STATUS_CANCELED; } else { $event->status = Calendar_Model_Event::STATUS_CONFIRMED; } } break; case 'DTEND': if (isset($property['VALUE']) && strtoupper($property['VALUE']) == 'DATE') { // all day event $event->is_all_day_event = true; $dtend = $this->_convertToTinebaseDateTime($property, TRUE); // whole day events ends at 23:59:59 in Tine 2.0 but 00:00 the next day in vcalendar $dtend->subSecond(1); } else { $event->is_all_day_event = false; $dtend = $this->_convertToTinebaseDateTime($property); } $event->dtend = $dtend; break; case 'DTSTART': if (isset($property['VALUE']) && strtoupper($property['VALUE']) == 'DATE') { // all day event $event->is_all_day_event = true; $dtstart = $this->_convertToTinebaseDateTime($property, TRUE); } else { $event->is_all_day_event = false; $dtstart = $this->_convertToTinebaseDateTime($property); } $event->originator_tz = $dtstart->getTimezone()->getName(); $event->dtstart = $dtstart; break; case 'SEQUENCE': if (!isset($options[self::OPTION_USE_SERVER_MODLOG]) || $options[self::OPTION_USE_SERVER_MODLOG] !== true) { $event->seq = $property->getValue(); } // iMIP only $event->external_seq = $property->getValue(); break; case 'DESCRIPTION': case 'LOCATION': case 'SUMMARY': $key = strtolower($property->name); $value = $property->getValue(); $event->{$key} = $value; break; case 'ORGANIZER': $email = null; if (!empty($property['EMAIL'])) { $email = $property['EMAIL']; } elseif (preg_match('/mailto:(?P<email>.*)/i', $property->getValue(), $matches)) { $email = $matches['email']; } if ($email !== null) { // it's not possible to change the organizer by spec if (empty($event->organizer)) { $name = isset($property['CN']) ? $property['CN']->getValue() : $email; $contact = Calendar_Model_Attender::resolveEmailToContact(array('email' => $email, 'lastName' => $name)); $event->organizer = $contact->getId(); } // Lightning attaches organizer ATTENDEE properties to ORGANIZER property and does not add an ATTENDEE for the organizer if (isset($property['PARTSTAT'])) { $newAttendees[] = $this->_getAttendee($property); } } break; case 'RECURRENCE-ID': // original start of the event $event->recurid = $this->_convertToTinebaseDateTime($property); // convert recurrence id to utc $event->recurid->setTimezone('UTC'); break; case 'RRULE': $rruleString = $property->getValue(); // convert date format $rruleString = preg_replace_callback('/UNTIL=([\\dTZ]+)(?=;?)/', function ($matches) { $dtUntil = Calendar_Convert_Event_VCalendar_Abstract::getUTCDateFromStringInUsertime($matches[1]); return 'UNTIL=' . $dtUntil->format(Tinebase_Record_Abstract::ISO8601LONG); }, $rruleString); // remove additional days from BYMONTHDAY property (BYMONTHDAY=11,15 => BYMONTHDAY=11) $rruleString = preg_replace('/(BYMONTHDAY=)([\\d]+),([,\\d]+)/', '$1$2', $rruleString); $event->rrule = $rruleString; // process exceptions if (isset($vevent->EXDATE)) { $exdates = new Tinebase_Record_RecordSet('Calendar_Model_Event'); foreach ($vevent->EXDATE as $exdate) { foreach ($exdate->getDateTimes() as $exception) { if (isset($exdate['VALUE']) && strtoupper($exdate['VALUE']) == 'DATE') { $recurid = new Tinebase_DateTime($exception->format(Tinebase_Record_Abstract::ISO8601LONG), (string) Tinebase_Core::getUserTimezone()); } else { $recurid = new Tinebase_DateTime($exception->format(Tinebase_Record_Abstract::ISO8601LONG), $exception->getTimezone()); } $recurid->setTimezone(new DateTimeZone('UTC')); $eventException = new Calendar_Model_Event(array('recurid' => $recurid, 'is_deleted' => true)); $exdates->addRecord($eventException); } } $event->exdate = $exdates; } break; case 'TRANSP': if (in_array($property->getValue(), array(Calendar_Model_Event::TRANSP_OPAQUE, Calendar_Model_Event::TRANSP_TRANSP))) { $event->transp = $property->getValue(); } else { $event->transp = Calendar_Model_Event::TRANSP_TRANSP; } break; case 'UID': // it's not possible to change the uid by spec if (!empty($event->uid)) { continue; } $event->uid = $property->getValue(); break; case 'VALARM': $this->_parseAlarm($event, $property, $vevent); break; case 'CATEGORIES': $tags = Tinebase_Model_Tag::resolveTagNameToTag($property->getParts(), 'Calendar'); if (!isset($event->tags)) { $event->tags = $tags; } else { $event->tags->merge($tags); } break; case 'ATTACH': $name = (string) $property['FILENAME']; $managedId = (string) $property['MANAGED-ID']; $value = (string) $property['VALUE']; $attachment = NULL; $readFromURL = false; $url = ''; if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) { Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' attachment found: ' . $name . ' ' . $managedId); } if ($managedId) { $attachment = $event->attachments instanceof Tinebase_Record_RecordSet ? $event->attachments->filter('hash', $property['MANAGED-ID'])->getFirstRecord() : NULL; // NOTE: we might miss a attachment here for the following reasons // 1. client reuses a managed id (we are server): // We havn't observerd this yet. iCal client reuse manged id's // from base events in exceptions but this is covered as we // initialize new exceptions with base event attachments // // When a client reuses a managed id it's not clear yet if // this managed id needs to be in the same series/calendar/server // // As we use the object hash the managed id might be used in the // same files with different names. We need to evaluate the name // (if attached) in this case as well. // // 2. server send his managed id (we are client) // * we need to download the attachment (here?) // * we need to have a mapping externalid / internalid (where?) if (!$attachment) { $readFromURL = true; $url = $property->getValue(); } else { $attachments->addRecord($attachment); } } elseif ('URI' === $value) { /* * ATTACH;VALUE=URI:https://server.com/calendars/__uids__/0AA0 3A3B-F7B6-459A-AB3E-4726E53637D0/dropbox/4971F93F-8657-412B-841A-A0FD913 9CD61.dropbox/Canada.png */ $url = $property->getValue(); $urlParts = parse_url($url); $host = $urlParts['host']; $name = pathinfo($urlParts['path'], PATHINFO_BASENAME); // iCal 10.7 places URI before uploading if (parse_url(Tinebase_Core::getHostname(), PHP_URL_HOST) != $host) { $readFromURL = true; } } else { // @TODO: implement (check if add / update / update is needed) if (Tinebase_Core::isLogLevel(Zend_Log::WARN)) { Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' attachment found that could not be imported due to missing managed id'); } } if ($readFromURL) { if (preg_match('#^(https?://)(.*)$#', str_replace(array("\n", "\r"), '', $url), $matches)) { // we are client and found an external hosted attachment that we need to import $userCredentialCache = Tinebase_Core::getUserCredentialCache(); $url = $matches[1] . $userCredentialCache->username . ':' . $userCredentialCache->password . '@' . $matches[2]; $attachmentInfo = $matches[1] . $matches[2] . ' ' . $name . ' ' . $managedId; if (Tinebase_Helper::urlExists($url)) { if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) { Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Downloading attachment: ' . $attachmentInfo); } $stream = fopen($url, 'r'); $attachment = new Tinebase_Model_Tree_Node(array('name' => rawurldecode($name), 'type' => Tinebase_Model_Tree_Node::TYPE_FILE, 'contenttype' => (string) $property['FMTTYPE'], 'tempFile' => $stream), true); $attachments->addRecord($attachment); } else { if (Tinebase_Core::isLogLevel(Zend_Log::WARN)) { Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' Url not found (got 404): ' . $attachmentInfo . ' - Skipping attachment'); } } } else { if (Tinebase_Core::isLogLevel(Zend_Log::WARN)) { Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' Attachment found with malformed url: ' . $url); } } } break; case 'X-MOZ-LASTACK': $lastAck = $this->_convertToTinebaseDateTime($property); break; case 'X-MOZ-SNOOZE-TIME': $snoozeTime = $this->_convertToTinebaseDateTime($property); break; default: // thunderbird saves snooze time for recurring event occurrences in properties with names like this - // we just assume that the event/recur series has only one snooze time if (preg_match('/^X-MOZ-SNOOZE-TIME-[0-9]+$/', $property->name)) { $snoozeTime = $this->_convertToTinebaseDateTime($property); if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Found snooze time for recur occurrence: ' . $snoozeTime->toString()); } } break; } } // NOTE: X-CALENDARSERVER-ACCESS overwrites CLASS if (isset($vevent->{'X-CALENDARSERVER-ACCESS'})) { $event->class = $vevent->{'X-CALENDARSERVER-ACCESS'} == 'PUBLIC' ? Calendar_Model_Event::CLASS_PUBLIC : Calendar_Model_Event::CLASS_PRIVATE; } if (isset($lastAck)) { Calendar_Controller_Alarm::setAcknowledgeTime($event->alarms, $lastAck); } if (isset($snoozeTime)) { Calendar_Controller_Alarm::setSnoozeTime($event->alarms, $snoozeTime); } // merge old and new attendee Calendar_Model_Attender::emailsToAttendee($event, $newAttendees); if (empty($event->seq)) { $event->seq = 1; } if (empty($event->class)) { $event->class = Calendar_Model_Event::CLASS_PUBLIC; } $this->_manageAttachmentsFromClient($event, $attachments); if (empty($event->dtend)) { if (empty($event->dtstart)) { throw new Tinebase_Exception_UnexpectedValue("Got event without dtstart and dtend"); } // TODO find out duration (see TRIGGER DURATION) // if (isset($vevent->DURATION)) { // } if (Tinebase_Core::isLogLevel(Zend_Log::NOTICE)) { Tinebase_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . ' Got event without dtend. Assuming 30 minutes duration'); } $event->dtend = clone $event->dtstart; $event->dtend->addMinute(30); } $this->_manageAttachmentsFromClient($event, $attachments); // convert all datetime fields to UTC $event->setTimezone('UTC'); }