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