mirror of
https://github.com/the-djmaze/snappymail.git
synced 2024-09-20 07:35:55 +08:00
CardDAV second look :)
This commit is contained in:
parent
7648000521
commit
a46d6832d9
|
@ -10,6 +10,7 @@ function AdminContacts()
|
|||
this.defautOptionsAfterRender = Utils.defautOptionsAfterRender;
|
||||
this.enableContacts = ko.observable(!!RL.settingsGet('ContactsEnable'));
|
||||
this.contactsSharing = ko.observable(!!RL.settingsGet('ContactsSharing'));
|
||||
this.contactsSync = ko.observable(!!RL.settingsGet('ContactsSync'));
|
||||
|
||||
var
|
||||
aTypes = ['sqlite', 'mysql', 'pgsql'],
|
||||
|
@ -183,6 +184,12 @@ AdminContacts.prototype.onBuild = function ()
|
|||
'ContactsSharing': bValue ? '1' : '0'
|
||||
});
|
||||
});
|
||||
|
||||
self.contactsSync.subscribe(function (bValue) {
|
||||
RL.remote().saveAdminConfig(null, {
|
||||
'ContactsSync': bValue ? '1' : '0'
|
||||
});
|
||||
});
|
||||
|
||||
self.contactsType.subscribe(function (sValue) {
|
||||
RL.remote().saveAdminConfig(f5, {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
function ContactModel()
|
||||
{
|
||||
this.idContact = 0;
|
||||
this.idContactStr = '';
|
||||
this.display = '';
|
||||
this.properties = [];
|
||||
this.readOnly = false;
|
||||
|
@ -57,6 +58,7 @@ ContactModel.prototype.parse = function (oItem)
|
|||
if (oItem && 'Object/Contact' === oItem['@Object'])
|
||||
{
|
||||
this.idContact = Utils.pInt(oItem['IdContact']);
|
||||
this.idContactStr = Utils.pString(oItem['IdContactStr']);
|
||||
this.display = Utils.pString(oItem['Display']);
|
||||
this.readOnly = !!oItem['ReadOnly'];
|
||||
this.scopeType = Utils.pInt(oItem['ScopeType']);
|
||||
|
|
|
@ -570,11 +570,12 @@ WebMailAjaxRemoteStorage.prototype.contacts = function (fCallback, iOffset, iLim
|
|||
/**
|
||||
* @param {?Function} fCallback
|
||||
*/
|
||||
WebMailAjaxRemoteStorage.prototype.contactSave = function (fCallback, sRequestUid, sUid, nScopeType, aProperties)
|
||||
WebMailAjaxRemoteStorage.prototype.contactSave = function (fCallback, sRequestUid, sUid, sUidStr, nScopeType, aProperties)
|
||||
{
|
||||
this.defaultRequest(fCallback, 'ContactSave', {
|
||||
'RequestUid': sRequestUid,
|
||||
'Uid': Utils.trim(sUid),
|
||||
'UidStr': Utils.trim(sUidStr),
|
||||
'ScopeType': nScopeType,
|
||||
'Properties': aProperties
|
||||
});
|
||||
|
|
|
@ -48,6 +48,7 @@ function PopupsContactsViewModel()
|
|||
this.viewClearSearch = ko.observable(false);
|
||||
|
||||
this.viewID = ko.observable('');
|
||||
this.viewIDStr = ko.observable('');
|
||||
this.viewReadOnly = ko.observable(false);
|
||||
this.viewScopeType = ko.observable(Enums.ContactScopeType.Default);
|
||||
this.viewProperties = ko.observableArray([]);
|
||||
|
@ -251,13 +252,14 @@ function PopupsContactsViewModel()
|
|||
self.viewID(Utils.pInt(oData.Result.ResultID));
|
||||
}
|
||||
|
||||
if ('' === self.viewIDStr())
|
||||
{
|
||||
self.viewIDStr(Utils.pString(oData.Result.ResultIDStr));
|
||||
}
|
||||
|
||||
self.reloadContactList();
|
||||
bRes = true;
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// // TODO
|
||||
// }
|
||||
|
||||
_.delay(function () {
|
||||
self.viewSaveTrigger(bRes ? Enums.SaveSettingsStep.TrueResult : Enums.SaveSettingsStep.FalseResult);
|
||||
|
@ -270,7 +272,7 @@ function PopupsContactsViewModel()
|
|||
}, 1000);
|
||||
}
|
||||
|
||||
}, sRequestUid, this.viewID(), this.viewScopeType(), aProperties);
|
||||
}, sRequestUid, this.viewID(), this.viewIDStr(), this.viewScopeType(), aProperties);
|
||||
|
||||
}, function () {
|
||||
var
|
||||
|
@ -414,6 +416,7 @@ PopupsContactsViewModel.prototype.populateViewContact = function (oContact)
|
|||
{
|
||||
var
|
||||
sId = '',
|
||||
sIdStr = '',
|
||||
bHasName = false,
|
||||
aList = []
|
||||
;
|
||||
|
@ -427,6 +430,7 @@ PopupsContactsViewModel.prototype.populateViewContact = function (oContact)
|
|||
if (oContact)
|
||||
{
|
||||
sId = oContact.idContact;
|
||||
sIdStr = oContact.idContactStr;
|
||||
|
||||
if (Utils.isNonEmptyArray(oContact.properties))
|
||||
{
|
||||
|
@ -454,6 +458,7 @@ PopupsContactsViewModel.prototype.populateViewContact = function (oContact)
|
|||
}
|
||||
|
||||
this.viewID(sId);
|
||||
this.viewIDStr(sIdStr);
|
||||
this.viewProperties([]);
|
||||
this.viewProperties(aList);
|
||||
|
||||
|
|
|
@ -995,6 +995,7 @@ class Actions
|
|||
|
||||
$aResult['ContactsEnable'] = (bool) $oConfig->Get('contacts', 'enable', false);
|
||||
$aResult['ContactsSharing'] = (bool) $oConfig->Get('contacts', 'allow_sharing', false);
|
||||
$aResult['ContactsSync'] = (bool) $oConfig->Get('contacts', 'allow_carddav_sync', false);
|
||||
$aResult['ContactsPdoType'] = $this->ValidateContactPdoType(\trim($this->Config()->Get('contacts', 'type', 'sqlite')));
|
||||
$aResult['ContactsPdoDsn'] = (string) $oConfig->Get('contacts', 'pdo_dsn', '');
|
||||
$aResult['ContactsPdoType'] = (string) $oConfig->Get('contacts', 'type', '');
|
||||
|
@ -1875,6 +1876,7 @@ class Actions
|
|||
|
||||
$this->setConfigFromParams($oConfig, 'ContactsEnable', 'contacts', 'enable', 'bool');
|
||||
$this->setConfigFromParams($oConfig, 'ContactsSharing', 'contacts', 'allow_sharing', 'bool');
|
||||
$this->setConfigFromParams($oConfig, 'ContactsSync', 'contacts', 'allow_carddav_sync', 'bool');
|
||||
$this->setConfigFromParams($oConfig, 'ContactsPdoDsn', 'contacts', 'pdo_dsn', 'string');
|
||||
$this->setConfigFromParams($oConfig, 'ContactsPdoUser', 'contacts', 'pdo_user', 'string');
|
||||
$this->setConfigFromParams($oConfig, 'ContactsPdoPassword', 'contacts', 'pdo_password', 'dummy');
|
||||
|
@ -4207,7 +4209,7 @@ class Actions
|
|||
if ($this->PersonalAddressBookProvider($oAccount)->IsActive())
|
||||
{
|
||||
$iCount = 0;
|
||||
$mResult = $this->PersonalAddressBookProvider($oAccount)->GetContacts($oAccount,
|
||||
$mResult = $this->PersonalAddressBookProvider($oAccount)->GetContacts($oAccount->ParentEmailHelper(),
|
||||
$iOffset, $iLimit, $sSearch, $iCount);
|
||||
}
|
||||
|
||||
|
@ -4236,7 +4238,7 @@ class Actions
|
|||
$bResult = false;
|
||||
if (0 < \count($aFilteredUids) && $this->PersonalAddressBookProvider($oAccount)->IsActive())
|
||||
{
|
||||
$bResult = $this->PersonalAddressBookProvider($oAccount)->DeleteContacts($oAccount, $aFilteredUids);
|
||||
$bResult = $this->PersonalAddressBookProvider($oAccount)->DeleteContacts($oAccount->ParentEmailHelper(), $aFilteredUids);
|
||||
}
|
||||
|
||||
return $this->DefaultResponse(__FUNCTION__, $bResult);
|
||||
|
@ -4256,6 +4258,7 @@ class Actions
|
|||
if ($oPab && $oPab->IsActive() && 0 < \strlen($sRequestUid))
|
||||
{
|
||||
$sUid = \trim($this->GetActionParam('Uid', ''));
|
||||
$sUidStr = \trim($this->GetActionParam('UidStr', ''));
|
||||
$iScopeType = (int) $this->GetActionParam('ScopeType', null);
|
||||
if (!in_array($iScopeType, array(
|
||||
\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_,
|
||||
|
@ -4269,6 +4272,10 @@ class Actions
|
|||
{
|
||||
$oContact->IdContact = $sUid;
|
||||
}
|
||||
if (0 < \strlen($sUidStr))
|
||||
{
|
||||
$oContact->IdContactStr = $sUidStr;
|
||||
}
|
||||
|
||||
$oContact->ScopeType = $iScopeType;
|
||||
|
||||
|
@ -4290,12 +4297,13 @@ class Actions
|
|||
}
|
||||
}
|
||||
|
||||
$bResult = $oPab->ContactSave($oAccount, $oContact);
|
||||
$bResult = $oPab->ContactSave($oAccount->ParentEmailHelper(), $oContact);
|
||||
}
|
||||
|
||||
return $this->DefaultResponse(__FUNCTION__, array(
|
||||
'RequestUid' => $sRequestUid,
|
||||
'ResultID' => $bResult ? $oContact->IdContact : '',
|
||||
'ResultIDStr' => $bResult ? $oContact->IdContactStr : '',
|
||||
'Result' => $bResult
|
||||
));
|
||||
}
|
||||
|
@ -4328,7 +4336,7 @@ class Actions
|
|||
$oPab = $this->PersonalAddressBookProvider($oAccount);
|
||||
if ($oPab && $oPab->IsActive())
|
||||
{
|
||||
$aSuggestions = $oPab->GetSuggestions($oAccount, $sQuery, $iLimit);
|
||||
$aSuggestions = $oPab->GetSuggestions($oAccount->ParentEmailHelper(), $sQuery, $iLimit);
|
||||
if (0 === \count($aResult))
|
||||
{
|
||||
$aResult = $aSuggestions;
|
||||
|
@ -5938,6 +5946,7 @@ class Actions
|
|||
$mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
|
||||
/* @var $mResponse \RainLoop\Providers\PersonalAddressBook\Classes\Contact */
|
||||
'IdContact' => $mResponse->IdContact,
|
||||
'IdContactStr' => $mResponse->IdContactStr,
|
||||
'Display' => \MailSo\Base\Utils::Utf8Clear($mResponse->Display),
|
||||
'ReadOnly' => $mResponse->ReadOnly,
|
||||
'ScopeType' => $mResponse->ScopeType,
|
||||
|
|
|
@ -229,12 +229,18 @@ abstract class PdoAbstract
|
|||
/**
|
||||
* @param string $sEmail
|
||||
* @param bool $bSkipInsert = false
|
||||
* @param bool $bSkipUpdateTables = false
|
||||
* @param bool $bCache = true
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function getUserId($sEmail, $bSkipInsert = false)
|
||||
protected function getUserId($sEmail, $bSkipInsert = false, $bCache = true)
|
||||
{
|
||||
static $aCache = array();
|
||||
if ($bCache && isset($aCache[$sEmail]))
|
||||
{
|
||||
return $aCache[$sEmail];
|
||||
}
|
||||
|
||||
$sEmail = \strtolower(\trim($sEmail));
|
||||
if (empty($sEmail))
|
||||
{
|
||||
|
@ -242,20 +248,38 @@ abstract class PdoAbstract
|
|||
}
|
||||
|
||||
$oStmt = $this->prepareAndExecute('SELECT id_user FROM rainloop_users WHERE rl_email = :rl_email',
|
||||
array(':rl_email' => array($sEmail, \PDO::PARAM_STR)));
|
||||
array(
|
||||
':rl_email' => array($sEmail, \PDO::PARAM_STR)
|
||||
)
|
||||
);
|
||||
|
||||
$mRow = $oStmt->fetch(\PDO::FETCH_ASSOC);
|
||||
if ($mRow && isset($mRow['id_user']) && \is_numeric($mRow['id_user']))
|
||||
{
|
||||
return (int) $mRow['id_user'];
|
||||
$iResult = (int) $mRow['id_user'];
|
||||
if (0 >= $iResult)
|
||||
{
|
||||
throw new \Exception('id_user <= 0');
|
||||
}
|
||||
|
||||
if ($bCache)
|
||||
{
|
||||
$aCache[$sEmail] = $iResult;
|
||||
}
|
||||
|
||||
return $iResult;
|
||||
}
|
||||
|
||||
if (!$bSkipInsert)
|
||||
{
|
||||
$oStmt->closeCursor();
|
||||
|
||||
$oStmt = $this->prepareAndExecute('INSERT INTO rainloop_users (rl_email) VALUES (:rl_email)',
|
||||
array(':rl_email' => array($sEmail, \PDO::PARAM_STR)));
|
||||
$oStmt = $this->prepareAndExecute('INSERT INTO rainloop_users (rl_email, rl_hash) VALUES (:rl_email, :rl_hash)',
|
||||
array(
|
||||
':rl_email' => array($sEmail, \PDO::PARAM_STR),
|
||||
':rl_hash' => array(\md5($sEmail.\microtime(true)), \PDO::PARAM_STR)
|
||||
)
|
||||
);
|
||||
|
||||
return $this->getUserId($sEmail, true);
|
||||
}
|
||||
|
@ -374,6 +398,8 @@ abstract class PdoAbstract
|
|||
}
|
||||
|
||||
/**
|
||||
* @param bool $bWatchVersion = true
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function initSystemTables()
|
||||
|
@ -384,55 +410,51 @@ abstract class PdoAbstract
|
|||
if ($oPdo)
|
||||
{
|
||||
$aQ = array();
|
||||
if ('mysql' === $this->sDbType)
|
||||
switch ($this->sDbType)
|
||||
{
|
||||
$aQ[] = 'CREATE TABLE IF NOT EXISTS rainloop_system (
|
||||
sys_name varchar(50) NOT NULL,
|
||||
value_int int UNSIGNED NOT NULL DEFAULT 0,
|
||||
value_str varchar(128) NOT NULL DEFAULT \'\',
|
||||
INDEX sys_name_rainloop_system_index (sys_name)
|
||||
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;';
|
||||
|
||||
$aQ[] = 'CREATE TABLE IF NOT EXISTS rainloop_users (
|
||||
id_user int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
rl_email varchar(128) NOT NULL DEFAULT \'\',
|
||||
PRIMARY KEY(id_user),
|
||||
INDEX rl_email_rainloop_users_index (rl_email)
|
||||
case 'mysql':
|
||||
$aQ[] = 'CREATE TABLE IF NOT EXISTS rainloop_system (
|
||||
sys_name varchar(50) NOT NULL,
|
||||
value_int int UNSIGNED NOT NULL DEFAULT 0,
|
||||
value_str varchar(128) NOT NULL DEFAULT \'\',
|
||||
INDEX sys_name_rainloop_system_index (sys_name)
|
||||
) /*!40000 ENGINE=INNODB *//*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;';
|
||||
$aQ[] = 'CREATE TABLE IF NOT EXISTS rainloop_users (
|
||||
id_user int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
rl_email varchar(128) NOT NULL DEFAULT \'\',
|
||||
PRIMARY KEY(id_user),
|
||||
INDEX rl_email_rainloop_users_index (rl_email)
|
||||
) /*!40000 ENGINE=INNODB */;';
|
||||
}
|
||||
else if ('pgsql' === $this->sDbType)
|
||||
{
|
||||
$aQ[] = 'CREATE TABLE rainloop_system (
|
||||
sys_name varchar(50) NOT NULL,
|
||||
value_int integer NOT NULL DEFAULT 0,
|
||||
value_str varchar(128) NOT NULL DEFAULT \'\'
|
||||
);';
|
||||
break;
|
||||
|
||||
$aQ[] = 'CREATE INDEX sys_name_rainloop_system_index ON rainloop_system (sys_name);';
|
||||
|
||||
$aQ[] = 'CREATE SEQUENCE id_user START WITH 1 INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1;';
|
||||
|
||||
$aQ[] = 'CREATE TABLE rainloop_users (
|
||||
id_user integer DEFAULT nextval(\'id_user\'::text) PRIMARY KEY,
|
||||
rl_email varchar(128) NOT NULL DEFAULT \'\'
|
||||
case 'pgsql':
|
||||
$aQ[] = 'CREATE TABLE rainloop_system (
|
||||
sys_name varchar(50) NOT NULL,
|
||||
value_int integer NOT NULL DEFAULT 0,
|
||||
value_str varchar(128) NOT NULL DEFAULT \'\'
|
||||
);';
|
||||
$aQ[] = 'CREATE INDEX rl_email_rainloop_users_index ON rainloop_users (rl_email);';
|
||||
}
|
||||
else if ('sqlite' === $this->sDbType)
|
||||
{
|
||||
$aQ[] = 'CREATE TABLE rainloop_system (
|
||||
sys_name text NOT NULL,
|
||||
value_int integer NOT NULL default 0,
|
||||
value_str text NOT NULL default \'\'
|
||||
$aQ[] = 'CREATE INDEX sys_name_rainloop_system_index ON rainloop_system (sys_name);';
|
||||
$aQ[] = 'CREATE SEQUENCE id_user START WITH 1 INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1;';
|
||||
$aQ[] = 'CREATE TABLE rainloop_users (
|
||||
id_user integer DEFAULT nextval(\'id_user\'::text) PRIMARY KEY,
|
||||
rl_email varchar(128) NOT NULL DEFAULT \'\'
|
||||
);';
|
||||
$aQ[] = 'CREATE INDEX rl_email_rainloop_users_index ON rainloop_users (rl_email);';
|
||||
break;
|
||||
|
||||
$aQ[] = 'CREATE INDEX sys_name_rainloop_system_index ON rainloop_system (sys_name);';
|
||||
|
||||
$aQ[] = 'CREATE TABLE rainloop_users (
|
||||
id_user integer NOT NULL PRIMARY KEY,
|
||||
rl_email text NOT NULL default \'\'
|
||||
case 'sqlite':
|
||||
$aQ[] = 'CREATE TABLE rainloop_system (
|
||||
sys_name text NOT NULL,
|
||||
value_int integer NOT NULL DEFAULT 0,
|
||||
value_str text NOT NULL DEFAULT \'\'
|
||||
);';
|
||||
$aQ[] = 'CREATE INDEX rl_email_rainloop_users_index ON rainloop_users (rl_email);';
|
||||
$aQ[] = 'CREATE INDEX sys_name_rainloop_system_index ON rainloop_system (sys_name);';
|
||||
$aQ[] = 'CREATE TABLE rainloop_users (
|
||||
id_user integer NOT NULL PRIMARY KEY,
|
||||
rl_email text NOT NULL DEFAULT \'\'
|
||||
);';
|
||||
$aQ[] = 'CREATE INDEX rl_email_rainloop_users_index ON rainloop_users (rl_email);';
|
||||
break;
|
||||
}
|
||||
|
||||
if (0 < \count($aQ))
|
||||
|
|
|
@ -84,6 +84,7 @@ class Application extends \RainLoop\Config\AbstractConfig
|
|||
'contacts' => array(
|
||||
'enable' => array(false, 'Enable contacts'),
|
||||
'allow_sharing' => array(true),
|
||||
'allow_carddav_sync' => array(false),
|
||||
'suggestions_limit' => array(30),
|
||||
'type' => array('sqlite', ''),
|
||||
'pdo_dsn' => array('mysql:host=127.0.0.1;port=3306;dbname=rainloop', ''),
|
||||
|
|
|
@ -67,8 +67,20 @@ class PersonalAddressBook extends \RainLoop\Providers\AbstractProvider
|
|||
*/
|
||||
public function GetUserUidByEmail($sEmail)
|
||||
{
|
||||
return $this->oDriver instanceof \RainLoop\Providers\PersonalAddressBook\PersonalAddressBookInterface &&
|
||||
$this->oDriver->GetUserUidByEmail($sEmail);
|
||||
return $this->oDriver instanceof \RainLoop\Providers\PersonalAddressBook\PersonalAddressBookInterface ?
|
||||
$this->oDriver->GetUserUidByEmail($sEmail) : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param bool $bCreate = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetUserHashByEmail($sEmail, $bCreate = false)
|
||||
{
|
||||
return $this->oDriver instanceof \RainLoop\Providers\PersonalAddressBook\PersonalAddressBookInterface ?
|
||||
$this->oDriver->GetUserHashByEmail($sEmail, $bCreate) : '';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -121,6 +133,18 @@ class PersonalAddressBook extends \RainLoop\Providers\AbstractProvider
|
|||
$iOffset, $iLimit, $sSearch, $iResultCount) : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param string $sID
|
||||
* @param bool $bIsStrID = false
|
||||
*
|
||||
* @return \RainLoop\Providers\PersonalAddressBook\Classes\Contact|null
|
||||
*/
|
||||
public function GetContactByID($sEmail, $mID, $bIsStrID = false)
|
||||
{
|
||||
return $this->IsActive() ? $this->oDriver->GetContactByID($sEmail, $mID, $bIsStrID) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param string $sSearch
|
||||
|
|
|
@ -11,6 +11,11 @@ class Contact
|
|||
*/
|
||||
public $IdContact;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $IdContactStr;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
|
@ -59,6 +64,7 @@ class Contact
|
|||
public function Clear()
|
||||
{
|
||||
$this->IdContact = '';
|
||||
$this->IdContactStr = '';
|
||||
$this->IdUser = 0;
|
||||
$this->Display = '';
|
||||
$this->DisplayName = '';
|
||||
|
@ -95,6 +101,11 @@ class Contact
|
|||
}
|
||||
}
|
||||
|
||||
if (empty($this->IdContactStr))
|
||||
{
|
||||
$this->IdContactStr = \Sabre\DAV\UUIDUtil::getUUID();
|
||||
}
|
||||
|
||||
$this->DisplayName = $sDisplayName;
|
||||
$this->DisplayEmail = $sDisplayEmail;
|
||||
|
||||
|
@ -123,6 +134,8 @@ class Contact
|
|||
*/
|
||||
public function ToVCardObject()
|
||||
{
|
||||
$this->UpdateDependentValues();
|
||||
|
||||
$oVCard = new \Sabre\VObject\Component\VCard('VCARD');
|
||||
|
||||
$oVCard->VERSION = '3.0';
|
||||
|
@ -141,6 +154,32 @@ class Contact
|
|||
case PropertyType::NICK:
|
||||
$oVCard->NICKNAME = $oProperty->Value;
|
||||
break;
|
||||
case PropertyType::EMAIl_PERSONAL:
|
||||
case PropertyType::EMAIl_OTHER:
|
||||
$oVCard->add('EMAIL', $oProperty->Value, array('TYPE' => 'INTERNET', 'TYPE' => 'HOME'));
|
||||
break;
|
||||
case PropertyType::EMAIl_BUSSINES:
|
||||
$oVCard->add('EMAIL', $oProperty->Value, array('TYPE' => 'INTERNET', 'TYPE' => 'WORK'));
|
||||
break;
|
||||
case PropertyType::PHONE_PERSONAL:
|
||||
case PropertyType::PHONE_OTHER:
|
||||
$oVCard->add('TEL', $oProperty->Value, array('TYPE' => 'VOICE', 'TYPE' => 'HOME'));
|
||||
break;
|
||||
case PropertyType::PHONE_BUSSINES:
|
||||
$oVCard->add('TEL', $oProperty->Value, array('TYPE' => 'VOICE', 'TYPE' => 'WORK'));
|
||||
break;
|
||||
case PropertyType::MOBILE_PERSONAL:
|
||||
case PropertyType::MOBILE_BUSSINES:
|
||||
case PropertyType::MOBILE_OTHER:
|
||||
$oVCard->add('TEL', $oProperty->Value, array('TYPE' => 'VOICE', 'TYPE' => 'CELL'));
|
||||
break;
|
||||
case PropertyType::FAX_PERSONAL:
|
||||
case PropertyType::FAX_OTHER:
|
||||
$oVCard->add('TEL', $oProperty->Value, array('TYPE' => 'FAX', 'TYPE' => 'HOME'));
|
||||
break;
|
||||
case PropertyType::FAX_BUSSINES:
|
||||
$oVCard->add('TEL', $oProperty->Value, array('TYPE' => 'FAX', 'TYPE' => 'WORK'));
|
||||
break;
|
||||
case PropertyType::FIRST_NAME:
|
||||
$sFirstName = $oProperty->Value;
|
||||
break;
|
||||
|
@ -148,15 +187,10 @@ class Contact
|
|||
$sSurName = $oProperty->Value;
|
||||
break;
|
||||
}
|
||||
|
||||
if (PropertyType::FULLNAME === $oProperty->Type)
|
||||
{
|
||||
$oVCard->FN = $oProperty->Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$oVCard->UID = ((string) $this->IdContact).'.vcf';
|
||||
$oVCard->UID = $this->VCardUID();
|
||||
|
||||
// $oVCard->N = array(
|
||||
// $sSurName,
|
||||
|
@ -169,4 +203,14 @@ class Contact
|
|||
|
||||
return $oVCard;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function VCardUID()
|
||||
{
|
||||
return $this->IdContactStr.'.vcf';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -93,15 +93,54 @@ class PdoPersonalAddressBook
|
|||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param string $sEmail
|
||||
* @param bool $bCreate = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetUserHashByEmail($sEmail, $bCreate = false)
|
||||
{
|
||||
$sHash = '';
|
||||
$iUserID = $this->getUserId($sEmail);
|
||||
if (0 < $iUserID)
|
||||
{
|
||||
$oStmt = $this->prepareAndExecute('SELECT pass_hash FROM rainloop_pab_users_hashes WHERE id_user = :id_user LIMIT 1',
|
||||
array(':id_user' => array($iUserID, \PDO::PARAM_INT)));
|
||||
|
||||
if ($oStmt)
|
||||
{
|
||||
$aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
if ($aFetch && !empty($aFetch[0]['pass_hash']))
|
||||
{
|
||||
$sHash = \rtrim(\base_convert(\md5(\md5($sEmail.'-'.\trim($aFetch[0]['pass_hash']).'-rainloop')), 16, 32), '0');
|
||||
}
|
||||
else if ($bCreate)
|
||||
{
|
||||
$this->prepareAndExecute('INSERT INTO rainloop_pab_users_hashes (id_user, pass_hash) VALUES (:id_user, :pass_hash);',
|
||||
array(
|
||||
':id_user' => array($iUserID, \PDO::PARAM_INT),
|
||||
':pass_hash' => array(\md5($sEmail.\microtime(true)), \PDO::PARAM_STR)
|
||||
)
|
||||
);
|
||||
|
||||
$this->GetUserHashByEmail($sEmail, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $sHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param \RainLoop\Providers\PersonalAddressBook\Classes\Contact $oContact
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function ContactSave($oAccount, &$oContact)
|
||||
public function ContactSave($sEmail, &$oContact)
|
||||
{
|
||||
$this->Sync();
|
||||
$iUserID = $this->getUserId($oAccount->ParentEmailHelper());
|
||||
$iUserID = $this->getUserId($sEmail);
|
||||
|
||||
$iIdContact = \strlen($oContact->IdContact) && \is_numeric($oContact->IdContact) ? (int) $oContact->IdContact : 0;
|
||||
|
||||
|
@ -127,13 +166,14 @@ class PdoPersonalAddressBook
|
|||
{
|
||||
$aFreq = $this->getContactFreq($iUserID, $iIdContact);
|
||||
|
||||
$sSql = 'UPDATE rainloop_pab_contacts SET display = :display, display_name = :display_name, display_email = :display_email, '.
|
||||
$sSql = 'UPDATE rainloop_pab_contacts SET id_contact_str = :id_contact_str, display = :display, display_name = :display_name, display_email = :display_email, '.
|
||||
'scope_type = :scope_type, changed = :changed WHERE id_user = :id_user AND id_contact = :id_contact';
|
||||
|
||||
$this->prepareAndExecute($sSql,
|
||||
array(
|
||||
':id_user' => array($iUserID, \PDO::PARAM_INT),
|
||||
':id_contact' => array($iIdContact, \PDO::PARAM_INT),
|
||||
':id_contact_str' => array($oContact->IdContactStr, \PDO::PARAM_STR),
|
||||
':display' => array($oContact->Display, \PDO::PARAM_STR),
|
||||
':display_name' => array($oContact->DisplayName, \PDO::PARAM_STR),
|
||||
':display_email' => array($oContact->DisplayEmail, \PDO::PARAM_STR),
|
||||
|
@ -154,12 +194,13 @@ class PdoPersonalAddressBook
|
|||
else
|
||||
{
|
||||
$sSql = 'INSERT INTO rainloop_pab_contacts '.
|
||||
'( id_user, display, display_name, display_email, scope_type, changed) VALUES '.
|
||||
'(:id_user, :display, :display_name, :display_email, :scope_type, :changed)';
|
||||
'( id_user, id_contact_str, display, display_name, display_email, scope_type, changed) VALUES '.
|
||||
'(:id_user, :id_contact_str, :display, :display_name, :display_email, :scope_type, :changed)';
|
||||
|
||||
$this->prepareAndExecute($sSql,
|
||||
array(
|
||||
':id_user' => array($iUserID, \PDO::PARAM_INT),
|
||||
':id_contact_str' => array($oContact->IdContactStr, \PDO::PARAM_STR),
|
||||
':display' => array($oContact->Display, \PDO::PARAM_STR),
|
||||
':display_name' => array($oContact->DisplayName, \PDO::PARAM_STR),
|
||||
':display_email' => array($oContact->DisplayEmail, \PDO::PARAM_STR),
|
||||
|
@ -225,14 +266,14 @@ class PdoPersonalAddressBook
|
|||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param string $sEmail
|
||||
* @param array $aContactIds
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function DeleteContacts($oAccount, $aContactIds)
|
||||
public function DeleteContacts($sEmail, $aContactIds)
|
||||
{
|
||||
$iUserID = $this->getUserId($oAccount->ParentEmailHelper());
|
||||
$iUserID = $this->getUserId($sEmail);
|
||||
|
||||
$aContactIds = \array_filter($aContactIds, function (&$mItem) {
|
||||
$mItem = (int) \trim($mItem);
|
||||
|
@ -255,15 +296,15 @@ class PdoPersonalAddressBook
|
|||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param string $sEmail
|
||||
* @param array $aTagsIds
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function DeleteTags($oAccount, $aTagsIds)
|
||||
public function DeleteTags($sEmail, $aTagsIds)
|
||||
{
|
||||
$this->Sync();
|
||||
$iUserID = $this->getUserId($oAccount->ParentEmailHelper());
|
||||
$iUserID = $this->getUserId($sEmail);
|
||||
|
||||
$aTagsIds = \array_filter($aTagsIds, function (&$mItem) {
|
||||
$mItem = (int) \trim($mItem);
|
||||
|
@ -285,7 +326,7 @@ class PdoPersonalAddressBook
|
|||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account|mixed $mAccountOrId
|
||||
* @param string $sEmail
|
||||
* @param int $iOffset = 0
|
||||
* @param int $iLimit = 20
|
||||
* @param string $sSearch = ''
|
||||
|
@ -293,7 +334,7 @@ class PdoPersonalAddressBook
|
|||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetContacts($mAccountOrId, $iOffset = 0, $iLimit = 20, $sSearch = '', &$iResultCount = 0)
|
||||
public function GetContacts($sEmail, $iOffset = 0, $iLimit = 20, $sSearch = '', &$iResultCount = 0)
|
||||
{
|
||||
$this->Sync();
|
||||
|
||||
|
@ -301,11 +342,7 @@ class PdoPersonalAddressBook
|
|||
$iLimit = 0 < $iLimit ? (int) $iLimit : 20;
|
||||
$sSearch = \trim($sSearch);
|
||||
|
||||
$iUserID = $mAccountOrId instanceof \RainLoop\Account ? $this->getUserId($mAccountOrId->ParentEmailHelper()) : (int) $mAccountOrId;
|
||||
if (0 === $iUserID)
|
||||
{
|
||||
throw new \InvalidArgumentException('Invalid Accoutn ID');
|
||||
}
|
||||
$iUserID = $this->getUserId($sEmail);
|
||||
|
||||
$iCount = 0;
|
||||
$aSearchIds = array();
|
||||
|
@ -428,6 +465,7 @@ class PdoPersonalAddressBook
|
|||
$oContact = new \RainLoop\Providers\PersonalAddressBook\Classes\Contact();
|
||||
|
||||
$oContact->IdContact = (string) $iIdContact;
|
||||
$oContact->IdContactStr = isset($aItem['id_contact_str']) ? (string) $aItem['id_contact_str'] : '';
|
||||
$oContact->Display = isset($aItem['display']) ? (string) $aItem['display'] : '';
|
||||
$oContact->DisplayName = isset($aItem['display_name']) ? (string) $aItem['display_name'] : '';
|
||||
$oContact->DisplayEmail = isset($aItem['display_email']) ? (string) $aItem['display_email'] : '';
|
||||
|
@ -498,7 +536,124 @@ class PdoPersonalAddressBook
|
|||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param string $sEmail
|
||||
* @param string $sID
|
||||
* @param bool $bIsStrID = false
|
||||
*
|
||||
* @return \RainLoop\Providers\PersonalAddressBook\Classes\Contact|null
|
||||
*/
|
||||
public function GetContactByID($sEmail, $mID, $bIsStrID = false)
|
||||
{
|
||||
$this->Sync();
|
||||
|
||||
$mID = \trim($mID);
|
||||
|
||||
$iUserID = $this->getUserId($sEmail);
|
||||
|
||||
$sSql = 'SELECT * FROM rainloop_pab_contacts '.
|
||||
'WHERE id_user = :id_user'.
|
||||
($this->bConsiderShare ? ' OR scope_type = :scope_type_share_all' : '')
|
||||
;
|
||||
|
||||
$aParams = array(
|
||||
':id_user' => array($iUserID, \PDO::PARAM_INT)
|
||||
);
|
||||
|
||||
if ($this->bConsiderShare)
|
||||
{
|
||||
$aParams[':scope_type_share_all'] = array(\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::SHARE_ALL, \PDO::PARAM_INT);
|
||||
}
|
||||
|
||||
if ($bIsStrID)
|
||||
{
|
||||
$sSql .= ' AND id_contact_str = :id_contact_str';
|
||||
$aParams[':id_contact_str'] = array($mID, \PDO::PARAM_STR);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sSql .= ' AND id_contact = :id_contact';
|
||||
$aParams[':id_contact'] = array($mID, \PDO::PARAM_INT);
|
||||
}
|
||||
|
||||
$sSql .= ' LIMIT 1';
|
||||
|
||||
$oContact = null;
|
||||
$iIdContact = 0;
|
||||
|
||||
$oStmt = $this->prepareAndExecute($sSql, $aParams);
|
||||
if ($oStmt)
|
||||
{
|
||||
$aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
if (\is_array($aFetch) && 0 < \count($aFetch))
|
||||
{
|
||||
foreach ($aFetch as $aItem)
|
||||
{
|
||||
$iIdContact = $aItem && isset($aItem['id_contact']) ? (int) $aItem['id_contact'] : 0;
|
||||
if (0 < $iIdContact)
|
||||
{
|
||||
$oContact = new \RainLoop\Providers\PersonalAddressBook\Classes\Contact();
|
||||
|
||||
$oContact->IdContact = (string) $iIdContact;
|
||||
$oContact->IdContactStr = isset($aItem['id_contact_str']) ? (string) $aItem['id_contact_str'] : '';
|
||||
$oContact->Display = isset($aItem['display']) ? (string) $aItem['display'] : '';
|
||||
$oContact->DisplayName = isset($aItem['display_name']) ? (string) $aItem['display_name'] : '';
|
||||
$oContact->DisplayEmail = isset($aItem['display_email']) ? (string) $aItem['display_email'] : '';
|
||||
$oContact->ScopeType = isset($aItem['scope_type']) ? (int) $aItem['scope_type'] :
|
||||
\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_;
|
||||
$oContact->Changed = isset($aItem['changed']) ? (int) $aItem['changed'] : 0;
|
||||
$oContact->ReadOnly = $iUserID !== (isset($aItem['id_user']) ? (int) $aItem['id_user'] : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unset($aFetch);
|
||||
|
||||
if (0 < $iIdContact && $oContact)
|
||||
{
|
||||
$oStmt->closeCursor();
|
||||
|
||||
$sSql = 'SELECT * FROM rainloop_pab_properties WHERE id_contact = '.$iIdContact;
|
||||
$oStmt = $this->prepareAndExecute($sSql);
|
||||
|
||||
if ($oStmt)
|
||||
{
|
||||
$aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
if (\is_array($aFetch) && 0 < \count($aFetch))
|
||||
{
|
||||
foreach ($aFetch as $aItem)
|
||||
{
|
||||
if ($aItem && isset($aItem['id_prop'], $aItem['id_contact'], $aItem['prop_type'], $aItem['prop_value']))
|
||||
{
|
||||
if ((string) $oContact->IdContact === (string) $aItem['id_contact'])
|
||||
{
|
||||
$oProperty = new \RainLoop\Providers\PersonalAddressBook\Classes\Property();
|
||||
$oProperty->IdProperty = (int) $aItem['id_prop'];
|
||||
$oProperty->ScopeType = isset($aItem['scope_type']) ? (int) $aItem['scope_type'] :
|
||||
\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_;
|
||||
$oProperty->Type = (int) $aItem['prop_type'];
|
||||
$oProperty->TypeCustom = isset($aItem['prop_type_custom']) ? (string) $aItem['prop_type_custom'] : '';
|
||||
$oProperty->Value = (string) $aItem['prop_value'];
|
||||
$oProperty->ValueCustom = isset($aItem['prop_value_custom']) ? (string) $aItem['prop_value_custom'] : '';
|
||||
$oProperty->Frec = isset($aItem['prop_frec']) ? (int) $aItem['prop_frec'] : 0;
|
||||
|
||||
$oContact->Properties[] = $oProperty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unset($aFetch);
|
||||
|
||||
$oContact->UpdateDependentValues();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $oContact;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param string $sSearch
|
||||
* @param int $iLimit = 20
|
||||
*
|
||||
|
@ -506,7 +661,7 @@ class PdoPersonalAddressBook
|
|||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function GetSuggestions($oAccount, $sSearch, $iLimit = 20)
|
||||
public function GetSuggestions($sEmail, $sSearch, $iLimit = 20)
|
||||
{
|
||||
$sSearch = \trim($sSearch);
|
||||
if (0 === \strlen($sSearch))
|
||||
|
@ -516,7 +671,7 @@ class PdoPersonalAddressBook
|
|||
|
||||
$this->Sync();
|
||||
|
||||
$iUserID = $this->getUserId($oAccount->ParentEmailHelper());
|
||||
$iUserID = $this->getUserId($sEmail);
|
||||
|
||||
$sTypes = implode(',', array(
|
||||
PropertyType::EMAIl_PERSONAL, PropertyType::EMAIl_BUSSINES, PropertyType::EMAIl_OTHER, PropertyType::FULLNAME
|
||||
|
@ -675,13 +830,13 @@ class PdoPersonalAddressBook
|
|||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param string $sEmail
|
||||
* @param array $aEmails
|
||||
* @param bool $bCreateAuto = true
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function IncFrec($oAccount, $aEmails, $bCreateAuto = true)
|
||||
public function IncFrec($sEmail, $aEmails, $bCreateAuto = true)
|
||||
{
|
||||
$self = $this;
|
||||
$aEmailsObjects = \array_map(function ($mItem) {
|
||||
|
@ -700,7 +855,7 @@ class PdoPersonalAddressBook
|
|||
}
|
||||
|
||||
$this->Sync();
|
||||
$iUserID = $this->getUserId($oAccount->ParentEmailHelper());
|
||||
$iUserID = $this->getUserId($sEmail);
|
||||
|
||||
$sTypes = \implode(',', array(
|
||||
PropertyType::EMAIl_PERSONAL, PropertyType::EMAIl_BUSSINES, PropertyType::EMAIl_OTHER
|
||||
|
@ -792,7 +947,7 @@ class PdoPersonalAddressBook
|
|||
|
||||
if (0 < \count($oContact->Properties))
|
||||
{
|
||||
$this->ContactSave($oAccount, $oContact);
|
||||
$this->ContactSave($sEmail, $oContact);
|
||||
}
|
||||
|
||||
$oContact->Clear();
|
||||
|
@ -975,11 +1130,11 @@ POSTGRESINITIAL;
|
|||
CREATE TABLE rainloop_pab_contacts (
|
||||
id_contact integer NOT NULL PRIMARY KEY,
|
||||
id_user integer NOT NULL,
|
||||
scope_type integer NOT NULL default 0,
|
||||
display_name text NOT NULL default '',
|
||||
display_email text NOT NULL default '',
|
||||
display text NOT NULL default '',
|
||||
changed integer NOT NULL default 0
|
||||
scope_type integer NOT NULL DEFAULT 0,
|
||||
display_name text NOT NULL DEFAULT '',
|
||||
display_email text NOT NULL DEFAULT '',
|
||||
display text NOT NULL DEFAULT '',
|
||||
changed integer NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE INDEX id_user_scope_type_rainloop_pab_contacts_index ON rainloop_pab_contacts (id_user, scope_type);
|
||||
|
@ -988,12 +1143,12 @@ CREATE TABLE rainloop_pab_properties (
|
|||
id_prop integer NOT NULL PRIMARY KEY,
|
||||
id_contact integer NOT NULL,
|
||||
id_user integer NOT NULL,
|
||||
scope_type integer NOT NULL default 0,
|
||||
scope_type integer NOT NULL DEFAULT 0,
|
||||
prop_type integer NOT NULL,
|
||||
prop_type_custom text NOT NULL default '',
|
||||
prop_value text NOT NULL default '',
|
||||
prop_value_custom text NOT NULL default '',
|
||||
prop_frec integer NOT NULL default 0
|
||||
prop_type_custom text NOT NULL DEFAULT '',
|
||||
prop_value text NOT NULL DEFAULT '',
|
||||
prop_value_custom text NOT NULL DEFAULT '',
|
||||
prop_frec integer NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE INDEX id_user_rainloop_pab_properties_index ON rainloop_pab_properties (id_user);
|
||||
|
@ -1045,15 +1200,36 @@ SQLITEINITIAL;
|
|||
{
|
||||
case 'mysql':
|
||||
return $this->dataBaseUpgrade($this->sDsnType.'-pab-version', array(
|
||||
1 => $this->getInitialTablesArray($this->sDsnType)
|
||||
1 => $this->getInitialTablesArray($this->sDsnType),
|
||||
2 => array(
|
||||
'ALTER TABLE rainloop_pab_contacts ADD id_contact_str varchar(128) NOT NULL DEFAULT \'\' AFTER id_contact;',
|
||||
'CREATE TABLE IF NOT EXISTS rainloop_pab_users_hashes (
|
||||
id_user int UNSIGNED NOT NULL,
|
||||
pass_hash varchar(128) NOT NULL
|
||||
)/*!40000 ENGINE=INNODB */;'
|
||||
)
|
||||
));
|
||||
case 'pgsql':
|
||||
return $this->dataBaseUpgrade($this->sDsnType.'-pab-version', array(
|
||||
1 => $this->getInitialTablesArray($this->sDsnType)
|
||||
1 => $this->getInitialTablesArray($this->sDsnType),
|
||||
2 => array(
|
||||
'ALTER TABLE rainloop_pab_contacts ADD id_contact_str varchar(128) NOT NULL DEFAULT \'\';',
|
||||
'CREATE TABLE rainloop_pab_users_hashes (
|
||||
id_user integer NOT NULL,
|
||||
pass_hash varchar(128) NOT NULL
|
||||
);'
|
||||
)
|
||||
));
|
||||
case 'sqlite':
|
||||
return $this->dataBaseUpgrade($this->sDsnType.'-pab-version', array(
|
||||
1 => $this->getInitialTablesArray($this->sDsnType)
|
||||
1 => $this->getInitialTablesArray($this->sDsnType),
|
||||
2 => array(
|
||||
'ALTER TABLE rainloop_pab_contacts ADD id_contact_str text NOT NULL DEFAULT \'\';',
|
||||
'CREATE TABLE rainloop_pab_users_hashes (
|
||||
id_user integer NOT NULL,
|
||||
pass_hash text NOT NULL
|
||||
);'
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
@ -10,31 +10,31 @@ interface PersonalAddressBookInterface
|
|||
public function IsSupported();
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param string $sEmail
|
||||
* @param \RainLoop\Providers\PersonalAddressBook\Classes\Contact $oContact
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function ContactSave($oAccount, &$oContact);
|
||||
public function ContactSave($sEmail, &$oContact);
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param string $sEmail
|
||||
* @param array $aContactIds
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function DeleteContacts($oAccount, $aContactIds);
|
||||
public function DeleteContacts($sEmail, $aContactIds);
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param string $sEmail
|
||||
* @param array $aTagsIds
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function DeleteTags($oAccount, $aTagsIds);
|
||||
public function DeleteTags($sEmail, $aTagsIds);
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account|mixed $mAccountOrId
|
||||
* @param string $sEmail
|
||||
* @param int $iOffset = 0
|
||||
* @param int $iLimit = 20
|
||||
* @param string $sSearch = ''
|
||||
|
@ -42,10 +42,10 @@ interface PersonalAddressBookInterface
|
|||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetContacts($mAccountOrId, $iOffset = 0, $iLimit = 20, $sSearch = '', &$iResultCount = 0);
|
||||
public function GetContacts($sEmail, $iOffset = 0, $iLimit = 20, $sSearch = '', &$iResultCount = 0);
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param string $sEmail
|
||||
* @param string $sSearch
|
||||
* @param int $iLimit = 20
|
||||
*
|
||||
|
@ -53,13 +53,13 @@ interface PersonalAddressBookInterface
|
|||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function GetSuggestions($oAccount, $sSearch, $iLimit = 20);
|
||||
public function GetSuggestions($sEmail, $sSearch, $iLimit = 20);
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param string $sEmail
|
||||
* @param array $aEmails
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function IncFrec($oAccount, $aEmails);
|
||||
public function IncFrec($sEmail, $aEmails);
|
||||
}
|
|
@ -1,31 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\SabreDAV;
|
||||
|
||||
class AuthBasic extends \Sabre\DAV\Auth\Backend\AbstractBasic
|
||||
{
|
||||
/**
|
||||
* @var \RainLoop\Providers\PersonalAddressBook
|
||||
*/
|
||||
private $oPersonalAddressBook;
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Providers\PersonalAddressBook $oPersonalAddressBook
|
||||
*/
|
||||
public function __construct($oPersonalAddressBook)
|
||||
{
|
||||
$this->oPersonalAddressBook = $oPersonalAddressBook;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sUserName
|
||||
* @param string $sPassword
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function validateUserPass($sUserName, $sPassword)
|
||||
{
|
||||
$this->currentUser = $sUserName;
|
||||
return true; // TODO
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
namespace RainLoop\SabreDAV;
|
||||
|
||||
class AuthBasic extends \Sabre\DAV\Auth\Backend\AbstractBasic
|
||||
{
|
||||
/**
|
||||
* @var \RainLoop\Providers\PersonalAddressBook
|
||||
*/
|
||||
private $oPersonalAddressBook;
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Providers\PersonalAddressBook $oPersonalAddressBook
|
||||
*/
|
||||
public function __construct($oPersonalAddressBook)
|
||||
{
|
||||
$this->oPersonalAddressBook = $oPersonalAddressBook;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sUserName
|
||||
* @param string $sPassword
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function validateUserPass($sUserName, $sPassword)
|
||||
{
|
||||
return $sPassword === $this->oPersonalAddressBook->GetUserHashByEmail($sUserName, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\SabreDAV;
|
||||
|
||||
class AuthBasic extends \Sabre\DAV\Auth\Backend\AbstractDigest
|
||||
{
|
||||
/**
|
||||
* @var \RainLoop\Providers\PersonalAddressBook
|
||||
*/
|
||||
private $oPersonalAddressBook;
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Providers\PersonalAddressBook $oPersonalAddressBook
|
||||
*/
|
||||
public function __construct($oPersonalAddressBook)
|
||||
{
|
||||
$this->oPersonalAddressBook = $oPersonalAddressBook;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getDigestHash($sRealm, $sUserName)
|
||||
{
|
||||
$this->currentUser = $sUserName;
|
||||
return true; // TODO
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
namespace RainLoop\SabreDAV;
|
||||
|
||||
class AuthDigest extends \Sabre\DAV\Auth\Backend\AbstractDigest
|
||||
{
|
||||
/**
|
||||
* @var \RainLoop\Providers\PersonalAddressBook
|
||||
*/
|
||||
private $oPersonalAddressBook;
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Providers\PersonalAddressBook $oPersonalAddressBook
|
||||
*/
|
||||
public function __construct($oPersonalAddressBook)
|
||||
{
|
||||
$this->oPersonalAddressBook = $oPersonalAddressBook;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sRealm
|
||||
* @param string $sUserName
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getDigestHash($sRealm, $sUserName)
|
||||
{
|
||||
$sHash = $this->oPersonalAddressBook->GetUserHashByEmail($sUserName, true);
|
||||
if (!empty($sHash))
|
||||
{
|
||||
$this->currentUser = $sUserName;
|
||||
return \md5($sUserName.':'.$sRealm.':'.$sHash);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,278 +1,333 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\SabreDAV;
|
||||
|
||||
class CardDAV implements \Sabre\CardDAV\Backend\BackendInterface {
|
||||
|
||||
/**
|
||||
* @var \RainLoop\Providers\PersonalAddressBook
|
||||
*/
|
||||
private $oPersonalAddressBook;
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Providers\PersonalAddressBook $oPersonalAddressBook
|
||||
*/
|
||||
public function __construct($oPersonalAddressBook)
|
||||
{
|
||||
$this->oPersonalAddressBook = $oPersonalAddressBook;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sPrincipalUri
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getEmailFromPrincipalUri($sPrincipalUri)
|
||||
{
|
||||
$sEmail = '';
|
||||
$aMatch = array();
|
||||
if (\preg_match('/\/?principals\/([^@\/]+@[^@\/]+)/i', $sPrincipalUri, $aMatch) && !empty($aMatch[1]))
|
||||
{
|
||||
$sEmail = \trim($aMatch[1]);
|
||||
}
|
||||
|
||||
return $sEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sPrincipalUri
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getCalendarID($sPrincipalUri)
|
||||
{
|
||||
$mUserId = (string) $this->oPersonalAddressBook->GetUserUidByEmail(
|
||||
$this->getEmailFromPrincipalUri($sPrincipalUri));
|
||||
|
||||
return !empty($mUserId) ? $mUserId : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of addressbooks for a specific user.
|
||||
*
|
||||
* @param string $sPrincipalUri
|
||||
* @return array
|
||||
*/
|
||||
public function getAddressBooksForUser($sPrincipalUri)
|
||||
{
|
||||
$mAddressBookID = $this->getCalendarID($sPrincipalUri);
|
||||
|
||||
$aAddressBooks = array();
|
||||
if (!empty($mAddressBookID))
|
||||
{
|
||||
$aAddressBooks[] = array(
|
||||
'id' => $mAddressBookID,
|
||||
'uri' => 'default',
|
||||
'principaluri' => $sPrincipalUri,
|
||||
'{DAV:}displayname' => 'Personal Address Book',
|
||||
'{'.\Sabre\CardDAV\Plugin::NS_CARDDAV.'}addressbook-description' => 'Personal Address Book',
|
||||
'{http://calendarserver.org/ns/}getctag' => 1,
|
||||
'{'.\Sabre\CardDAV\Plugin::NS_CARDDAV.'}supported-address-data' => new \Sabre\CardDAV\Property\SupportedAddressData()
|
||||
);
|
||||
}
|
||||
|
||||
return $aAddressBooks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an addressbook's properties
|
||||
*
|
||||
* See Sabre\DAV\IProperties for a description of the mutations array, as
|
||||
* well as the return value.
|
||||
*
|
||||
* @param mixed $mAddressBookId
|
||||
* @param array $aMutations
|
||||
* @see Sabre\DAV\IProperties::updateProperties
|
||||
* @return bool|array
|
||||
*/
|
||||
public function updateAddressBook($mAddressBookId, array $aMutations)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new address book
|
||||
*
|
||||
* @param string $sPrincipalUri
|
||||
* @param string $sUrl Just the 'basename' of the url.
|
||||
* @param array $aProperties
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function createAddressBook($sPrincipalUri, $sUrl, array $aProperties)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an entire addressbook and all its contents
|
||||
*
|
||||
* @param mixed $mAddressBookId
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deleteAddressBook($mAddressBookId)
|
||||
{
|
||||
}
|
||||
|
||||
private function simpleGetCards($mAddressBookId, $sCardUri = '')
|
||||
{
|
||||
$aResult = array();
|
||||
if (!empty($mAddressBookId))
|
||||
{
|
||||
$aList = $this->oPersonalAddressBook->GetContacts($mAddressBookId, 0, 20);
|
||||
foreach ($aList as /* @var $oItem \RainLoop\Providers\PersonalAddressBook\Classes\Contact */ $oItem)
|
||||
{
|
||||
$oVCard = $oItem->ToVCardObject();
|
||||
if ('' === $sCardUri || $sCardUri === $oVCard->UID)
|
||||
{
|
||||
$aResult[] = array(
|
||||
'id' => $oItem->IdContact,
|
||||
'uri' => $oVCard->UID,
|
||||
'lastmodified' => $oItem->Changed,
|
||||
'carddata' => $oVCard->serialize()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all cards for a specific addressbook id.
|
||||
*
|
||||
* This method should return the following properties for each card:
|
||||
* * carddata - raw vcard data
|
||||
* * uri - Some unique url
|
||||
* * lastmodified - A unix timestamp
|
||||
*
|
||||
* It's recommended to also return the following properties:
|
||||
* * etag - A unique etag. This must change every time the card changes.
|
||||
* * size - The size of the card in bytes.
|
||||
*
|
||||
* If these last two properties are provided, less time will be spent
|
||||
* calculating them. If they are specified, you can also ommit carddata.
|
||||
* This may speed up certain requests, especially with large cards.
|
||||
*
|
||||
* @param mixed $mAddressbookId
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCards($mAddressBookId)
|
||||
{
|
||||
return $this->simpleGetCards($mAddressBookId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a specfic card.
|
||||
*
|
||||
* The same set of properties must be returned as with getCards. The only
|
||||
* exception is that 'carddata' is absolutely required.
|
||||
*
|
||||
* @param mixed $mAddressBookId
|
||||
* @param string $sCardUri
|
||||
* @return array
|
||||
*/
|
||||
public function getCard($mAddressBookId, $sCardUri)
|
||||
{
|
||||
$aList = $this->simpleGetCards($mAddressBookId, $sCardUri);
|
||||
return 0 < count($aList) && isset($aList) ? $aList[0] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new card.
|
||||
*
|
||||
* The addressbook id will be passed as the first argument. This is the
|
||||
* same id as it is returned from the getAddressbooksForUser method.
|
||||
*
|
||||
* The cardUri is a base uri, and doesn't include the full path. The
|
||||
* cardData argument is the vcard body, and is passed as a string.
|
||||
*
|
||||
* It is possible to return an ETag from this method. This ETag is for the
|
||||
* newly created resource, and must be enclosed with double quotes (that
|
||||
* is, the string itself must contain the double quotes).
|
||||
*
|
||||
* You should only return the ETag if you store the carddata as-is. If a
|
||||
* subsequent GET request on the same card does not have the same body,
|
||||
* byte-by-byte and you did return an ETag here, clients tend to get
|
||||
* confused.
|
||||
*
|
||||
* If you don't return an ETag, you can just return null.
|
||||
*
|
||||
* @param mixed $mAddressBookId
|
||||
* @param string $sCardUri
|
||||
* @param string $sCardData
|
||||
* @return string|null
|
||||
*/
|
||||
public function createCard($mAddressBookId, $sCardUri, $sCardData)
|
||||
{
|
||||
return null;
|
||||
//
|
||||
// $stmt = $this->pdo->prepare('INSERT INTO ' . $this->cardsTableName . ' (carddata, uri, lastmodified, addressbookid) VALUES (?, ?, ?, ?)');
|
||||
//
|
||||
// $result = $stmt->execute(array($cardData, $cardUri, time(), $addressBookId));
|
||||
//
|
||||
// $stmt2 = $this->pdo->prepare('UPDATE ' . $this->addressBooksTableName . ' SET ctag = ctag + 1 WHERE id = ?');
|
||||
// $stmt2->execute(array($addressBookId));
|
||||
//
|
||||
// return '"' . md5($cardData) . '"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a card.
|
||||
*
|
||||
* The addressbook id will be passed as the first argument. This is the
|
||||
* same id as it is returned from the getAddressbooksForUser method.
|
||||
*
|
||||
* The cardUri is a base uri, and doesn't include the full path. The
|
||||
* cardData argument is the vcard body, and is passed as a string.
|
||||
*
|
||||
* It is possible to return an ETag from this method. This ETag should
|
||||
* match that of the updated resource, and must be enclosed with double
|
||||
* quotes (that is: the string itself must contain the actual quotes).
|
||||
*
|
||||
* You should only return the ETag if you store the carddata as-is. If a
|
||||
* subsequent GET request on the same card does not have the same body,
|
||||
* byte-by-byte and you did return an ETag here, clients tend to get
|
||||
* confused.
|
||||
*
|
||||
* If you don't return an ETag, you can just return null.
|
||||
*
|
||||
* @param mixed $mAddressBookId
|
||||
* @param string $sCardUri
|
||||
* @param string $sCardData
|
||||
* @return string|null
|
||||
*/
|
||||
public function updateCard($mAddressBookId, $sCardUri, $sCardData)
|
||||
{
|
||||
return null;
|
||||
|
||||
// $stmt = $this->pdo->prepare('UPDATE ' . $this->cardsTableName . ' SET carddata = ?, lastmodified = ? WHERE uri = ? AND addressbookid =?');
|
||||
// $stmt->execute(array($cardData, time(), $cardUri, $addressBookId));
|
||||
//
|
||||
// $stmt2 = $this->pdo->prepare('UPDATE ' . $this->addressBooksTableName . ' SET ctag = ctag + 1 WHERE id = ?');
|
||||
// $stmt2->execute(array($addressBookId));
|
||||
//
|
||||
// return '"' . md5($cardData) . '"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a card
|
||||
*
|
||||
* @param mixed $mAddressBookId
|
||||
* @param string $sCardUri
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteCard($mAddressBookId, $sCardUri)
|
||||
{
|
||||
return false;
|
||||
// $stmt = $this->pdo->prepare('DELETE FROM ' . $this->cardsTableName . ' WHERE addressbookid = ? AND uri = ?');
|
||||
// $stmt->execute(array($addressBookId, $cardUri));
|
||||
//
|
||||
// $stmt2 = $this->pdo->prepare('UPDATE ' . $this->addressBooksTableName . ' SET ctag = ctag + 1 WHERE id = ?');
|
||||
// $stmt2->execute(array($addressBookId));
|
||||
//
|
||||
// return $stmt->rowCount()===1;
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
namespace RainLoop\SabreDAV;
|
||||
|
||||
class CardDAV implements \Sabre\CardDAV\Backend\BackendInterface
|
||||
{
|
||||
/**
|
||||
* @var \RainLoop\Providers\PersonalAddressBook
|
||||
*/
|
||||
private $oPersonalAddressBook;
|
||||
|
||||
/**
|
||||
* @var \RainLoop\SabreDAV\AuthBasic
|
||||
*/
|
||||
private $oAuthBackend;
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Providers\PersonalAddressBook $oPersonalAddressBook
|
||||
* @param \RainLoop\SabreDAV\AuthBasic $oAuthBackend
|
||||
*/
|
||||
public function __construct($oPersonalAddressBook, &$oAuthBackend)
|
||||
{
|
||||
$this->oPersonalAddressBook = $oPersonalAddressBook;
|
||||
$this->oPersonalAddressBook->ConsiderShare(false);
|
||||
$this->oAuthBackend = $oAuthBackend;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sPrincipalUri
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getEmailFromPrincipalUri($sPrincipalUri)
|
||||
{
|
||||
$sEmail = '';
|
||||
$aMatch = array();
|
||||
if (\preg_match('/\/?principals\/([^@\/]+@[^@\/]+)/i', $sPrincipalUri, $aMatch) && !empty($aMatch[1]))
|
||||
{
|
||||
$sEmail = \trim($aMatch[1]);
|
||||
}
|
||||
|
||||
return $sEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sPrincipalUri = ''
|
||||
* @param string $mAddressBookID = ''
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getAuthEmail($sPrincipalUri = '', $mAddressBookID = '')
|
||||
{
|
||||
$sGetCurrentUser = \trim($this->oAuthBackend->getCurrentUser());
|
||||
if (0 < \strlen($sPrincipalUri) && 0 < \strlen($sGetCurrentUser) &&
|
||||
$sGetCurrentUser !== $this->getEmailFromPrincipalUri($sPrincipalUri))
|
||||
{
|
||||
$sGetCurrentUser = '';
|
||||
}
|
||||
|
||||
if (0 < \strlen((string) $mAddressBookID) && 0 < \strlen($sGetCurrentUser) &&
|
||||
(string) $mAddressBookID !== (string) $this->oPersonalAddressBook->GetUserUidByEmail($sGetCurrentUser))
|
||||
{
|
||||
$sGetCurrentUser = '';
|
||||
}
|
||||
|
||||
return $sGetCurrentUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of addressbooks for a specific user.
|
||||
*
|
||||
* @param string $sPrincipalUri
|
||||
* @return array
|
||||
*/
|
||||
public function getAddressBooksForUser($sPrincipalUri)
|
||||
{
|
||||
$aAddressBooks = array();
|
||||
|
||||
$sEmail = $this->getAuthEmail($sPrincipalUri);
|
||||
if (0 < strlen($sEmail))
|
||||
{
|
||||
$mAddressBookID = $this->oPersonalAddressBook->GetUserUidByEmail($sEmail);
|
||||
if (!empty($mAddressBookID))
|
||||
{
|
||||
$aAddressBooks[] = array(
|
||||
'id' => $mAddressBookID,
|
||||
'uri' => 'default',
|
||||
'principaluri' => $sPrincipalUri,
|
||||
'{DAV:}displayname' => 'Personal Address Book',
|
||||
'{'.\Sabre\CardDAV\Plugin::NS_CARDDAV.'}addressbook-description' => 'Personal Address Book',
|
||||
'{http://calendarserver.org/ns/}getctag' => 1,
|
||||
'{'.\Sabre\CardDAV\Plugin::NS_CARDDAV.'}supported-address-data' => new \Sabre\CardDAV\Property\SupportedAddressData()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $aAddressBooks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an addressbook's properties
|
||||
*
|
||||
* See Sabre\DAV\IProperties for a description of the mutations array, as
|
||||
* well as the return value.
|
||||
*
|
||||
* @param mixed $mAddressBookId
|
||||
* @param array $aMutations
|
||||
* @see Sabre\DAV\IProperties::updateProperties
|
||||
* @return bool|array
|
||||
*/
|
||||
public function updateAddressBook($mAddressBookID, array $aMutations)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new address book
|
||||
*
|
||||
* @param string $sPrincipalUri
|
||||
* @param string $sUrl Just the 'basename' of the url.
|
||||
* @param array $aProperties
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function createAddressBook($sPrincipalUri, $sUrl, array $aProperties)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an entire addressbook and all its contents
|
||||
*
|
||||
* @param mixed $mAddressBookID
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deleteAddressBook($mAddressBookID)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all cards for a specific addressbook id.
|
||||
*
|
||||
* This method should return the following properties for each card:
|
||||
* * carddata - raw vcard data
|
||||
* * uri - Some unique url
|
||||
* * lastmodified - A unix timestamp
|
||||
*
|
||||
* It's recommended to also return the following properties:
|
||||
* * etag - A unique etag. This must change every time the card changes.
|
||||
* * size - The size of the card in bytes.
|
||||
*
|
||||
* If these last two properties are provided, less time will be spent
|
||||
* calculating them. If they are specified, you can also ommit carddata.
|
||||
* This may speed up certain requests, especially with large cards.
|
||||
*
|
||||
* @param mixed $mAddressBookID
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCards($mAddressBookID)
|
||||
{
|
||||
$aResult = array();
|
||||
if (!empty($mAddressBookID))
|
||||
{
|
||||
$sEmail = $this->getAuthEmail('', $mAddressBookID);
|
||||
if (!empty($sEmail))
|
||||
{
|
||||
$aList = $this->oPersonalAddressBook->GetContacts($sEmail, 0, 500);
|
||||
foreach ($aList as /* @var $oItem \RainLoop\Providers\PersonalAddressBook\Classes\Contact */ $oItem)
|
||||
{
|
||||
if (!$oItem->ReadOnly)
|
||||
{
|
||||
$sCardData = $oItem->ToVCardObject()->serialize();
|
||||
$aResult[] = array(
|
||||
'uri' => $oItem->VCardUID(),
|
||||
'lastmodified' => $oItem->Changed,
|
||||
'etag' => \md5($sCardData),
|
||||
'size' => \strlen($sCardData)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a specfic card.
|
||||
*
|
||||
* The same set of properties must be returned as with getCards. The only
|
||||
* exception is that 'carddata' is absolutely required.
|
||||
*
|
||||
* @param mixed $mAddressBookID
|
||||
* @param string $sCardUri
|
||||
* @return array
|
||||
*/
|
||||
public function getCard($mAddressBookID, $sCardUri)
|
||||
{
|
||||
$oContact = null;
|
||||
if (!empty($mAddressBookID) && !empty($sCardUri) && '.vcf' === \substr($sCardUri, -4))
|
||||
{
|
||||
$sEmail = $this->getAuthEmail('', $mAddressBookID);
|
||||
if (!empty($sEmail))
|
||||
{
|
||||
$oContact = $this->oPersonalAddressBook->GetContactByID($sEmail, \substr($sCardUri, 0, -4), true);
|
||||
}
|
||||
}
|
||||
|
||||
if ($oContact)
|
||||
{
|
||||
$sCardData = $oContact->ToVCardObject()->serialize();
|
||||
return array(
|
||||
'uri' => $oContact->VCardUID(),
|
||||
'lastmodified' => $oContact->Changed,
|
||||
'etag' => \md5($sCardData),
|
||||
'size' => \strlen($sCardData),
|
||||
'carddata' => $sCardData
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new card.
|
||||
*
|
||||
* The addressbook id will be passed as the first argument. This is the
|
||||
* same id as it is returned from the getAddressbooksForUser method.
|
||||
*
|
||||
* The cardUri is a base uri, and doesn't include the full path. The
|
||||
* cardData argument is the vcard body, and is passed as a string.
|
||||
*
|
||||
* It is possible to return an ETag from this method. This ETag is for the
|
||||
* newly created resource, and must be enclosed with double quotes (that
|
||||
* is, the string itself must contain the double quotes).
|
||||
*
|
||||
* You should only return the ETag if you store the carddata as-is. If a
|
||||
* subsequent GET request on the same card does not have the same body,
|
||||
* byte-by-byte and you did return an ETag here, clients tend to get
|
||||
* confused.
|
||||
*
|
||||
* If you don't return an ETag, you can just return null.
|
||||
*
|
||||
* @param mixed $mAddressBookID
|
||||
* @param string $sCardUri
|
||||
* @param string $sCardData
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function createCard($mAddressBookID, $sCardUri, $sCardData)
|
||||
{
|
||||
if (!empty($mAddressBookID) && !empty($sCardUri) && '.vcf' === \substr($sCardUri, -4) && 0 < \strlen($sCardData))
|
||||
{
|
||||
$sEmail = $this->getAuthEmail('', $mAddressBookID);
|
||||
if (!empty($sEmail))
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a card.
|
||||
*
|
||||
* The addressbook id will be passed as the first argument. This is the
|
||||
* same id as it is returned from the getAddressbooksForUser method.
|
||||
*
|
||||
* The cardUri is a base uri, and doesn't include the full path. The
|
||||
* cardData argument is the vcard body, and is passed as a string.
|
||||
*
|
||||
* It is possible to return an ETag from this method. This ETag should
|
||||
* match that of the updated resource, and must be enclosed with double
|
||||
* quotes (that is: the string itself must contain the actual quotes).
|
||||
*
|
||||
* You should only return the ETag if you store the carddata as-is. If a
|
||||
* subsequent GET request on the same card does not have the same body,
|
||||
* byte-by-byte and you did return an ETag here, clients tend to get
|
||||
* confused.
|
||||
*
|
||||
* If you don't return an ETag, you can just return null.
|
||||
*
|
||||
* @param mixed $mAddressBookID
|
||||
* @param string $sCardUri
|
||||
* @param string $sCardData
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function updateCard($mAddressBookID, $sCardUri, $sCardData)
|
||||
{
|
||||
if (!empty($mAddressBookID) && !empty($sCardUri) && '.vcf' === \substr($sCardUri, -4) && 0 < \strlen($sCardData))
|
||||
{
|
||||
$sEmail = $this->getAuthEmail('', $mAddressBookID);
|
||||
if (!empty($sEmail))
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a card
|
||||
*
|
||||
* @param mixed $mAddressBookID
|
||||
* @param string $sCardUri
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteCard($mAddressBookID, $sCardUri)
|
||||
{
|
||||
$bResult = false;
|
||||
$oContact = null;
|
||||
if (!empty($mAddressBookID) && !empty($sCardUri) && '.vcf' === \substr($sCardUri, -4))
|
||||
{
|
||||
$sEmail = $this->getAuthEmail('', $mAddressBookID);
|
||||
if (!empty($sEmail))
|
||||
{
|
||||
$oContact = $this->oPersonalAddressBook->GetContactByID($sEmail, \substr($sCardUri, 0, -4), true);
|
||||
}
|
||||
}
|
||||
|
||||
if ($oContact)
|
||||
{
|
||||
$bResult = $this->oPersonalAddressBook->DeleteContacts($sEmail, array($oContact->IdContact));
|
||||
}
|
||||
|
||||
return $bResult;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,7 +72,6 @@ class Principal extends \Sabre\DAVACL\PrincipalBackend\AbstractBackend
|
|||
$sGetCurrentUser = $this->oAuthBackend->getCurrentUser();
|
||||
if ('principals/'.$sGetCurrentUser === $sPath)
|
||||
{
|
||||
// var_dump($sPath);
|
||||
return array(
|
||||
'uri' => 'principals/'.$sGetCurrentUser,
|
||||
'{DAV:}displayname' => $sGetCurrentUser,
|
||||
|
@ -133,7 +132,7 @@ class Principal extends \Sabre\DAVACL\PrincipalBackend\AbstractBackend
|
|||
*/
|
||||
function updatePrincipal($path, $mutations)
|
||||
{
|
||||
return array();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -103,6 +103,14 @@ class Service
|
|||
$bCached = false;
|
||||
$sResult = '';
|
||||
$sPathInfo = \trim(\trim($this->oHttp->GetServer('PATH_INFO', '')), ' /');
|
||||
if (!empty($sPathInfo))
|
||||
{
|
||||
if ('dav' !== \substr($sPathInfo, 0, 3))
|
||||
{
|
||||
$sPathInfo = '';
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($sPathInfo))
|
||||
{
|
||||
$sQuery = \trim(\trim($this->oHttp->GetServer('QUERY_STRING', '')), ' /');
|
||||
|
|
|
@ -714,10 +714,13 @@ class ServiceActions
|
|||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function ServiceCardDav()
|
||||
public function ServiceDav()
|
||||
{
|
||||
return '';
|
||||
|
||||
if (!$this->Config()->Get('contacts', 'allow_carddav_sync', false))
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
\set_error_handler(function ($errno, $errstr, $errfile, $errline ) {
|
||||
|
@ -726,9 +729,10 @@ class ServiceActions
|
|||
|
||||
$oPersonalAddressBookProvider = $this->oActions->PersonalAddressBookProvider();
|
||||
|
||||
$oAuthBackend = new \RainLoop\SabreDAV\AuthBasic($oPersonalAddressBookProvider);
|
||||
// $oAuthBackend = new \RainLoop\SabreDAV\AuthBasic($oPersonalAddressBookProvider);
|
||||
$oAuthBackend = new \RainLoop\SabreDAV\AuthDigest($oPersonalAddressBookProvider);
|
||||
|
||||
$oCarddavBackend = new \RainLoop\SabreDAV\CardDAV($oPersonalAddressBookProvider);
|
||||
$oCarddavBackend = new \RainLoop\SabreDAV\CardDAV($oPersonalAddressBookProvider, $oAuthBackend);
|
||||
|
||||
$oPrincipalBackend = new \RainLoop\SabreDAV\Principal($oPersonalAddressBookProvider, $oAuthBackend);
|
||||
|
||||
|
@ -740,7 +744,7 @@ class ServiceActions
|
|||
$oServer = new \Sabre\DAV\Server($aNodes);
|
||||
|
||||
$aPath = \trim($this->oHttp->GetPath(), '/\\ ');
|
||||
$oServer->setBaseUri((0 < \strlen($aPath) ? '/'.$aPath.'/' : '').'index.php/carddav/');
|
||||
$oServer->setBaseUri((0 < \strlen($aPath) ? '/'.$aPath : '').'/index.php/dav/');
|
||||
|
||||
// Plugins
|
||||
$oServer->addPlugin(new \Sabre\DAV\Auth\Plugin($oAuthBackend, 'SabreDAV'));
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
<i data-bind="css: contactsSharing() ? 'icon-checkbox-checked' : 'icon-checkbox-unchecked'"></i>
|
||||
Allow contacts sharing
|
||||
</label>
|
||||
<label data-bind="click: function () { contactsSync(!contactsSync()); }">
|
||||
<i data-bind="css: contactsSync() ? 'icon-checkbox-checked' : 'icon-checkbox-unchecked'"></i>
|
||||
Allow contacts sync (CardDAV)
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
|
|
|
@ -5316,6 +5316,7 @@ function AdminContacts()
|
|||
this.defautOptionsAfterRender = Utils.defautOptionsAfterRender;
|
||||
this.enableContacts = ko.observable(!!RL.settingsGet('ContactsEnable'));
|
||||
this.contactsSharing = ko.observable(!!RL.settingsGet('ContactsSharing'));
|
||||
this.contactsSync = ko.observable(!!RL.settingsGet('ContactsSync'));
|
||||
|
||||
var
|
||||
aTypes = ['sqlite', 'mysql', 'pgsql'],
|
||||
|
@ -5489,6 +5490,12 @@ AdminContacts.prototype.onBuild = function ()
|
|||
'ContactsSharing': bValue ? '1' : '0'
|
||||
});
|
||||
});
|
||||
|
||||
self.contactsSync.subscribe(function (bValue) {
|
||||
RL.remote().saveAdminConfig(null, {
|
||||
'ContactsSync': bValue ? '1' : '0'
|
||||
});
|
||||
});
|
||||
|
||||
self.contactsType.subscribe(function (sValue) {
|
||||
RL.remote().saveAdminConfig(f5, {
|
||||
|
|
|
@ -5784,6 +5784,7 @@ EmailModel.prototype.inputoTagLine = function ()
|
|||
function ContactModel()
|
||||
{
|
||||
this.idContact = 0;
|
||||
this.idContactStr = '';
|
||||
this.display = '';
|
||||
this.properties = [];
|
||||
this.readOnly = false;
|
||||
|
@ -5835,6 +5836,7 @@ ContactModel.prototype.parse = function (oItem)
|
|||
if (oItem && 'Object/Contact' === oItem['@Object'])
|
||||
{
|
||||
this.idContact = Utils.pInt(oItem['IdContact']);
|
||||
this.idContactStr = Utils.pString(oItem['IdContactStr']);
|
||||
this.display = Utils.pString(oItem['Display']);
|
||||
this.readOnly = !!oItem['ReadOnly'];
|
||||
this.scopeType = Utils.pInt(oItem['ScopeType']);
|
||||
|
@ -9346,6 +9348,7 @@ function PopupsContactsViewModel()
|
|||
this.viewClearSearch = ko.observable(false);
|
||||
|
||||
this.viewID = ko.observable('');
|
||||
this.viewIDStr = ko.observable('');
|
||||
this.viewReadOnly = ko.observable(false);
|
||||
this.viewScopeType = ko.observable(Enums.ContactScopeType.Default);
|
||||
this.viewProperties = ko.observableArray([]);
|
||||
|
@ -9549,13 +9552,14 @@ function PopupsContactsViewModel()
|
|||
self.viewID(Utils.pInt(oData.Result.ResultID));
|
||||
}
|
||||
|
||||
if ('' === self.viewIDStr())
|
||||
{
|
||||
self.viewIDStr(Utils.pString(oData.Result.ResultIDStr));
|
||||
}
|
||||
|
||||
self.reloadContactList();
|
||||
bRes = true;
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// // TODO
|
||||
// }
|
||||
|
||||
_.delay(function () {
|
||||
self.viewSaveTrigger(bRes ? Enums.SaveSettingsStep.TrueResult : Enums.SaveSettingsStep.FalseResult);
|
||||
|
@ -9568,7 +9572,7 @@ function PopupsContactsViewModel()
|
|||
}, 1000);
|
||||
}
|
||||
|
||||
}, sRequestUid, this.viewID(), this.viewScopeType(), aProperties);
|
||||
}, sRequestUid, this.viewID(), this.viewIDStr(), this.viewScopeType(), aProperties);
|
||||
|
||||
}, function () {
|
||||
var
|
||||
|
@ -9712,6 +9716,7 @@ PopupsContactsViewModel.prototype.populateViewContact = function (oContact)
|
|||
{
|
||||
var
|
||||
sId = '',
|
||||
sIdStr = '',
|
||||
bHasName = false,
|
||||
aList = []
|
||||
;
|
||||
|
@ -9725,6 +9730,7 @@ PopupsContactsViewModel.prototype.populateViewContact = function (oContact)
|
|||
if (oContact)
|
||||
{
|
||||
sId = oContact.idContact;
|
||||
sIdStr = oContact.idContactStr;
|
||||
|
||||
if (Utils.isNonEmptyArray(oContact.properties))
|
||||
{
|
||||
|
@ -9752,6 +9758,7 @@ PopupsContactsViewModel.prototype.populateViewContact = function (oContact)
|
|||
}
|
||||
|
||||
this.viewID(sId);
|
||||
this.viewIDStr(sIdStr);
|
||||
this.viewProperties([]);
|
||||
this.viewProperties(aList);
|
||||
|
||||
|
@ -15021,11 +15028,12 @@ WebMailAjaxRemoteStorage.prototype.contacts = function (fCallback, iOffset, iLim
|
|||
/**
|
||||
* @param {?Function} fCallback
|
||||
*/
|
||||
WebMailAjaxRemoteStorage.prototype.contactSave = function (fCallback, sRequestUid, sUid, nScopeType, aProperties)
|
||||
WebMailAjaxRemoteStorage.prototype.contactSave = function (fCallback, sRequestUid, sUid, sUidStr, nScopeType, aProperties)
|
||||
{
|
||||
this.defaultRequest(fCallback, 'ContactSave', {
|
||||
'RequestUid': sRequestUid,
|
||||
'Uid': Utils.trim(sUid),
|
||||
'UidStr': Utils.trim(sUidStr),
|
||||
'ScopeType': nScopeType,
|
||||
'Properties': aProperties
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue