function post() { if (!local_channel() || get_pconfig(local_channel(), 'cdav', 'enabled') != 1) { return; } $channel = \App::get_channel(); $principalUri = 'principals/' . $channel['channel_address']; if (!cdav_principal($principalUri)) { return; } if (\DBA::$dba && \DBA::$dba->connected) { $pdovars = \DBA::$dba->pdo_get(); } else { killme(); } $pdo = new \PDO($pdovars[0], $pdovars[1], $pdovars[2]); $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); require_once 'vendor/autoload.php'; if (argc() == 2 && argv(1) === 'calendar') { $caldavBackend = new \Sabre\CalDAV\Backend\PDO($pdo); $calendars = $caldavBackend->getCalendarsForUser($principalUri); //create new calendar if ($_REQUEST['{DAV:}displayname'] && $_REQUEST['create']) { do { $duplicate = false; $calendarUri = random_string(40); $r = q("SELECT uri FROM calendarinstances WHERE principaluri = '%s' AND uri = '%s' LIMIT 1", dbesc($principalUri), dbesc($calendarUri)); if (count($r)) { $duplicate = true; } } while ($duplicate == true); $properties = ['{DAV:}displayname' => $_REQUEST['{DAV:}displayname'], '{http://apple.com/ns/ical/}calendar-color' => $_REQUEST['color'], '{urn:ietf:params:xml:ns:caldav}calendar-description' => $channel['channel_name']]; $id = $caldavBackend->createCalendar($principalUri, $calendarUri, $properties); // set new calendar to be visible set_pconfig(local_channel(), 'cdav_calendar', $id[0], 1); } //create new calendar object via ajax request if ($_REQUEST['submit'] === 'create_event' && $_REQUEST['title'] && $_REQUEST['target'] && $_REQUEST['dtstart']) { $id = explode(':', $_REQUEST['target']); if (!cdav_perms($id[0], $calendars, true)) { return; } $title = $_REQUEST['title']; $dtstart = new \DateTime($_REQUEST['dtstart']); if ($_REQUEST['dtend']) { $dtend = new \DateTime($_REQUEST['dtend']); } $description = $_REQUEST['description']; $location = $_REQUEST['location']; do { $duplicate = false; $objectUri = random_string(40) . '.ics'; $r = q("SELECT uri FROM calendarobjects WHERE calendarid = %s AND uri = '%s' LIMIT 1", intval($id[0]), dbesc($objectUri)); if (count($r)) { $duplicate = true; } } while ($duplicate == true); $vcalendar = new \Sabre\VObject\Component\VCalendar(['VEVENT' => ['SUMMARY' => $title, 'DTSTART' => $dtstart]]); if ($dtend) { $vcalendar->VEVENT->add('DTEND', $dtend); } if ($description) { $vcalendar->VEVENT->add('DESCRIPTION', $description); } if ($location) { $vcalendar->VEVENT->add('LOCATION', $location); } $calendarData = $vcalendar->serialize(); $caldavBackend->createCalendarObject($id, $objectUri, $calendarData); killme(); } //edit calendar name and color if ($_REQUEST['{DAV:}displayname'] && $_REQUEST['edit'] && $_REQUEST['id']) { $id = explode(':', $_REQUEST['id']); if (!cdav_perms($id[0], $calendars)) { return; } $mutations = ['{DAV:}displayname' => $_REQUEST['{DAV:}displayname'], '{http://apple.com/ns/ical/}calendar-color' => $_REQUEST['color']]; $patch = new \Sabre\DAV\PropPatch($mutations); $caldavBackend->updateCalendar($id, $patch); $patch->commit(); } //edit calendar object via ajax request if ($_REQUEST['submit'] === 'update_event' && $_REQUEST['uri'] && $_REQUEST['title'] && $_REQUEST['target'] && $_REQUEST['dtstart']) { $id = explode(':', $_REQUEST['target']); if (!cdav_perms($id[0], $calendars, true)) { return; } $uri = $_REQUEST['uri']; $title = $_REQUEST['title']; $dtstart = new \DateTime($_REQUEST['dtstart']); $dtend = $_REQUEST['dtend'] ? new \DateTime($_REQUEST['dtend']) : ''; $description = $_REQUEST['description']; $location = $_REQUEST['location']; $object = $caldavBackend->getCalendarObject($id, $uri); $vcalendar = \Sabre\VObject\Reader::read($object['calendardata']); if ($title) { $vcalendar->VEVENT->SUMMARY = $title; } if ($dtstart) { $vcalendar->VEVENT->DTSTART = $dtstart; } if ($dtend) { $vcalendar->VEVENT->DTEND = $dtend; } else { unset($vcalendar->VEVENT->DTEND); } if ($description) { $vcalendar->VEVENT->DESCRIPTION = $description; } if ($location) { $vcalendar->VEVENT->LOCATION = $location; } $calendarData = $vcalendar->serialize(); $caldavBackend->updateCalendarObject($id, $uri, $calendarData); killme(); } //delete calendar object via ajax request if ($_REQUEST['delete'] && $_REQUEST['uri'] && $_REQUEST['target']) { $id = explode(':', $_REQUEST['target']); if (!cdav_perms($id[0], $calendars, true)) { return; } $uri = $_REQUEST['uri']; $caldavBackend->deleteCalendarObject($id, $uri); killme(); } //edit calendar object date/timeme via ajax request (drag and drop) if ($_REQUEST['update'] && $_REQUEST['id'] && $_REQUEST['uri']) { $id = [$_REQUEST['id'][0], $_REQUEST['id'][1]]; if (!cdav_perms($id[0], $calendars, true)) { return; } $uri = $_REQUEST['uri']; $dtstart = new \DateTime($_REQUEST['dtstart']); $dtend = $_REQUEST['dtend'] ? new \DateTime($_REQUEST['dtend']) : ''; $object = $caldavBackend->getCalendarObject($id, $uri); $vcalendar = \Sabre\VObject\Reader::read($object['calendardata']); if ($dtstart) { $vcalendar->VEVENT->DTSTART = $dtstart; } if ($dtend) { $vcalendar->VEVENT->DTEND = $dtend; } else { unset($vcalendar->VEVENT->DTEND); } $calendarData = $vcalendar->serialize(); $caldavBackend->updateCalendarObject($id, $uri, $calendarData); killme(); } //share a calendar - this only works on local system (with channels on the same server) if ($_REQUEST['sharee'] && $_REQUEST['share']) { $id = [intval($_REQUEST['calendarid']), intval($_REQUEST['instanceid'])]; if (!cdav_perms($id[0], $calendars)) { return; } $hash = $_REQUEST['sharee']; $sharee_arr = channelx_by_hash($hash); $sharee = new \Sabre\DAV\Xml\Element\Sharee(); $sharee->href = 'mailto:' . $sharee_arr['channel_hash']; $sharee->principal = 'principals/' . $sharee_arr['channel_address']; $sharee->access = intval($_REQUEST['access']); $sharee->properties = ['{DAV:}displayname' => $channel['channel_name']]; $caldavBackend->updateInvites($id, [$sharee]); } } if (argc() >= 2 && argv(1) === 'addressbook') { $carddavBackend = new \Sabre\CardDAV\Backend\PDO($pdo); $addressbooks = $carddavBackend->getAddressBooksForUser($principalUri); //create new addressbook if ($_REQUEST['{DAV:}displayname'] && $_REQUEST['create']) { do { $duplicate = false; $addressbookUri = random_string(20); $r = q("SELECT uri FROM addressbooks WHERE principaluri = '%s' AND uri = '%s' LIMIT 1", dbesc($principalUri), dbesc($addressbookUri)); if (count($r)) { $duplicate = true; } } while ($duplicate == true); $properties = ['{DAV:}displayname' => $_REQUEST['{DAV:}displayname']]; $carddavBackend->createAddressBook($principalUri, $addressbookUri, $properties); } //edit addressbook if ($_REQUEST['{DAV:}displayname'] && $_REQUEST['edit'] && intval($_REQUEST['id'])) { $id = $_REQUEST['id']; if (!cdav_perms($id, $addressbooks)) { return; } $mutations = ['{DAV:}displayname' => $_REQUEST['{DAV:}displayname']]; $patch = new \Sabre\DAV\PropPatch($mutations); $carddavBackend->updateAddressBook($id, $patch); $patch->commit(); } //create addressbook card if ($_REQUEST['create'] && $_REQUEST['target'] && $_REQUEST['fn']) { $id = $_REQUEST['target']; do { $duplicate = false; $uri = random_string(40) . '.vcf'; $r = q("SELECT uri FROM cards WHERE addressbookid = %s AND uri = '%s' LIMIT 1", intval($id), dbesc($uri)); if (count($r)) { $duplicate = true; } } while ($duplicate == true); //TODO: this mostly duplictes the procedure in update addressbook card. should move this part to a function to avoid duplication $fn = $_REQUEST['fn']; $vcard = new \Sabre\VObject\Component\VCard(['FN' => $fn, 'N' => array_reverse(explode(' ', $fn))]); $org = $_REQUEST['org']; if ($org) { $vcard->ORG = $org; } $title = $_REQUEST['title']; if ($title) { $vcard->TITLE = $title; } $tel = $_REQUEST['tel']; $tel_type = $_REQUEST['tel_type']; if ($tel) { $i = 0; foreach ($tel as $item) { if ($item) { $vcard->add('TEL', $item, ['type' => $tel_type[$i]]); } $i++; } } $email = $_REQUEST['email']; $email_type = $_REQUEST['email_type']; if ($email) { $i = 0; foreach ($email as $item) { if ($item) { $vcard->add('EMAIL', $item, ['type' => $email_type[$i]]); } $i++; } } $impp = $_REQUEST['impp']; $impp_type = $_REQUEST['impp_type']; if ($impp) { $i = 0; foreach ($impp as $item) { if ($item) { $vcard->add('IMPP', $item, ['type' => $impp_type[$i]]); } $i++; } } $url = $_REQUEST['url']; $url_type = $_REQUEST['url_type']; if ($url) { $i = 0; foreach ($url as $item) { if ($item) { $vcard->add('URL', $item, ['type' => $url_type[$i]]); } $i++; } } $adr = $_REQUEST['adr']; $adr_type = $_REQUEST['adr_type']; if ($adr) { $i = 0; foreach ($adr as $item) { if ($item) { $vcard->add('ADR', $item, ['type' => $adr_type[$i]]); } $i++; } } $note = $_REQUEST['note']; if ($note) { $vcard->NOTE = $note; } $cardData = $vcard->serialize(); $carddavBackend->createCard($id, $uri, $cardData); } //edit addressbook card if ($_REQUEST['update'] && $_REQUEST['uri'] && $_REQUEST['target']) { $id = $_REQUEST['target']; if (!cdav_perms($id, $addressbooks)) { return; } $uri = $_REQUEST['uri']; $object = $carddavBackend->getCard($id, $uri); $vcard = \Sabre\VObject\Reader::read($object['carddata']); $fn = $_REQUEST['fn']; if ($fn) { $vcard->FN = $fn; $vcard->N = array_reverse(explode(' ', $fn)); } $org = $_REQUEST['org']; if ($org) { $vcard->ORG = $org; } else { unset($vcard->ORG); } $title = $_REQUEST['title']; if ($title) { $vcard->TITLE = $title; } else { unset($vcard->TITLE); } $tel = $_REQUEST['tel']; $tel_type = $_REQUEST['tel_type']; if ($tel) { $i = 0; unset($vcard->TEL); foreach ($tel as $item) { if ($item) { $vcard->add('TEL', $item, ['type' => $tel_type[$i]]); } $i++; } } else { unset($vcard->TEL); } $email = $_REQUEST['email']; $email_type = $_REQUEST['email_type']; if ($email) { $i = 0; unset($vcard->EMAIL); foreach ($email as $item) { if ($item) { $vcard->add('EMAIL', $item, ['type' => $email_type[$i]]); } $i++; } } else { unset($vcard->EMAIL); } $impp = $_REQUEST['impp']; $impp_type = $_REQUEST['impp_type']; if ($impp) { $i = 0; unset($vcard->IMPP); foreach ($impp as $item) { if ($item) { $vcard->add('IMPP', $item, ['type' => $impp_type[$i]]); } $i++; } } else { unset($vcard->IMPP); } $url = $_REQUEST['url']; $url_type = $_REQUEST['url_type']; if ($url) { $i = 0; unset($vcard->URL); foreach ($url as $item) { if ($item) { $vcard->add('URL', $item, ['type' => $url_type[$i]]); } $i++; } } else { unset($vcard->URL); } $adr = $_REQUEST['adr']; $adr_type = $_REQUEST['adr_type']; if ($adr) { $i = 0; unset($vcard->ADR); foreach ($adr as $item) { if ($item) { $vcard->add('ADR', $item, ['type' => $adr_type[$i]]); } $i++; } } else { unset($vcard->ADR); } $note = $_REQUEST['note']; if ($note) { $vcard->NOTE = $note; } else { unset($vcard->NOTE); } $cardData = $vcard->serialize(); $carddavBackend->updateCard($id, $uri, $cardData); } //delete addressbook card if ($_REQUEST['delete'] && $_REQUEST['uri'] && $_REQUEST['target']) { $id = $_REQUEST['target']; if (!cdav_perms($id, $addressbooks)) { return; } $uri = $_REQUEST['uri']; $carddavBackend->deleteCard($id, $uri); } } //Import calendar or addressbook if ($_FILES && array_key_exists('userfile', $_FILES) && intval($_FILES['userfile']['size']) && $_REQUEST['target']) { $src = @file_get_contents($_FILES['userfile']['tmp_name']); if ($src) { if ($_REQUEST['c_upload']) { $id = explode(':', $_REQUEST['target']); $ext = 'ics'; $table = 'calendarobjects'; $column = 'calendarid'; $objects = new \Sabre\VObject\Splitter\ICalendar($src); $profile = \Sabre\VObject\Node::PROFILE_CALDAV; $backend = new \Sabre\CalDAV\Backend\PDO($pdo); } if ($_REQUEST['a_upload']) { $id[] = intval($_REQUEST['target']); $ext = 'vcf'; $table = 'cards'; $column = 'addressbookid'; $objects = new \Sabre\VObject\Splitter\VCard($src); $profile = \Sabre\VObject\Node::PROFILE_CARDDAV; $backend = new \Sabre\CardDAV\Backend\PDO($pdo); } while ($object = $objects->getNext()) { if ($_REQUEST['a_upload']) { $object = $object->convert(\Sabre\VObject\Document::VCARD40); } $ret = $object->validate($profile & \Sabre\VObject\Node::REPAIR); //level 3 Means that the document is invalid, //level 2 means a warning. A warning means it's valid but it could cause interopability issues, //level 1 means that there was a problem earlier, but the problem was automatically repaired. if ($ret[0]['level'] < 3) { do { $duplicate = false; $objectUri = random_string(40) . '.' . $ext; $r = q("SELECT uri FROM {$table} WHERE {$column} = %d AND uri = '%s' LIMIT 1", dbesc($id[0]), dbesc($objectUri)); if (count($r)) { $duplicate = true; } } while ($duplicate == true); if ($_REQUEST['c_upload']) { $backend->createCalendarObject($id, $objectUri, $object->serialize()); } if ($_REQUEST['a_upload']) { $backend->createCard($id[0], $objectUri, $object->serialize()); } } else { if ($_REQUEST['c_upload']) { notice('<strong>' . t('INVALID EVENT DISMISSED!') . '</strong>' . EOL . '<strong>' . t('Summary: ') . '</strong>' . ($object->VEVENT->SUMMARY ? $object->VEVENT->SUMMARY : t('Unknown')) . EOL . '<strong>' . t('Date: ') . '</strong>' . ($object->VEVENT->DTSTART ? $object->VEVENT->DTSTART : t('Unknown')) . EOL . '<strong>' . t('Reason: ') . '</strong>' . $ret[0]['message'] . EOL); } if ($_REQUEST['a_upload']) { notice('<strong>' . t('INVALID CARD DISMISSED!') . '</strong>' . EOL . '<strong>' . t('Name: ') . '</strong>' . ($object->FN ? $object->FN : t('Unknown')) . EOL . '<strong>' . t('Reason: ') . '</strong>' . $ret[0]['message'] . EOL); } } } } @unlink($src); } }
<?php include __DIR__ . '/../vendor/autoload.php'; if ($argc < 2) { echo "sabre/vobject ", Sabre\VObject\Version::VERSION, " manipulation benchmark\n"; echo "\n"; echo "This script can be used to measure the speed of opening a large amount of\n"; echo "vcards, making a few alterations and serializing them again.\n"; echo "system."; echo "\n"; echo "Usage: " . $argv[0] . " inputfile.vcf\n"; die; } list(, $inputFile) = $argv; $input = file_get_contents($inputFile); $splitter = new Sabre\VObject\Splitter\VCard($input); $bench = new Hoa\Bench\Bench(); while (true) { $bench->parse->start(); $vcard = $splitter->getNext(); $bench->parse->pause(); if (!$vcard) { break; } $bench->manipulate->start(); $vcard->{'X-FOO'} = 'Random new value!'; $emails = []; if (isset($vcard->EMAIL)) { foreach ($vcard->EMAIL as $email) { $emails[] = (string) $email; }
/** * Allows for importing data into user's address book. * * @param int $iUserId User ID * @param string $sSyncType Data source type. Currently, "csv" and "vcf" options are supported. * @param string $sTempFileName Path to the file data are imported from. * @param int $iParsedCount * @param int $iGroupId * @param bool $bIsShared * * @return int|false If importing is successful, number of imported entries is returned. */ public function import($iUserId, $sSyncType, $sTempFileName, &$iParsedCount, $iGroupId, $bIsShared) { $oApiUsersManager = CApi::Manager('users'); $oAccount = $oApiUsersManager->getDefaultAccount($iUserId); if ($sSyncType === \EContactFileType::CSV) { $this->inc('helpers.' . $sSyncType . '.formatter'); $this->inc('helpers.' . $sSyncType . '.parser'); $this->inc('helpers.sync.' . $sSyncType); $sSyncClass = 'CApi' . ucfirst($this->GetManagerName()) . 'Sync' . ucfirst($sSyncType); if (class_exists($sSyncClass)) { $oSync = new $sSyncClass($this); return $oSync->Import($iUserId, $sTempFileName, $iParsedCount, $iGroupId, $bIsShared); } } else { if ($sSyncType === \EContactFileType::VCF) { // You can either pass a readable stream, or a string. $oHandler = fopen($sTempFileName, 'r'); $oSplitter = new \Sabre\VObject\Splitter\VCard($oHandler); while ($oVCard = $oSplitter->getNext()) { $oContact = new \CContact(); $oContact->InitFromVCardObject($iUserId, $oVCard); if ($oAccount) { $oContact->IdDomain = $oAccount->IdDomain; $oContact->IdTenant = $oAccount->IdTenant; } $oContact->SharedToAll = $bIsShared; $oContact->GroupsIds = array($iGroupId); if ($this->createContact($oContact)) { $iParsedCount++; } } return $iParsedCount; } } return false; }
protected function actionImportVCard($params) { $summaryLog = new \GO\Base\Component\SummaryLog(); $readOnly = !empty($params['readOnly']); if (isset($_FILES['files']['tmp_name'][0])) { $params['file'] = $_FILES['files']['tmp_name'][0]; } if (!empty($params['importBaseParams'])) { $importBaseParams = json_decode($params['importBaseParams'], true); $params['addressbook_id'] = $importBaseParams['addressbook_id']; } $file = new \GO\Base\Fs\File($params['file']); $file->convertToUtf8(); $options = \Sabre\VObject\Reader::OPTION_FORGIVING + \Sabre\VObject\Reader::OPTION_IGNORE_INVALID_LINES; $vcards = new \Sabre\VObject\Splitter\VCard(fopen($file->path(), 'r+'), $options); unset($params['file']); $nr = 0; if ($readOnly) { $contactsAttr = array(); } while ($vObject = $vcards->getNext()) { $nr++; \GO\Base\VObject\Reader::convertVCard21ToVCard30($vObject); $contact = new \GO\Addressbook\Model\Contact(); try { if ($contact->importVObject($vObject, $params, !$readOnly)) { $summaryLog->addSuccessful(); } if ($readOnly) { $contactsAttr[] = $contact->getAttributes('formatted'); } } catch (\Exception $e) { $summaryLog->addError($nr, $e->getMessage()); } } $response = $summaryLog->getErrorsJson(); if ($readOnly) { $response['contacts'] = $contactsAttr; } $response['successCount'] = $summaryLog->getTotalSuccessful(); $response['totalCount'] = $summaryLog->getTotal(); $response['success'] = true; return $response; }
/** * @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; }
/** * @param int $iUserId * @param string $sSyncType * @param string $sTempFileName * @param int $iParsedCount * @return int | false */ public function Import($iUserId, $sSyncType, $sTempFileName, &$iParsedCount) { if ($sSyncType === \EContactFileType::CSV) { $this->inc('helpers.' . $sSyncType . '.formatter'); $this->inc('helpers.' . $sSyncType . '.parser'); $this->inc('helpers.sync.' . $sSyncType); $sSyncClass = 'CApi' . ucfirst($this->GetManagerName()) . 'Sync' . ucfirst($sSyncType); if (class_exists($sSyncClass)) { $oSync = new $sSyncClass($this); return $oSync->Import($iUserId, $sTempFileName, $iParsedCount); } } else { if ($sSyncType === \EContactFileType::VCF) { // You can either pass a readable stream, or a string. $oHandler = fopen($sTempFileName, 'r'); $oSplitter = new \Sabre\VObject\Splitter\VCard($oHandler); while ($oVCard = $oSplitter->getNext()) { $oContact = new \CContact(); $oContact->InitFromVCardObject($iUserId, $oVCard); if ($this->CreateContact($oContact)) { $iParsedCount++; } } return $iParsedCount; } } return false; }