mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-09 06:28:28 +03:00
Added draft code to use Kolab as AddressBook
This commit is contained in:
parent
733a96a987
commit
be35be8908
6 changed files with 246 additions and 42 deletions
|
|
@ -293,7 +293,7 @@ abstract class SearchCriterias
|
|||
return $sCriteriasResult ?: 'ALL';
|
||||
}
|
||||
|
||||
private static function escapeSearchString(\MailSo\Imap\ImapClient $oImapClient, string $sSearch) : string
|
||||
public static function escapeSearchString(\MailSo\Imap\ImapClient $oImapClient, string $sSearch) : string
|
||||
{
|
||||
return !\MailSo\Base\Utils::IsAscii($sSearch)
|
||||
? '{'.\strlen($sSearch).'}'."\r\n".$sSearch : $oImapClient->EscapeString($sSearch);
|
||||
|
|
|
|||
|
|
@ -267,6 +267,7 @@ class Actions
|
|||
$sDsn = $sDsnType . ':' . \preg_replace('/^[a-z]+:/', '', $sDsn);
|
||||
}
|
||||
$mResult = new Providers\AddressBook\PdoAddressBook($sDsn, $sUser, $sPassword, $sDsnType);
|
||||
// $mResult = new Providers\AddressBook\KolabAddressBook($this->MailClient()->ImapClient());
|
||||
break;
|
||||
case 'identities':
|
||||
case 'suggestions':
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@ interface AddressBookInterface
|
|||
|
||||
public function ContactSave(string $sEmail, Classes\Contact $oContact) : bool;
|
||||
|
||||
public function DeleteContacts(string $sEmail, array $aContactIds, bool $bSyncDb = true) : bool;
|
||||
public function DeleteContacts(string $sEmail, array $aContactIds) : bool;
|
||||
|
||||
public function DeleteAllContacts(string $sEmail, bool $bSyncDb = true) : bool;
|
||||
public function DeleteAllContacts(string $sEmail) : bool;
|
||||
|
||||
public function GetContacts(string $sEmail, int $iOffset = 0, int $iLimit = 20, string $sSearch = '', int &$iResultCount = 0) : array;
|
||||
|
||||
|
|
|
|||
|
|
@ -180,44 +180,20 @@ class Contact implements \JsonSerializable
|
|||
return $this->IdContactStr.'.vcf';
|
||||
}
|
||||
|
||||
public function ToVCard(string $sPreVCard = '', $oLogger = null) : string
|
||||
public function GetUID() : string
|
||||
{
|
||||
$this->UpdateDependentValues();
|
||||
|
||||
if ("\xef\xbb\xbf" === \substr($sPreVCard, 0, 3))
|
||||
{
|
||||
$sPreVCard = \substr($sPreVCard, 3);
|
||||
}
|
||||
|
||||
$oVCard = null;
|
||||
if (\strlen($sPreVCard))
|
||||
{
|
||||
try
|
||||
{
|
||||
$oVCard = \Sabre\VObject\Reader::read($sPreVCard);
|
||||
}
|
||||
catch (\Throwable $oExc)
|
||||
{
|
||||
if ($oLogger)
|
||||
{
|
||||
$oLogger->WriteException($oExc);
|
||||
$oLogger->WriteDump($sPreVCard);
|
||||
}
|
||||
foreach ($this->Properties as $oProperty) {
|
||||
if ($oProperty && PropertyType::UID == $oProperty->Type) {
|
||||
return $oProperty->Value;
|
||||
}
|
||||
}
|
||||
return $this->IdContactStr;
|
||||
}
|
||||
|
||||
// if ($oLogger)
|
||||
// {
|
||||
// $oLogger->WriteDump($sPreVCard);
|
||||
// }
|
||||
|
||||
if (!$oVCard)
|
||||
{
|
||||
$oVCard = new \Sabre\VObject\Component\VCard();
|
||||
}
|
||||
|
||||
private function fillVCard(\Sabre\VObject\Component\VCard $oVCard) : void
|
||||
{
|
||||
$oVCard->VERSION = '3.0';
|
||||
$oVCard->PRODID = '-//RainLoop//'.APP_VERSION.'//EN';
|
||||
$oVCard->PRODID = '-//SnappyMail//'.APP_VERSION.'//EN';
|
||||
|
||||
unset($oVCard->FN, $oVCard->EMAIL, $oVCard->TEL, $oVCard->URL, $oVCard->NICKNAME);
|
||||
|
||||
|
|
@ -282,10 +258,70 @@ class Contact implements \JsonSerializable
|
|||
$oVCard->UID = empty($sUid) ? $this->IdContactStr : $sUid;
|
||||
$oVCard->N = array($sLastName, $sFirstName, $sMiddleName, $sPrefix, $sSuffix);
|
||||
$oVCard->REV = \gmdate('Ymd', $this->Changed).'T'.\gmdate('His', $this->Changed).'Z';
|
||||
}
|
||||
|
||||
public function ToVCard(string $sPreVCard = '', $oLogger = null) : string
|
||||
{
|
||||
$this->UpdateDependentValues();
|
||||
|
||||
if ("\xef\xbb\xbf" === \substr($sPreVCard, 0, 3)) {
|
||||
$sPreVCard = \substr($sPreVCard, 3);
|
||||
}
|
||||
|
||||
$oVCard = null;
|
||||
|
||||
if (\strlen($sPreVCard)) {
|
||||
try
|
||||
{
|
||||
$oVCard = \Sabre\VObject\Reader::read($sPreVCard);
|
||||
}
|
||||
catch (\Throwable $oExc)
|
||||
{
|
||||
if ($oLogger) {
|
||||
$oLogger->WriteException($oExc);
|
||||
$oLogger->WriteDump($sPreVCard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if ($oLogger) {
|
||||
// $oLogger->WriteDump($sPreVCard);
|
||||
// }
|
||||
|
||||
$oVCard = $oVCard ?: new \Sabre\VObject\Component\VCard();
|
||||
|
||||
$this->fillVCard($oVCard);
|
||||
|
||||
return (string) $oVCard->serialize();
|
||||
}
|
||||
|
||||
public function ToXCard(string $sPreVCard = '', $oLogger = null) : string
|
||||
{
|
||||
$this->UpdateDependentValues();
|
||||
|
||||
$oVCard = null;
|
||||
|
||||
if (\strlen($sPreVCard)) {
|
||||
try
|
||||
{
|
||||
$oVCard = \Sabre\VObject\Reader::readXML($sPreVCard);
|
||||
}
|
||||
catch (\Throwable $oExc)
|
||||
{
|
||||
if ($oLogger) {
|
||||
$oLogger->WriteException($oExc);
|
||||
$oLogger->WriteDump($sPreVCard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$oVCard = $oVCard ?: new \Sabre\VObject\Component\VCard();
|
||||
|
||||
$this->fillVCard($oVCard);
|
||||
|
||||
return (string) \Sabre\VObject\Writer::writeXml($oVCard);
|
||||
}
|
||||
|
||||
public function ToCsv(bool $bWithHeader = false) : string
|
||||
{
|
||||
$aData = array();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,170 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\AddressBook;
|
||||
|
||||
use RainLoop\Providers\AddressBook\Enumerations\PropertyType;
|
||||
|
||||
class KolabAddressBook implements \RainLoop\Providers\AddressBook\AddressBookInterface
|
||||
{
|
||||
use CardDAV;
|
||||
|
||||
protected $sFolderName;
|
||||
|
||||
function __construct(\MailSo\Imap\ImapClient $oImapClient)
|
||||
{
|
||||
$this->oImapClient = $oImapClient;
|
||||
}
|
||||
|
||||
public function SetFolder(string $sFolderName) : bool
|
||||
{
|
||||
$metadata = $this->oImapClient->FolderGetMetadata($sFolderName, [\MailSo\Imap\Enumerations\MetadataKeys::KOLAB_CTYPE]);
|
||||
if ($metadata && 'contact' !== \array_shift($metadata)) {
|
||||
// Throw error
|
||||
// $this->oImapClient->FolderList() : array
|
||||
}
|
||||
$this->oImapClient->FolderSelect($sFolderName);
|
||||
$this->sFolderName = $sFolderName;
|
||||
}
|
||||
|
||||
public function IsSupported() : bool
|
||||
{
|
||||
// Check $this->oImapClient->IsSupported('METADATA')
|
||||
return true;
|
||||
}
|
||||
|
||||
public function IsSharingAllowed() : bool
|
||||
{
|
||||
return $this->IsSupported() && false; // TODO
|
||||
}
|
||||
|
||||
public function Sync(array $oConfig) : bool
|
||||
{
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
public function Export(string $sEmail, string $sType = 'vcf') : bool
|
||||
{
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
public function ContactSave(string $sEmail, Classes\Contact $oContact) : bool
|
||||
{
|
||||
// TODO
|
||||
// $emails = $oContact->GetEmails();
|
||||
|
||||
$oContact->PopulateDisplayAndFullNameValue();
|
||||
|
||||
$sUID = $oContact->GetUID();
|
||||
|
||||
$oMessage = new \MailSo\Mime\Message();
|
||||
$oMessage->SetFrom(new \MailSo\Mime\Email($sEmail, $oContact->Display));
|
||||
$oMessage->SetSubject($sUID);
|
||||
// $oMessage->SetDate(\time());
|
||||
$oMessage->Headers->AddByName('X-Kolab-Type', 'application/x-vnd.kolab.contact');
|
||||
$oMessage->Headers->AddByName('X-Kolab-Mime-Version', '3.0');
|
||||
// $oMessage->Headers->AddByName('User-Agent', 'SnappyMail');
|
||||
|
||||
$oPart = new \MailSo\Mime\Part;
|
||||
$oPart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, 'text/plain');
|
||||
$oPart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TRANSFER_ENCODING, '7Bit');
|
||||
$oPart->Body = "This is a Kolab Groupware object.\r\n"
|
||||
. "To view this object you will need an email client that can understand the Kolab Groupware format.\r\n"
|
||||
. "For a list of such email clients please visit\r\n"
|
||||
. "http://www.kolab.org/get-kolab";
|
||||
$oMessage->SubParts->append($oPart);
|
||||
|
||||
// Now the vCard
|
||||
$oPart = new \MailSo\Mime\Part;
|
||||
$oPart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, 'application/vcard+xml; name="kolab.xml"');
|
||||
// $oPart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_TRANSFER_ENCODING, 'quoted-printable');
|
||||
$oPart->Headers->AddByName(\MailSo\Mime\Enumerations\Header::CONTENT_DISPOSITION, 'attachment; filename="kolab.xml"');
|
||||
$oPart->Body = $oContact->ToXCard($sPreVCard = '', $oLogger);
|
||||
$oMessage->SubParts->append($oPart);
|
||||
|
||||
// Search in IMAP folder:
|
||||
$email = \MailSo\Imap\SearchCriterias::escapeSearchString($sEmail);
|
||||
$aUids = $this->oImapClient->MessageSimpleSearch("SUBJECT {$sUID}");
|
||||
// $aUids = $this->oImapClient->MessageSimpleSearch("OR SUBJECT {$sUID} FROM {$email}");
|
||||
// $aUids = $this->oImapClient->MessageSimpleSearch("OR SUBJECT {$sUID} FROM {$email} BODY {$email}");
|
||||
|
||||
if ($aUids) {
|
||||
// Replace Message
|
||||
if (false && $this->oImapClient->IsSupported('REPLACE')) {
|
||||
// UID REPLACE
|
||||
} else {
|
||||
$oRange = new \MailSo\Imap\SequenceSet($aUids[0]);
|
||||
$this->oImapClient->MessageStoreFlag($oRange,
|
||||
array(\MailSo\Imap\Enumerations\MessageFlag::DELETED),
|
||||
\MailSo\Imap\Enumerations\StoreAction::ADD_FLAGS_SILENT
|
||||
);
|
||||
$this->oImapClient->FolderExpunge($oRange);
|
||||
}
|
||||
}
|
||||
|
||||
// Store Message
|
||||
$rMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource();
|
||||
$iMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter(
|
||||
$oMessage->ToStream(false), array($rMessageStream), 8192, true, true);
|
||||
if (false !== $iMessageStreamSize) {
|
||||
\rewind($rMessageStream);
|
||||
$this->oImapClient->MessageAppendStream($this->sFolderName, $rMessageStream, $iMessageStreamSize);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function DeleteContacts(string $sEmail, array $aContactIds) : bool
|
||||
{
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
public function DeleteAllContacts(string $sEmail) : bool
|
||||
{
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
public function GetContacts(string $sEmail, int $iOffset = 0, int $iLimit = 20, string $sSearch = '', int &$iResultCount = 0) : array
|
||||
{
|
||||
// TODO
|
||||
return [];
|
||||
}
|
||||
|
||||
public function GetContactByID(string $sEmail, $mID, bool $bIsStrID = false) : ?Classes\Contact
|
||||
{
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
public function GetSuggestions(string $sEmail, string $sSearch, int $iLimit = 20) : array
|
||||
{
|
||||
// TODO
|
||||
return [];
|
||||
}
|
||||
|
||||
public function IncFrec(string $sEmail, array $aEmails, bool $bCreateAuto = true) : bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function Test() : string
|
||||
{
|
||||
$sResult = '';
|
||||
try
|
||||
{
|
||||
// $sResult = 'Unknown error';
|
||||
}
|
||||
catch (\Throwable $oException)
|
||||
{
|
||||
$sResult = $oException->getMessage();
|
||||
if (!\is_string($sResult) || empty($sResult)) {
|
||||
$sResult = 'Unknown error';
|
||||
}
|
||||
}
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
}
|
||||
|
|
@ -308,7 +308,7 @@ class PdoAddressBook
|
|||
$bCsvHeader = true;
|
||||
|
||||
$aDatabaseSyncData = $this->prepareDatabaseSyncData($iUserID);
|
||||
if (\is_array($aDatabaseSyncData) && \count($aDatabaseSyncData))
|
||||
if (\count($aDatabaseSyncData))
|
||||
{
|
||||
foreach ($aDatabaseSyncData as $mData)
|
||||
{
|
||||
|
|
@ -476,12 +476,9 @@ class PdoAddressBook
|
|||
return true;
|
||||
}
|
||||
|
||||
public function DeleteAllContacts(string $sEmail, bool $bSyncDb = true) : bool
|
||||
public function DeleteAllContacts(string $sEmail) : bool
|
||||
{
|
||||
if ($bSyncDb)
|
||||
{
|
||||
$this->SyncDatabase();
|
||||
}
|
||||
$this->SyncDatabase();
|
||||
|
||||
$iUserID = $this->getUserId($sEmail);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue