summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2021-01-07 19:37:08 +0300
committerGeorge Hazan <ghazan@miranda.im>2021-01-07 19:37:08 +0300
commitff65292a817e82bf5fd58811cfa436a8c5232bd9 (patch)
tree697237c9680b0212e8d8cc24fcbb75cdae4554fd /src
parent5508a77c6103f979697dd72d5a72347a354d020d (diff)
more common code moved to MDatabaseCommon
Diffstat (limited to 'src')
-rw-r--r--src/mir_app/src/MDatabaseCommon.cpp214
-rw-r--r--src/mir_app/src/MDatabaseReadonly.cpp2
-rw-r--r--src/mir_app/src/mir_app.def5
-rw-r--r--src/mir_app/src/mir_app64.def5
4 files changed, 223 insertions, 3 deletions
diff --git a/src/mir_app/src/MDatabaseCommon.cpp b/src/mir_app/src/MDatabaseCommon.cpp
index 20abf51d35..657b6a703b 100644
--- a/src/mir_app/src/MDatabaseCommon.cpp
+++ b/src/mir_app/src/MDatabaseCommon.cpp
@@ -324,6 +324,121 @@ STDMETHODIMP_(BOOL) MDatabaseCommon::GetContactSettingStatic(MCONTACT contactID,
return 0;
}
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static bool ValidLookupName(const char *szModule, const char *szSetting)
+{
+ if (!strcmp(szModule, META_PROTO))
+ return strcmp(szSetting, "IsSubcontact") && strcmp(szSetting, "ParentMetaID");
+
+ return false;
+}
+
+STDMETHODIMP_(int) MDatabaseCommon::GetContactSettingWorker(MCONTACT contactID, const char *szModule, const char *szSetting, DBVARIANT *dbv, int isStatic)
+{
+ if (szSetting == nullptr || szModule == nullptr)
+ return 1;
+
+ DBVARIANT *pCachedValue;
+ size_t settingNameLen = strlen(szSetting);
+ size_t moduleNameLen = strlen(szModule);
+ {
+ mir_cslock lck(m_csDbAccess);
+
+LBL_Seek:
+ char *szCachedSettingName = m_cache->GetCachedSetting(szModule, szSetting, moduleNameLen, settingNameLen);
+
+ pCachedValue = m_cache->GetCachedValuePtr(contactID, szCachedSettingName, 0);
+ if (pCachedValue == nullptr) {
+ // if nothing was faund, try to lookup the same setting from meta's default contact
+ if (contactID) {
+ DBCachedContact *cc = m_cache->GetCachedContact(contactID);
+ if (cc && cc->IsMeta() && ValidLookupName(szModule, szSetting)) {
+ if (contactID = db_mc_getDefault(contactID)) {
+ szModule = Proto_GetBaseAccountName(contactID);
+ if (szModule == nullptr) // smth went wrong
+ return 1;
+
+ moduleNameLen = strlen(szModule);
+ goto LBL_Seek;
+ }
+ }
+ }
+
+ // otherwise fail
+ return 1;
+ }
+ }
+
+ switch(pCachedValue->type) {
+ case DBVT_ASCIIZ:
+ case DBVT_UTF8:
+ dbv->type = pCachedValue->type;
+ if (isStatic) {
+ int cbLen = (int)mir_strlen(pCachedValue->pszVal);
+ int cbOrigLen = dbv->cchVal;
+ cbOrigLen--;
+ if (cbLen < cbOrigLen)
+ cbOrigLen = cbLen;
+ memcpy(dbv->pszVal, pCachedValue->pszVal, cbOrigLen);
+ dbv->pszVal[cbOrigLen] = 0;
+ dbv->cchVal = cbLen;
+ }
+ else {
+ dbv->pszVal = (char *)mir_alloc(strlen(pCachedValue->pszVal) + 1);
+ strcpy(dbv->pszVal, pCachedValue->pszVal);
+ dbv->cchVal = pCachedValue->cchVal;
+ }
+ break;
+
+ case DBVT_BLOB:
+ dbv->type = DBVT_BLOB;
+ if (isStatic) {
+ if (pCachedValue->cpbVal < dbv->cpbVal)
+ dbv->cpbVal = pCachedValue->cpbVal;
+ memcpy(dbv->pbVal, pCachedValue->pbVal, dbv->cpbVal);
+ }
+ else {
+ dbv->pbVal = (BYTE *)mir_alloc(pCachedValue->cpbVal);
+ memcpy(dbv->pbVal, pCachedValue->pbVal, pCachedValue->cpbVal);
+ }
+ dbv->cpbVal = pCachedValue->cpbVal;
+ break;
+
+ case DBVT_ENCRYPTED:
+ if (m_crypto != nullptr) {
+ size_t realLen;
+ ptrA decoded(m_crypto->decodeString(pCachedValue->pbVal, pCachedValue->cpbVal, &realLen));
+ if (decoded == nullptr)
+ return 1;
+
+ dbv->type = DBVT_UTF8;
+ if (isStatic) {
+ dbv->cchVal--;
+ if (realLen < dbv->cchVal)
+ dbv->cchVal = WORD(realLen);
+ memcpy(dbv->pszVal, decoded, dbv->cchVal);
+ dbv->pszVal[dbv->cchVal] = 0;
+ dbv->cchVal = WORD(realLen);
+ }
+ else {
+ dbv->pszVal = (char *)mir_alloc(1 + realLen);
+ memcpy(dbv->pszVal, decoded, realLen);
+ dbv->pszVal[realLen] = 0;
+ }
+ break;
+ }
+ return 1;
+
+ default:
+ memcpy(dbv, pCachedValue, sizeof(DBVARIANT));
+ }
+
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
STDMETHODIMP_(BOOL) MDatabaseCommon::FreeVariant(DBVARIANT *dbv)
{
if (dbv == nullptr) return 1;
@@ -345,6 +460,105 @@ STDMETHODIMP_(BOOL) MDatabaseCommon::FreeVariant(DBVARIANT *dbv)
}
/////////////////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP_(BOOL) MDatabaseCommon::WriteContactSetting(MCONTACT contactID, DBCONTACTWRITESETTING *dbcws)
+{
+ if (dbcws == nullptr || dbcws->szSetting == nullptr || dbcws->szModule == nullptr)
+ return 1;
+
+ // the db format can't tolerate more than 255 bytes of space (incl. null) for settings+module name
+ size_t settingNameLen = strlen(dbcws->szSetting);
+ size_t moduleNameLen = strlen(dbcws->szModule);
+
+ // used for notifications
+ DBCONTACTWRITESETTING dbcwNotif = *dbcws;
+ if (dbcwNotif.value.type == DBVT_WCHAR) {
+ if (dbcwNotif.value.pszVal != nullptr) {
+ T2Utf val(dbcwNotif.value.pwszVal);
+ if (!val)
+ return 1;
+
+ dbcwNotif.value.pszVal = NEWSTR_ALLOCA(val);
+ dbcwNotif.value.type = DBVT_UTF8;
+ }
+ else return 1;
+ }
+
+ if (dbcwNotif.szModule == nullptr || dbcwNotif.szSetting == nullptr)
+ return 1;
+
+ DBCONTACTWRITESETTING dbcwWork = dbcwNotif;
+
+ mir_ptr<BYTE> pEncoded(nullptr);
+ bool bIsEncrypted = false;
+ switch (dbcwWork.value.type) {
+ case DBVT_BYTE: case DBVT_WORD: case DBVT_DWORD:
+ break;
+
+ case DBVT_ASCIIZ:
+ case DBVT_UTF8:
+ bIsEncrypted = m_bEncrypted || IsSettingEncrypted(dbcws->szModule, dbcws->szSetting);
+ if (dbcwWork.value.pszVal == nullptr)
+ return 1;
+
+ dbcwWork.value.cchVal = (WORD)strlen(dbcwWork.value.pszVal);
+ if (bIsEncrypted) {
+ size_t len;
+ BYTE *pResult = m_crypto->encodeString(dbcwWork.value.pszVal, &len);
+ if (pResult != nullptr) {
+ pEncoded = dbcwWork.value.pbVal = pResult;
+ dbcwWork.value.cpbVal = (WORD)len;
+ dbcwWork.value.type = DBVT_ENCRYPTED;
+ }
+ }
+ break;
+
+ case DBVT_BLOB:
+ case DBVT_ENCRYPTED:
+ if (dbcwWork.value.pbVal == nullptr)
+ return 1;
+ break;
+
+ default:
+ return 1;
+ }
+
+ mir_cslockfull lck(m_csDbAccess);
+ char *szCachedSettingName = m_cache->GetCachedSetting(dbcwWork.szModule, dbcwWork.szSetting, moduleNameLen, settingNameLen);
+
+ DBVARIANT *pCachedValue = m_cache->GetCachedValuePtr(contactID, szCachedSettingName, 1);
+ if (pCachedValue != nullptr) {
+ bool bIsIdentical = false;
+ if (pCachedValue->type == dbcwWork.value.type) {
+ switch (dbcwWork.value.type) {
+ case DBVT_BYTE: bIsIdentical = pCachedValue->bVal == dbcwWork.value.bVal; break;
+ case DBVT_WORD: bIsIdentical = pCachedValue->wVal == dbcwWork.value.wVal; break;
+ case DBVT_DWORD: bIsIdentical = pCachedValue->dVal == dbcwWork.value.dVal; break;
+ case DBVT_UTF8:
+ case DBVT_ASCIIZ: bIsIdentical = strcmp(pCachedValue->pszVal, dbcwWork.value.pszVal) == 0; break;
+ case DBVT_BLOB:
+ case DBVT_ENCRYPTED:
+ if (pCachedValue->cpbVal == dbcwWork.value.cchVal)
+ bIsIdentical = memcmp(pCachedValue->pbVal, dbcwWork.value.pbVal, dbcwWork.value.cchVal);
+ break;
+ }
+ if (bIsIdentical)
+ return 0;
+ }
+ m_cache->SetCachedVariant(&dbcwWork.value, pCachedValue);
+ }
+
+ // for non-resident settings we call a write worker
+ if (szCachedSettingName[-1] == 0)
+ if (WriteContactSettingWorker(contactID, dbcwWork))
+ return 1;
+
+ lck.unlock();
+ NotifyEventHooks(g_hevSettingChanged, contactID, (LPARAM)&dbcwNotif);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
// Resident settings
STDMETHODIMP_(BOOL) MDatabaseCommon::EnumResidentSettings(DBMODULEENUMPROC pFunc, void *pParam)
diff --git a/src/mir_app/src/MDatabaseReadonly.cpp b/src/mir_app/src/MDatabaseReadonly.cpp
index 1de92de019..0f006160eb 100644
--- a/src/mir_app/src/MDatabaseReadonly.cpp
+++ b/src/mir_app/src/MDatabaseReadonly.cpp
@@ -108,7 +108,7 @@ BOOL MDatabaseReadonly::GetContactSettingWorker(MCONTACT, LPCSTR, LPCSTR, DBVARI
return 1;
}
-BOOL MDatabaseReadonly::WriteContactSetting(MCONTACT, DBCONTACTWRITESETTING*)
+BOOL MDatabaseReadonly::WriteContactSettingWorker(MCONTACT, DBCONTACTWRITESETTING&)
{
return 1;
}
diff --git a/src/mir_app/src/mir_app.def b/src/mir_app/src/mir_app.def
index d7ea30182d..68e30d3dc4 100644
--- a/src/mir_app/src/mir_app.def
+++ b/src/mir_app/src/mir_app.def
@@ -593,7 +593,7 @@ Miranda_WaitOnHandleEx @663
?MetaMergeHistory@MDatabaseReadonly@@UAGHPAUDBCachedContact@@0@Z @680 NONAME
?MetaSplitHistory@MDatabaseReadonly@@UAGHPAUDBCachedContact@@0@Z @681 NONAME
?SetCacheSafetyMode@MDatabaseReadonly@@UAGXH@Z @682 NONAME
-?WriteContactSetting@MDatabaseReadonly@@UAGHIPAUDBCONTACTWRITESETTING@@@Z @683 NONAME
+?WriteContactSettingWorker@MDatabaseReadonly@@UAGHIAAUDBCONTACTWRITESETTING@@@Z @683 NONAME
??0MDatabaseReadonly@@QAE@XZ @684 NONAME
??_7MDatabaseReadonly@@6B@ @685 NONAME
?GetEventById@MDatabaseReadonly@@UAGIPBD0@Z @686 NONAME
@@ -752,3 +752,6 @@ _Netlib_GetTlsUnique@8 @831 NONAME
?SafeMoveFile@PU@@YGHPB_W0@Z @840 NONAME
?FilterSearch@Clist@@3V?$CMOption@_N@@A @841 NONAME
?FillContactSettings@MDatabaseCommon@@IAEXXZ @842 NONAME
+?GetContactSettingWorker@MDatabaseCommon@@MAGHIPBD0PAUDBVARIANT@@H@Z @843 NONAME
+?WriteContactSetting@MDatabaseCommon@@UAGHIPAUDBCONTACTWRITESETTING@@@Z @844 NONAME
+?getCrypt@MDatabaseCommon@@QBEPAUMICryptoEngine@@XZ @845 NONAME
diff --git a/src/mir_app/src/mir_app64.def b/src/mir_app/src/mir_app64.def
index 3ec5305738..85ec395060 100644
--- a/src/mir_app/src/mir_app64.def
+++ b/src/mir_app/src/mir_app64.def
@@ -593,7 +593,7 @@ Miranda_WaitOnHandleEx @663
?MetaMergeHistory@MDatabaseReadonly@@UEAAHPEAUDBCachedContact@@0@Z @680 NONAME
?MetaSplitHistory@MDatabaseReadonly@@UEAAHPEAUDBCachedContact@@0@Z @681 NONAME
?SetCacheSafetyMode@MDatabaseReadonly@@UEAAXH@Z @682 NONAME
-?WriteContactSetting@MDatabaseReadonly@@UEAAHIPEAUDBCONTACTWRITESETTING@@@Z @683 NONAME
+?WriteContactSettingWorker@MDatabaseReadonly@@UEAAHIAEAUDBCONTACTWRITESETTING@@@Z @683 NONAME
??0MDatabaseReadonly@@QEAA@XZ @684 NONAME
??_7MDatabaseReadonly@@6B@ @685 NONAME
?GetEventById@MDatabaseReadonly@@UEAAIPEBD0@Z @686 NONAME
@@ -752,3 +752,6 @@ Netlib_GetTlsUnique @831 NONAME
?SafeMoveFile@PU@@YAHPEB_W0@Z @840 NONAME
?FilterSearch@Clist@@3V?$CMOption@_N@@A @841 NONAME
?FillContactSettings@MDatabaseCommon@@IEAAXXZ @842 NONAME
+?GetContactSettingWorker@MDatabaseCommon@@MEAAHIPEBD0PEAUDBVARIANT@@H@Z @843 NONAME
+?WriteContactSetting@MDatabaseCommon@@UEAAHIPEAUDBCONTACTWRITESETTING@@@Z @844 NONAME
+?getCrypt@MDatabaseCommon@@QEBAPEAUMICryptoEngine@@XZ @845 NONAME