public function handle($onSuccess, $onFailure, Request $request, User $user, Calendar $calendar = null) { $new = false; if (is_null($calendar)) { $calendar = new Calendar(); $calendar->setPrincipaluri($user->getIdentityPrincipal()->getUri()); $calendar->setUri(UUIDUtil::getUUID()); $new = true; } $form = $this->formfactory->create(new CalendarType(), $calendar); $form->handleRequest($request); if ($form->isValid()) { $this->em->persist($calendar); $this->em->flush(); return $onSuccess($form, $calendar, $new); } return $onFailure($form, $calendar, $new); }
public function handle($onSuccess, $onFailure, Request $request, User $user, Addressbook $addressbook = null) { $new = false; if (is_null($addressbook)) { $addressbook = new Addressbook(); $addressbook->setPrincipaluri($user->getIdentityPrincipal()->getUri()); $addressbook->setUri(UUIDUtil::getUUID()); $addressbook->setSynctoken('1'); $new = true; } $form = $this->formfactory->create(new AddressbookType(), $addressbook); $form->handleRequest($request); if ($form->isValid()) { $this->em->persist($addressbook); $this->em->flush(); return $onSuccess($form, $addressbook, $new); } return $onFailure($form, $addressbook, $new); }
/** * @return string */ public function GenerateStrId() { return \Sabre\DAV\UUIDUtil::getUUID().'.vcf'; }
/** * Returns a list of calendars for a principal. * * Every project is an array with the following keys: * * id, a unique id that will be used by other functions to modify the * calendar. This can be the same as the uri or a database key. * * uri, which the basename of the uri with which the calendar is * accessed. * * principaluri. The owner of the calendar. Almost always the same as * principalUri passed to this method. * * Furthermore it can contain webdav properties in clark notation. A very * common one is '{DAV:}displayname'. * * MODIFIED: THIS METHOD NOW NEEDS TO BE ABLE TO RETRIEVE SHARED CALENDARS * * @param string $principalUri * @return array */ public function getCalendarsForUser($principalUri) { $aCalendars = $this->getOwnCalendarsForUser($principalUri); if (count($aCalendars) === 0) { $this->createCalendar($principalUri, \Sabre\DAV\UUIDUtil::getUUID(), ['{DAV:}displayname' => \CApi::ClientI18N('CALENDAR/CALENDAR_DEFAULT_NAME', basename($principalUri)), '{' . \Sabre\CalDAV\Plugin::NS_CALENDARSERVER . '}getctag' => 1, '{' . \Sabre\CalDAV\Plugin::NS_CALDAV . '}calendar-description' => '', '{http://apple.com/ns/ical/}calendar-color' => \Afterlogic\DAV\Constants::CALENDAR_DEFAULT_COLOR, '{http://apple.com/ns/ical/}calendar-order' => 0]); $aCalendars = $this->getOwnCalendarsForUser($principalUri); } /* $aSharedCalendars = $this->getSharedCalendarsForUser($principalUri); $aSharedToAllCalendars = $this->getSharedCalendarsForUser( \Afterlogic\DAV\Utils::getTenantPrincipalUri($principalUri) ); foreach ($aSharedToAllCalendars as $iKey => $aSharedToAllCalendar) { if (isset($aCalendars[$iKey])) { $aSharedToAllCalendar['{http://sabredav.org/ns}read-only'] = false; } $aCalendars[$iKey] = $aSharedToAllCalendar; } foreach ($aSharedCalendars as $iKey => $aSharedCalendar) { if (isset($aCalendars[$iKey])) { $aSharedCalendar['{http://sabredav.org/ns}read-only'] = false; } $aCalendars[$iKey] = $aSharedCalendar; } */ $aSharedCalendars = array(); return array_merge($aCalendars, $aSharedCalendars); }
/** * @param \CAccount $oAccount * @return string */ public function generateXMLProfile($oAccount) { $mResult = false; if ($oAccount) { $oDomImplementation = new DOMImplementation(); $oDocumentType = $oDomImplementation->createDocumentType('plist', '-//Apple//DTD PLIST 1.0//EN', 'http://www.apple.com/DTDs/PropertyList-1.0.dtd'); $oXmlDocument = $oDomImplementation->createDocument('', '', $oDocumentType); $oXmlDocument->xmlVersion = '1.0'; $oXmlDocument->encoding = 'UTF-8'; $oXmlDocument->formatOutput = true; $oPlist = $oXmlDocument->createElement('plist'); $oPlist->setAttribute('version', '1.0'); $sPayloadId = $this->oApiDavManager ? 'afterlogic.' . $this->oApiDavManager->getServerHost($oAccount) : ''; $aPayload = array('PayloadVersion' => 1, 'PayloadUUID' => \Sabre\DAV\UUIDUtil::getUUID(), 'PayloadType' => 'Configuration', 'PayloadRemovalDisallowed' => false, 'PayloadIdentifier' => $sPayloadId, 'PayloadOrganization' => $oAccount->Domain->SiteName, 'PayloadDescription' => $oAccount->Domain->SiteName . ' Mobile', 'PayloadDisplayName' => $oAccount->Domain->SiteName . ' Mobile Profile'); $oArrayElement = $oXmlDocument->createElement('array'); $bIsDemo = false; \CApi::Plugin()->RunHook('plugin-is-demo-account', array(&$oAccount, &$bIsDemo)); if (!$bIsDemo) { $aInfo = $this->oApiUsersManager->getUserAccounts($oAccount->IdUser); if (is_array($aInfo) && 0 < count($aInfo)) { foreach (array_keys($aInfo) as $iIdAccount) { if ($oAccount->IdAccount === $iIdAccount) { $oAccountItem = $oAccount; } else { $oAccountItem = $this->oApiUsersManager->getAccountById($iIdAccount); } $oEmailDictElement = $this->_generateEmailDict($oXmlDocument, $sPayloadId, $oAccountItem, $bIsDemo); if ($oEmailDictElement === false) { return false; } else { $oArrayElement->appendChild($oEmailDictElement); } unset($oAccountItem); unset($oEmailDictElement); } } else { return false; } } // Calendars $oCaldavDictElement = $this->_generateCaldavDict($oXmlDocument, $sPayloadId, $oAccount, $bIsDemo); $oArrayElement->appendChild($oCaldavDictElement); // Contacts $oCarddavDictElement = $this->_generateCarddavDict($oXmlDocument, $sPayloadId, $oAccount, $bIsDemo); $oArrayElement->appendChild($oCarddavDictElement); $oDictElement = $this->_generateDict($oXmlDocument, $aPayload); $oPayloadContentElement = $oXmlDocument->createElement('key', 'PayloadContent'); $oDictElement->appendChild($oPayloadContentElement); $oDictElement->appendChild($oArrayElement); $oPlist->appendChild($oDictElement); $oXmlDocument->appendChild($oPlist); $mResult = $oXmlDocument->saveXML(); } return $mResult; }
/** * @param CContact $oContact * @return bool */ public function createContact($oContact) { $bResult = false; if (isset($oContact)) { $this->init($oContact->IdUser); $sUUID = \Sabre\DAV\UUIDUtil::getUUID(); if (empty($oContact->IdContact)) { $oContact->IdContact = $sUUID; } $vCard = new \Sabre\VObject\Component('VCARD'); CApiContactsVCardHelper::UpdateVCardFromContact($oContact, $vCard); $sUrl = $this->AddressBookHomeSet . \afterlogic\DAV\Constants::ADDRESSBOOK_DEFAULT_NAME . '/' . $oContact->IdContact . '.vcf'; $this->Dav->CreateItem($sUrl, $vCard->serialize()); $bResult = true; /* $oContact->initBeforeChange(); $sEmail = $oContact->ViewEmail; $oAddressBook = $this->getAddressBook($oContact->IdUser, 'Collected'); $aContactsIds = $this->searchContactItemsByEmail($oContact->IdUser, $sEmail, $oAddressBook); $this->deleteContactsByAddressBook($oContact->IdUser, $aContactsIds, $oAddressBook); */ } return $bResult; }
/** * Checks if the submitted iCalendar data is in fact, valid. * * An exception is thrown if it's not. * * @param resource|string $data * @return void */ protected function validateVCard(&$data) { // If it's a stream, we convert it to a string first. if (is_resource($data)) { $data = stream_get_contents($data); } // Converting the data to unicode, if needed. $data = DAV\StringUtil::ensureUTF8($data); try { $vobj = VObject\Reader::read($data); } catch (VObject\ParseException $e) { throw new DAV\Exception\UnsupportedMediaType('This resource only supports valid vcard data. Parse error: ' . $e->getMessage()); } if ($vobj->name !== 'VCARD') { throw new DAV\Exception\UnsupportedMediaType('This collection can only support vcard objects.'); } if (!isset($vobj->UID)) { // No UID in vcards is invalid, but we'll just add it in anyway. $vobj->add('UID', DAV\UUIDUtil::getUUID()); $data = $vobj->serialize(); } }
/** * Parses a webdav lock xml body, and returns a new Sabre\DAV\Locks\LockInfo object * * @param string $body * @return LockInfo */ protected function parseLockRequest($body) { $result = $this->server->xml->expect('{DAV:}lockinfo', $body); $lockInfo = new LockInfo(); $lockInfo->owner = $result->owner; $lockInfo->token = DAV\UUIDUtil::getUUID(); $lockInfo->scope = $result->scope; return $lockInfo; }
/** * Updates the list of shares. * * @param mixed $calendarId * @param \Sabre\DAV\Xml\Element\Sharee[] $sharees * @return void */ function updateInvites($calendarId, array $sharees) { if (!is_array($calendarId)) { throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId'); } $currentInvites = $this->getInvites($calendarId); list($calendarId, $instanceId) = $calendarId; $removeStmt = $this->pdo->prepare("DELETE FROM " . $this->calendarInstancesTableName . " WHERE calendarid = ? AND share_href = ? AND access IN (2,3)"); $updateStmt = $this->pdo->prepare("UPDATE " . $this->calendarInstancesTableName . " SET access = ?, share_displayname = ?, share_invitestatus = ? WHERE calendarid = ? AND share_href = ?"); $insertStmt = $this->pdo->prepare(' INSERT INTO ' . $this->calendarInstancesTableName . ' ( calendarid, principaluri, access, displayname, uri, description, calendarorder, calendarcolor, timezone, transparent, share_href, share_displayname, share_invitestatus ) SELECT ?, ?, ?, displayname, ?, description, calendarorder, calendarcolor, timezone, 1, ?, ?, ? FROM ' . $this->calendarInstancesTableName . ' WHERE id = ?'); foreach ($sharees as $sharee) { if ($sharee->access === \Sabre\DAV\Sharing\Plugin::ACCESS_NOACCESS) { // if access was set no NOACCESS, it means access for an // existing sharee was removed. $removeStmt->execute([$calendarId, $sharee->href]); continue; } if (is_null($sharee->principal)) { // If the server could not determine the principal automatically, // we will mark the invite status as invalid. $sharee->inviteStatus = \Sabre\DAV\Sharing\Plugin::INVITE_INVALID; } else { // Because sabre/dav does not yet have an invitation system, // every invite is automatically accepted for now. $sharee->inviteStatus = \Sabre\DAV\Sharing\Plugin::INVITE_ACCEPTED; } foreach ($currentInvites as $oldSharee) { if ($oldSharee->href === $sharee->href) { // This is an update $sharee->properties = array_merge($oldSharee->properties, $sharee->properties); $updateStmt->execute([$sharee->access, isset($sharee->properties['{DAV:}displayname']) ? $sharee->properties['{DAV:}displayname'] : null, $sharee->inviteStatus ?: $oldSharee->inviteStatus, $calendarId, $sharee->href]); continue 2; } } // If we got here, it means it was a new sharee $insertStmt->execute([$calendarId, $sharee->principal, $sharee->access, \Sabre\DAV\UUIDUtil::getUUID(), $sharee->href, isset($sharee->properties['{DAV:}displayname']) ? $sharee->properties['{DAV:}displayname'] : null, $sharee->inviteStatus ?: \Sabre\DAV\Sharing\Plugin::INVITE_NORESPONSE, $instanceId]); } }
public static function CheckPrincipals($sUserName) { if (trim($sUserName) !== '') { $oPdo = \CApi::GetPDO(); $dbPrefix = \CApi::GetSettingsConf('Common/DBPrefix'); $oAccount = self::GetAccountByLogin($sUserName); if ($oAccount) { $sPrincipal = \afterlogic\DAV\Constants::PRINCIPALS_PREFIX . '/' . $sUserName; $oStmt = $oPdo->prepare('SELECT id FROM ' . $dbPrefix . Constants::T_PRINCIPALS . ' WHERE uri = ? LIMIT 1'); $oStmt->execute(array($sPrincipal)); if (count($oStmt->fetchAll()) === 0) { $oStmt = $oPdo->prepare('INSERT INTO ' . $dbPrefix . Constants::T_PRINCIPALS . ' (uri,email,displayname) VALUES (?, ?, ?)'); try { $oStmt->execute(array($sPrincipal, $sUserName, '')); } catch (Exception $e) { } } $oStmt = $oPdo->prepare('SELECT principaluri FROM ' . $dbPrefix . Constants::T_CALENDARS . ' WHERE principaluri = ?'); $oStmt->execute(array($sPrincipal)); if (count($oStmt->fetchAll()) === 0) { $oStmt = $oPdo->prepare('INSERT INTO ' . $dbPrefix . Constants::T_CALENDARS . ' (principaluri, displayname, uri, description, components, ctag, calendarcolor) VALUES (?, ?, ?, ?, ?, 1, ?)'); $oStmt->execute(array($sPrincipal, \CApi::ClientI18N('CALENDAR/CALENDAR_DEFAULT_NAME', $oAccount), \Sabre\DAV\UUIDUtil::getUUID(), '', 'VEVENT,VTODO', Constants::CALENDAR_DEFAULT_COLOR)); } $oStmt = $oPdo->prepare('SELECT principaluri FROM ' . $dbPrefix . Constants::T_CALENDARS . ' WHERE principaluri = ? and uri = ? LIMIT 1'); $oStmt->execute(array($sPrincipal, Constants::CALENDAR_DEFAULT_NAME)); if (count($oStmt->fetchAll()) !== 0) { $oStmt = $oPdo->prepare('UPDATE ' . $dbPrefix . Constants::T_CALENDARS . ' SET uri = ? WHERE principaluri = ? and uri = ?'); $oStmt->execute(array(\Sabre\DAV\UUIDUtil::getUUID(), $sPrincipal, Constants::CALENDAR_DEFAULT_NAME)); } $oStmt = $oPdo->prepare('SELECT principaluri FROM ' . $dbPrefix . Constants::T_ADDRESSBOOKS . ' WHERE principaluri = ? and uri = ? LIMIT 1'); $oStmt->execute(array($sPrincipal, Constants::ADDRESSBOOK_DEFAULT_NAME)); $bHasDefaultAddressbooks = count($oStmt->fetchAll()) != 0; $oStmt->execute(array($sPrincipal, Constants::ADDRESSBOOK_DEFAULT_NAME_OLD)); $bHasOldDefaultAddressbooks = count($oStmt->fetchAll()) != 0; $oStmt->execute(array($sPrincipal, Constants::ADDRESSBOOK_COLLECTED_NAME)); $bHasCollectedAddressbooks = count($oStmt->fetchAll()) != 0; $stmt1 = $oPdo->prepare('INSERT INTO ' . $dbPrefix . Constants::T_ADDRESSBOOKS . ' (principaluri, displayname, uri, description, ctag) VALUES (?, ?, ?, ?, 1)'); if (!$bHasDefaultAddressbooks) { if ($bHasOldDefaultAddressbooks) { $oStmt = $oPdo->prepare('UPDATE ' . $dbPrefix . Constants::T_ADDRESSBOOKS . ' SET uri = ? WHERE principaluri = ? and uri = ?'); $oStmt->execute(array(Constants::ADDRESSBOOK_DEFAULT_NAME, $sPrincipal, Constants::ADDRESSBOOK_DEFAULT_NAME_OLD)); } else { $stmt1->execute(array($sPrincipal, Constants::ADDRESSBOOK_DEFAULT_DISPLAY_NAME, Constants::ADDRESSBOOK_DEFAULT_NAME, Constants::ADDRESSBOOK_DEFAULT_DISPLAY_NAME)); } } if (!$bHasCollectedAddressbooks) { $stmt1->execute(array($sPrincipal, Constants::ADDRESSBOOK_COLLECTED_DISPLAY_NAME, Constants::ADDRESSBOOK_COLLECTED_NAME, Constants::ADDRESSBOOK_COLLECTED_DISPLAY_NAME)); } } } }
/** * @param int $iUserId * @param string $sEmail * @return bool */ public function UpdateSuggestTable($iUserId, $aEmails) { $bResult = false; $this->Init($iUserId); $oDefautltAB = $this->getAddressBook($iUserId, \afterlogic\DAV\Constants::ADDRESSBOOK_DEFAULT_NAME); $oCollectedAB = $this->getAddressBook($iUserId, \afterlogic\DAV\Constants::ADDRESSBOOK_COLLECTED_NAME); $aCollectedContactItems = $this->getObjectItems($iUserId, $oCollectedAB); foreach ($aEmails as $sEmail => $sName) { $mFindContact = false; if ($aCollectedContactItems) { foreach ($aCollectedContactItems as $oCollectedContactItem) { $oVCard = \Sabre\VObject\Reader::read($oCollectedContactItem->get()); if (isset($oVCard->EMAIL)) { foreach ($oVCard->EMAIL as $oEmail) { if (strtolower((string) $oEmail) == strtolower($sEmail)) { $mFindContact = $oCollectedContactItem; break; } } } unset($oVCard); } } $aDefaultContactIds = $this->searchContactItemsByEmail($iUserId, $sEmail, $oDefautltAB); if (count($aDefaultContactIds) === 0) { if ($mFindContact === false) { $sUUID = \Sabre\DAV\UUIDUtil::getUUID(); $oContact = new CContact(); $oContact->FullName = $sName; $oContact->HomeEmail = $sEmail; $oContact->IdContactStr = $sUUID; $oVCard = new \Sabre\VObject\Component\VCard(); $oVCard->{'X-AFTERLOGIC-USE-FREQUENCY'} = '1'; CApiContactsVCardHelper::UpdateVCardFromContact($oContact, $oVCard); $oCollectedAB->createFile($sUUID . '.vcf', $oVCard->serialize()); $bResult = true; } else { if ($mFindContact instanceof \Sabre\CardDAV\Card) { $oVCard = \Sabre\VObject\Reader::read($mFindContact->get()); if (isset($oVCard->{'X-AFTERLOGIC-USE-FREQUENCY'})) { $oVCard->{'X-AFTERLOGIC-USE-FREQUENCY'} = (int) $oVCard->{'X-AFTERLOGIC-USE-FREQUENCY'}->getValue() + 1; } else { $oVCard->{'X-AFTERLOGIC-USE-FREQUENCY'} = '1'; } $mFindContact->put($oVCard->serialize()); unset($oVCard); } } } else { foreach ($aDefaultContactIds as $sDefaultContactId) { $mDefaultContact = $this->geItem($iUserId, $oDefautltAB, $sDefaultContactId); if ($mDefaultContact !== false) { $oVCard = \Sabre\VObject\Reader::read($mDefaultContact->get()); if (isset($oVCard->{'X-AFTERLOGIC-USE-FREQUENCY'})) { $oVCard->{'X-AFTERLOGIC-USE-FREQUENCY'} = (int) $oVCard->{'X-AFTERLOGIC-USE-FREQUENCY'}->getValue() + 1; } else { $oVCard->{'X-AFTERLOGIC-USE-FREQUENCY'} = '1'; } $mDefaultContact->put($oVCard->serialize()); unset($oVCard); } } if ($mFindContact instanceof \Sabre\CardDAV\Card) { $mFindContact->delete(); } } } return $bResult; }
/** * Parses a webdav lock xml body, and returns a new Sabre\DAV\Locks\LockInfo object * * @param string $body * @return DAV\Locks\LockInfo */ protected function parseLockRequest($body) { // Fixes an XXE vulnerability on PHP versions older than 5.3.23 or // 5.4.13. $previous = libxml_disable_entity_loader(true); $xml = simplexml_load_string(DAV\XMLUtil::convertDAVNamespace($body), null, LIBXML_NOWARNING); libxml_disable_entity_loader($previous); $xml->registerXPathNamespace('d', 'urn:DAV'); $lockInfo = new LockInfo(); $children = $xml->children("urn:DAV"); $lockInfo->owner = (string) $children->owner; $lockInfo->token = DAV\UUIDUtil::getUUID(); $lockInfo->scope = count($xml->xpath('d:lockscope/d:exclusive')) > 0 ? LockInfo::EXCLUSIVE : LockInfo::SHARED; return $lockInfo; }
public function PopulateByVCard($sVCard, $sEtag = '') { $this->Properties = array(); if (!empty($sEtag)) { $this->Etag = $sEtag; } try { $oVCard = \Sabre\VObject\Reader::read($sVCard); } catch (\Exception $oExc) { } $aProperties = array(); if ($oVCard) { $bOldVersion = empty($oVCard->VERSION) ? false : \in_array((string) $oVCard->VERSION, array('2.1', '2.0', '1.0')); $this->IdContactStr = $oVCard->UID ? (string) $oVCard->UID : \Sabre\DAV\UUIDUtil::getUUID(); if (isset($oVCard->FN) && '' !== \trim($oVCard->FN)) { $sValue = $this->getPropertyValueHelper($oVCard->FN, $bOldVersion); $aProperties[] = new Property(PropertyType::FULLNAME, $sValue); } if (isset($oVCard->NICKNAME) && '' !== \trim($oVCard->NICKNAME)) { $sValue = $sValue = $this->getPropertyValueHelper($oVCard->NICKNAME, $bOldVersion); $aProperties[] = new Property(PropertyType::NICK_NAME, $sValue); } if (isset($oVCard->NOTE) && '' !== \trim($oVCard->NOTE)) { $sValue = $this->getPropertyValueHelper($oVCard->NOTE, $bOldVersion); $aProperties[] = new Property(PropertyType::NOTE, $sValue); } if (isset($oVCard->N)) { $aNames = $oVCard->N->getParts(); foreach ($aNames as $iIndex => $sValue) { $sValue = \trim($sValue); if ($bOldVersion && !isset($oVCard->N->parameters['CHARSET'])) { if (0 < \strlen($sValue)) { $sEncValue = @\utf8_encode($sValue); if (0 === \strlen($sEncValue)) { $sEncValue = $sValue; } $sValue = $sEncValue; } } $sValue = \MailSo\Base\Utils::Utf8Clear($sValue); switch ($iIndex) { case 0: $aProperties[] = new Property(PropertyType::LAST_NAME, $sValue); break; case 1: $aProperties[] = new Property(PropertyType::FIRST_NAME, $sValue); break; case 2: $aProperties[] = new Property(PropertyType::MIDDLE_NAME, $sValue); break; case 3: $aProperties[] = new Property(PropertyType::NAME_PREFIX, $sValue); break; case 4: $aProperties[] = new Property(PropertyType::NAME_SUFFIX, $sValue); break; } } } if (isset($oVCard->EMAIL)) { $this->addArrayPropertyHelper($aProperties, $oVCard->EMAIL, PropertyType::EMAIl); } if (isset($oVCard->URL)) { $this->addArrayPropertyHelper($aProperties, $oVCard->URL, PropertyType::WEB_PAGE); } if (isset($oVCard->TEL)) { $this->addArrayPropertyHelper($aProperties, $oVCard->TEL, PropertyType::PHONE); } $this->Properties = $aProperties; if (isset($oVCard->CATEGORIES)) { $this->Tags = (array) $oVCard->CATEGORIES->getParts(); $this->Tags = \is_array($this->Tags) ? $this->Tags : array(); $this->Tags = \array_map('trim', $this->Tags); } } $this->UpdateDependentValues(); }
/** * Creates a new calendar for a principal. * * If the creation was a success, an id must be returned that can be used to reference * this calendar in other methods, such as updateCalendar. * * This function must return a server-wide unique id that can be used * later to reference the calendar. * * @param string $principalUri * @param string $calendarUri * @param array $properties * @return string|int */ function createCalendar($principalUri, $calendarUri, array $properties) { $id = DAV\UUIDUtil::getUUID(); $this->calendars[] = array_merge(['id' => $id, 'principaluri' => $principalUri, 'uri' => $calendarUri, '{' . CalDAV\Plugin::NS_CALDAV . '}supported-calendar-component-set' => new CalDAV\Xml\Property\SupportedCalendarComponentSet(['VEVENT', 'VTODO'])], $properties); return $id; }
/** * @param string $sEmail * @param string $sVcfData * * @return int */ public function ImportVcfFile($sEmail, $sVcfData) { $iCount = 0; if ($this->IsActive() && \is_string($sVcfData)) { $sVcfData = \trim($sVcfData); if ("" === \substr($sVcfData, 0, 3)) { $sVcfData = \substr($sVcfData, 3); } $oVCardSplitter = null; try { $oVCardSplitter = new \Sabre\VObject\Splitter\VCard($sVcfData); } catch (\Exception $oExc) { $this->Logger()->WriteException($oExc); } if ($oVCardSplitter) { $oContact = new \RainLoop\Providers\AddressBook\Classes\Contact(); $oVCard = null; while ($oVCard = $oVCardSplitter->getNext()) { if ($oVCard instanceof \Sabre\VObject\Component\VCard) { \MailSo\Base\Utils::ResetTimeLimit(); if (empty($oVCard->UID)) { $oVCard->UID = \Sabre\DAV\UUIDUtil::getUUID(); } $oContact->PopulateByVCard($oVCard->serialize()); if (0 < \count($oContact->Properties)) { if ($this->ContactSave($sEmail, $oContact)) { $iCount++; } } $oContact->Clear(); } } } } return $iCount; }
/** * Checks if the submitted iCalendar data is in fact, valid. * * An exception is thrown if it's not. * * @param resource|string $data * @param bool $modified Should be set to true, if this event handler * changed &$data. * @return void */ protected function validateVCard(&$data, &$modified) { // If it's a stream, we convert it to a string first. if (is_resource($data)) { $data = stream_get_contents($data); } $before = md5($data); // Converting the data to unicode, if needed. $data = DAV\StringUtil::ensureUTF8($data); if (md5($data) !== $before) { $modified = true; } try { // If the data starts with a [, we can reasonably assume we're dealing // with a jCal object. if (substr($data, 0, 1) === '[') { $vobj = VObject\Reader::readJson($data); // Converting $data back to iCalendar, as that's what we // technically support everywhere. $data = $vobj->serialize(); $modified = true; } else { $vobj = VObject\Reader::read($data); } } catch (VObject\ParseException $e) { throw new DAV\Exception\UnsupportedMediaType('This resource only supports valid vCard or jCard data. Parse error: ' . $e->getMessage()); } if ($vobj->name !== 'VCARD') { throw new DAV\Exception\UnsupportedMediaType('This collection can only support vcard objects.'); } if (!isset($vobj->UID)) { // No UID in vcards is invalid, but we'll just add it in anyway. $vobj->add('UID', DAV\UUIDUtil::getUUID()); $data = $vobj->serialize(); $modified = true; } }
/** * Parses a webdav lock xml body, and returns a new Sabre\DAV\Locks\LockInfo object * * @param string $body * @return DAV\Locks\LockInfo */ protected function parseLockRequest($body) { $xml = simplexml_load_string(DAV\XMLUtil::convertDAVNamespace($body), null, LIBXML_NOWARNING); $xml->registerXPathNamespace('d', 'urn:DAV'); $lockInfo = new LockInfo(); $children = $xml->children("urn:DAV"); $lockInfo->owner = (string) $children->owner; $lockInfo->token = DAV\UUIDUtil::getUUID(); $lockInfo->scope = count($xml->xpath('d:lockscope/d:exclusive')) > 0 ? LockInfo::EXCLUSIVE : LockInfo::SHARED; return $lockInfo; }
/** * Event handler for the 'schedule' event. * * This handler attempts to look at local accounts to deliver the * scheduling object. * * @param ITip\Message $iTipMessage * @return void */ function scheduleLocalDelivery(ITip\Message $iTipMessage) { $aclPlugin = $this->server->getPlugin('acl'); // Local delivery is not available if the ACL plugin is not loaded. if (!$aclPlugin) { return; } $caldavNS = '{' . Plugin::NS_CALDAV . '}'; $principalUri = $aclPlugin->getPrincipalByUri($iTipMessage->recipient); if (!$principalUri) { $iTipMessage->scheduleStatus = '3.7;Could not find principal.'; return; } // We found a principal URL, now we need to find its inbox. // Unfortunately we may not have sufficient privileges to find this, so // we are temporarily turning off ACL to let this come through. // // Once we support PHP 5.5, this should be wrapped in a try..finally // block so we can ensure that this privilege gets added again after. $this->server->removeListener('propFind', [$aclPlugin, 'propFind']); $result = $this->server->getProperties($principalUri, ['{DAV:}principal-URL', $caldavNS . 'calendar-home-set', $caldavNS . 'schedule-inbox-URL', $caldavNS . 'schedule-default-calendar-URL', '{http://sabredav.org/ns}email-address']); // Re-registering the ACL event $this->server->on('propFind', [$aclPlugin, 'propFind'], 20); if (!isset($result[$caldavNS . 'schedule-inbox-URL'])) { $iTipMessage->scheduleStatus = '5.2;Could not find local inbox'; return; } if (!isset($result[$caldavNS . 'calendar-home-set'])) { $iTipMessage->scheduleStatus = '5.2;Could not locate a calendar-home-set'; return; } if (!isset($result[$caldavNS . 'schedule-default-calendar-URL'])) { $iTipMessage->scheduleStatus = '5.2;Could not find a schedule-default-calendar-URL property'; return; } $calendarPath = $result[$caldavNS . 'schedule-default-calendar-URL']->getHref(); $homePath = $result[$caldavNS . 'calendar-home-set']->getHref(); $inboxPath = $result[$caldavNS . 'schedule-inbox-URL']->getHref(); if ($iTipMessage->method === 'REPLY') { $privilege = 'schedule-deliver-reply'; } else { $privilege = 'schedule-deliver-invite'; } if (!$aclPlugin->checkPrivileges($inboxPath, $caldavNS . $privilege, DAVACL\Plugin::R_PARENT, false)) { $iTipMessage->scheduleStatus = '3.8;organizer did not have the ' . $privilege . ' privilege on the attendees inbox'; return; } // Next, we're going to find out if the item already exits in one of // the users' calendars. $uid = $iTipMessage->uid; $newFileName = 'sabredav-' . \Sabre\DAV\UUIDUtil::getUUID() . '.ics'; $home = $this->server->tree->getNodeForPath($homePath); $inbox = $this->server->tree->getNodeForPath($inboxPath); $currentObject = null; $objectNode = null; $isNewNode = false; $result = $home->getCalendarObjectByUID($uid); if ($result) { // There was an existing object, we need to update probably. $objectPath = $homePath . '/' . $result; $objectNode = $this->server->tree->getNodeForPath($objectPath); $oldICalendarData = $objectNode->get(); $currentObject = Reader::read($oldICalendarData); } else { $isNewNode = true; } $broker = new ITip\Broker(); $newObject = $broker->processMessage($iTipMessage, $currentObject); $inbox->createFile($newFileName, $iTipMessage->message->serialize()); if (!$newObject) { // We received an iTip message referring to a UID that we don't // have in any calendars yet, and processMessage did not give us a // calendarobject back. // // The implication is that processMessage did not understand the // iTip message. $iTipMessage->scheduleStatus = '5.0;iTip message was not processed by the server, likely because we didn\'t understand it.'; return; } // Note that we are bypassing ACL on purpose by calling this directly. // We may need to look a bit deeper into this later. Supporting ACL // here would be nice. if ($isNewNode) { $calendar = $this->server->tree->getNodeForPath($calendarPath); $calendar->createFile($newFileName, $newObject->serialize()); } else { // If the message was a reply, we may have to inform other // attendees of this attendees status. Therefore we're shooting off // another itipMessage. if ($iTipMessage->method === 'REPLY') { $this->processICalendarChange($oldICalendarData, $newObject, [$iTipMessage->recipient], [$iTipMessage->sender]); } $objectNode->put($newObject->serialize()); } $iTipMessage->scheduleStatus = '1.2;Message delivered locally'; }