From ff65292a817e82bf5fd58811cfa436a8c5232bd9 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Thu, 7 Jan 2021 19:37:08 +0300 Subject: more common code moved to MDatabaseCommon --- include/m_database.h | 18 ++- include/m_db_int.h | 13 +- libs/win32/mir_app.lib | Bin 211418 -> 212774 bytes libs/win64/mir_app.lib | Bin 207076 -> 208466 bytes plugins/Db3x_mmap/src/dbcrypt.cpp | 2 +- plugins/Db3x_mmap/src/dbintf.h | 5 +- plugins/Db3x_mmap/src/dbsettings.cpp | 190 +++++----------------- plugins/Db3x_mmap/src/ui.cpp | 2 +- plugins/Dbx_mdbx/src/dbintf.h | 10 +- plugins/Dbx_mdbx/src/dbsettings.cpp | 239 ++-------------------------- plugins/Dbx_mdbx/src/ui.cpp | 2 +- plugins/Dbx_sqlite/src/dbintf.h | 6 +- plugins/Dbx_sqlite/src/dbsettings.cpp | 282 +++++++++------------------------ plugins/Import/src/dbrw/dbintf.h | 2 +- plugins/Import/src/dbrw/dbsettings.cpp | 6 +- src/mir_app/src/MDatabaseCommon.cpp | 214 +++++++++++++++++++++++++ src/mir_app/src/MDatabaseReadonly.cpp | 2 +- src/mir_app/src/mir_app.def | 5 +- src/mir_app/src/mir_app64.def | 5 +- 19 files changed, 383 insertions(+), 620 deletions(-) diff --git a/include/m_database.h b/include/m_database.h index cb6d0e55bf..fb9d84c53c 100644 --- a/include/m_database.h +++ b/include/m_database.h @@ -128,14 +128,16 @@ EXTERN_C MIR_CORE_DLL(int) db_enum_settings(MCONTACT hContact, DBSETTINGENUMPROC ///////////////////////////////////////////////////////////////////////////////////////// // DBVARIANT: used by db/contact/getsetting and db/contact/writesetting -#define DBVT_DELETED 0 // this setting just got deleted, no other values are valid -#define DBVT_BYTE 1 // bVal and cVal are valid -#define DBVT_WORD 2 // wVal and sVal are valid -#define DBVT_DWORD 4 // dVal and lVal are valid -#define DBVT_ASCIIZ 255 // pszVal is valid -#define DBVT_BLOB 254 // cpbVal and pbVal are valid -#define DBVT_UTF8 253 // pszVal is valid -#define DBVT_WCHAR 252 // pwszVal is valid +#define DBVT_DELETED 0 // this setting just got deleted, no other values are valid +#define DBVT_BYTE 1 // bVal and cVal are valid +#define DBVT_WORD 2 // wVal and sVal are valid +#define DBVT_DWORD 4 // dVal and lVal are valid +#define DBVT_ASCIIZ 255 // pszVal is valid +#define DBVT_BLOB 254 // cpbVal and pbVal are valid +#define DBVT_UTF8 253 // pszVal is valid +#define DBVT_WCHAR 252 // pwszVal is valid +#define DBVT_ENCRYPTED 250 // blob of encrypted bytesw + #define DBVTF_VARIABLELENGTH 0x80 diff --git a/include/m_db_int.h b/include/m_db_int.h index a2b53fb279..a393b23bbe 100644 --- a/include/m_db_int.h +++ b/include/m_db_int.h @@ -167,16 +167,20 @@ interface MIR_APP_EXPORT MIDatabase #pragma warning(push) #pragma warning(disable:4275) +struct MICryptoEngine; + class MIR_APP_EXPORT MDatabaseCommon : public MIDatabase, public MNonCopyable { HANDLE m_hLock = nullptr; protected: + bool m_bEncrypted = false; int m_codePage; mir_cs m_csDbAccess; LIST m_lResidentSettings; MIDatabaseCache* m_cache; + MICryptoEngine *m_crypto; protected: void FillContactSettings(); @@ -184,12 +188,14 @@ protected: int CheckProto(DBCachedContact *cc, const char *proto); void UnlockName(); - STDMETHOD_(BOOL, GetContactSettingWorker)(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv, int isStatic) PURE; + STDMETHOD_(BOOL, GetContactSettingWorker)(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv, int isStatic); + STDMETHOD_(BOOL, WriteContactSettingWorker)(MCONTACT contactID, DBCONTACTWRITESETTING &dbcws) PURE; public: MDatabaseCommon(); virtual ~MDatabaseCommon(); + __forceinline MICryptoEngine* getCrypt() const { return m_crypto; } __forceinline MIDatabaseCache* getCache() const { return m_cache; } STDMETHODIMP_(BOOL) DeleteModule(MCONTACT contactID, LPCSTR szModule) override; @@ -206,7 +212,8 @@ public: STDMETHODIMP_(BOOL) GetContactSettingStr(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv) override; STDMETHODIMP_(BOOL) GetContactSettingStatic(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv) override; STDMETHODIMP_(BOOL) FreeVariant(DBVARIANT *dbv); - + STDMETHODIMP_(BOOL) WriteContactSetting(MCONTACT contactID, DBCONTACTWRITESETTING *dbcws) override; + STDMETHODIMP_(BOOL) EnumResidentSettings(DBMODULEENUMPROC pFunc, void *pParam) override; STDMETHODIMP_(BOOL) SetSettingResident(BOOL bIsResident, const char *pszSettingName) override; @@ -252,7 +259,7 @@ public: //////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP_(BOOL) GetContactSettingWorker(MCONTACT, LPCSTR, LPCSTR, DBVARIANT*, int) override; - STDMETHODIMP_(BOOL) WriteContactSetting(MCONTACT, DBCONTACTWRITESETTING*) override; + STDMETHODIMP_(BOOL) WriteContactSettingWorker(MCONTACT, DBCONTACTWRITESETTING&) override; STDMETHODIMP_(BOOL) DeleteContactSetting(MCONTACT, LPCSTR, LPCSTR) override; STDMETHODIMP_(BOOL) EnumContactSettings(MCONTACT, DBSETTINGENUMPROC, const char*, void*) override; diff --git a/libs/win32/mir_app.lib b/libs/win32/mir_app.lib index 01437d5c1b..709bc424ec 100644 Binary files a/libs/win32/mir_app.lib and b/libs/win32/mir_app.lib differ diff --git a/libs/win64/mir_app.lib b/libs/win64/mir_app.lib index a1c4cbffcb..4c60455f8b 100644 Binary files a/libs/win64/mir_app.lib and b/libs/win64/mir_app.lib differ diff --git a/plugins/Db3x_mmap/src/dbcrypt.cpp b/plugins/Db3x_mmap/src/dbcrypt.cpp index 9913802065..c76f3feb4e 100644 --- a/plugins/Db3x_mmap/src/dbcrypt.cpp +++ b/plugins/Db3x_mmap/src/dbcrypt.cpp @@ -95,7 +95,7 @@ void sttContactEnum(MCONTACT contactID, const char *szModule, CDb3Mmap *db) for (auto &p : arSettings) { size_t len; - BYTE *pResult = db->m_crypto->encodeString(p->szValue, &len); + BYTE *pResult = db->getCrypt()->encodeString(p->szValue, &len); if (pResult != nullptr) { DBCONTACTWRITESETTING dbcws = { szModule, p->szVar }; dbcws.value.type = DBVT_ENCRYPTED; diff --git a/plugins/Db3x_mmap/src/dbintf.h b/plugins/Db3x_mmap/src/dbintf.h index 17f634e051..e839d56e4f 100644 --- a/plugins/Db3x_mmap/src/dbintf.h +++ b/plugins/Db3x_mmap/src/dbintf.h @@ -61,7 +61,6 @@ DBHeader #define WSOFS_END 0xFFFFFFFF #define WS_ERROR 0xFFFFFFFF -#define DBVT_ENCRYPTED 250 #define DBVT_UNENCRYPTED 251 #define MARKED_READ (DBEF_READ | DBEF_SENT) @@ -234,7 +233,7 @@ public: STDMETHODIMP_(BOOL) EnumModuleNames(DBMODULEENUMPROC pFunc, void *pParam) override; STDMETHODIMP_(BOOL) GetContactSettingWorker(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv, int isStatic) override; - STDMETHODIMP_(BOOL) WriteContactSetting(MCONTACT contactID, DBCONTACTWRITESETTING *dbcws) override; + STDMETHODIMP_(BOOL) WriteContactSettingWorker(MCONTACT contactID, DBCONTACTWRITESETTING &dbcws) override; STDMETHODIMP_(BOOL) DeleteContactSetting(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting) override; STDMETHODIMP_(BOOL) EnumContactSettings(MCONTACT hContact, DBSETTINGENUMPROC pfnEnumProc, const char *szModule, void *param) override; @@ -275,8 +274,6 @@ public: PBYTE m_pDbCache; HANDLE m_hMap; - MICryptoEngine *m_crypto; - protected: DWORD m_dwFileSize, m_dwMaxContactId; diff --git a/plugins/Db3x_mmap/src/dbsettings.cpp b/plugins/Db3x_mmap/src/dbsettings.cpp index c36b001d1d..e5586921dc 100644 --- a/plugins/Db3x_mmap/src/dbsettings.cpp +++ b/plugins/Db3x_mmap/src/dbsettings.cpp @@ -219,125 +219,18 @@ LBL_Seek: return 1; } -STDMETHODIMP_(BOOL) CDb3Mmap::WriteContactSetting(MCONTACT contactID, DBCONTACTWRITESETTING *dbcws) +STDMETHODIMP_(BOOL) CDb3Mmap::WriteContactSettingWorker(MCONTACT contactID, DBCONTACTWRITESETTING &dbcws) { - if (dbcws == nullptr || dbcws->szSetting == nullptr || dbcws->szModule == nullptr || m_bReadOnly) - return 1; - - // the db format can't tolerate more than 255 bytes of space (incl. null) for settings+module name - int settingNameLen = (int)mir_strlen(dbcws->szSetting); - int moduleNameLen = (int)mir_strlen(dbcws->szModule); - if (settingNameLen > 0xFE) { -#ifdef _DEBUG - OutputDebugStringA("WriteContactSetting() got a > 255 setting name length. \n"); -#endif - return 1; - } - if (moduleNameLen > 0xFE) { -#ifdef _DEBUG - OutputDebugStringA("WriteContactSetting() got a > 255 module name length. \n"); -#endif - return 1; - } - - // used for notifications - DBCONTACTWRITESETTING dbcwNotif = *dbcws; - if (dbcwNotif.value.type == DBVT_WCHAR) { - if (dbcwNotif.value.pszVal != nullptr) { - char* val = mir_utf8encodeW(dbcwNotif.value.pwszVal); - if (val == nullptr) - return 1; - - dbcwNotif.value.pszVal = (char*)alloca(mir_strlen(val) + 1); - mir_strcpy(dbcwNotif.value.pszVal, val); - mir_free(val); - dbcwNotif.value.type = DBVT_UTF8; - } - else return 1; - } - - if (dbcwNotif.szModule == nullptr || dbcwNotif.szSetting == nullptr) - return 1; - - DBCONTACTWRITESETTING dbcwWork = dbcwNotif; - char *szCachedSettingName = m_cache->GetCachedSetting(dbcwWork.szModule, dbcwWork.szSetting, moduleNameLen, settingNameLen); - bool bIsResident = szCachedSettingName[-1] != 0; - - mir_ptr 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 = !bIsResident && (m_bEncrypted || IsSettingEncrypted(dbcws->szModule, dbcws->szSetting)); - LBL_WriteString: - if (dbcwWork.value.pszVal == nullptr) - return 1; - dbcwWork.value.cchVal = (WORD)mir_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_UNENCRYPTED: - dbcwNotif.value.type = dbcwWork.value.type = DBVT_UTF8; - goto LBL_WriteString; - - case DBVT_BLOB: case DBVT_ENCRYPTED: - if (dbcwWork.value.pbVal == nullptr) - return 1; - break; - default: - return 1; - } - - mir_cslockfull lck(m_csDbAccess); + log1(" write database as %s", printVariant(&dbcws.value)); + DWORD settingNameLen = (DWORD)mir_strlen(dbcws.szSetting); DWORD ofsBlobPtr, ofsContact = GetContactOffset(contactID); if (ofsContact == 0) { _ASSERT(false); // contact doesn't exist? return 2; } - log3("set [%08p] %s (%p)", hContact, szCachedSettingName, szCachedSettingName); - - // we don't cache blobs and passwords - if (dbcwWork.value.type != DBVT_BLOB && dbcwWork.value.type != DBVT_ENCRYPTED && !bIsEncrypted) { - 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 = mir_strcmp(pCachedValue->pszVal, dbcwWork.value.pszVal) == 0; break; - } - if (bIsIdentical) - return 0; - } - m_cache->SetCachedVariant(&dbcwWork.value, pCachedValue); - } - if (bIsResident) { - lck.unlock(); - log2(" set resident as %s (%p)", printVariant(&dbcwWork.value), pCachedValue); - NotifyEventHooks(g_hevSettingChanged, contactID, (LPARAM)&dbcwWork); - return 0; - } - } - else m_cache->GetCachedValuePtr(contactID, szCachedSettingName, -1); - - log1(" write database as %s", printVariant(&dbcwWork.value)); - - DWORD ofsModuleName = GetModuleNameOfs(dbcwWork.szModule); + DWORD ofsModuleName = GetModuleNameOfs(dbcws.szModule); DBContact dbc = *(DBContact*)DBRead(ofsContact, nullptr); if (dbc.signature != DBCONTACT_SIGNATURE) return 1; @@ -348,15 +241,15 @@ STDMETHODIMP_(BOOL) CDb3Mmap::WriteContactSetting(MCONTACT contactID, DBCONTACTW DBContactSettings dbcs; DWORD ofsSettingsGroup = GetSettingsGroupOfsByModuleNameOfs(&dbc, ofsModuleName); if (ofsSettingsGroup == 0) { //module group didn't exist - make it - switch (dbcwWork.value.type) { + switch (dbcws.value.type) { case DBVT_ASCIIZ: case DBVT_UTF8: - bytesRequired = dbcwWork.value.cchVal + 2; + bytesRequired = dbcws.value.cchVal + 2; break; case DBVT_BLOB: case DBVT_ENCRYPTED: - bytesRequired = dbcwWork.value.cpbVal + 2; + bytesRequired = dbcws.value.cpbVal + 2; break; default: - bytesRequired = dbcwWork.value.type; + bytesRequired = dbcws.value.type; } bytesRequired += 2 + settingNameLen; bytesRequired += (DB_SETTINGS_RESIZE_GRANULARITY - (bytesRequired % DB_SETTINGS_RESIZE_GRANULARITY)) % DB_SETTINGS_RESIZE_GRANULARITY; @@ -380,7 +273,7 @@ STDMETHODIMP_(BOOL) CDb3Mmap::WriteContactSetting(MCONTACT contactID, DBCONTACTW pBlob = (PBYTE)DBRead(ofsBlobPtr, &bytesRemaining); while (pBlob[0]) { NeedBytes(settingNameLen + 1); - if (pBlob[0] == settingNameLen && !memcmp(pBlob + 1, dbcwWork.szSetting, settingNameLen)) + if (pBlob[0] == settingNameLen && !memcmp(pBlob + 1, dbcws.szSetting, settingNameLen)) break; NeedBytes(1); MoveAlong(pBlob[0] + 1); @@ -394,9 +287,9 @@ STDMETHODIMP_(BOOL) CDb3Mmap::WriteContactSetting(MCONTACT contactID, DBCONTACTW MoveAlong(1 + settingNameLen); // if different type or variable length and length is different NeedBytes(3); - if (pBlob[0] != dbcwWork.value.type || - ((pBlob[0] == DBVT_ASCIIZ || pBlob[0] == DBVT_UTF8) && *(PWORD)(pBlob + 1) != dbcwWork.value.cchVal) || - ((pBlob[0] == DBVT_BLOB || pBlob[0] == DBVT_ENCRYPTED) && *(PWORD)(pBlob + 1) != dbcwWork.value.cpbVal)) + if (pBlob[0] != dbcws.value.type || + ((pBlob[0] == DBVT_ASCIIZ || pBlob[0] == DBVT_UTF8) && *(PWORD)(pBlob + 1) != dbcws.value.cchVal) || + ((pBlob[0] == DBVT_BLOB || pBlob[0] == DBVT_ENCRYPTED) && *(PWORD)(pBlob + 1) != dbcws.value.cpbVal)) { // bin it NeedBytes(3); @@ -418,26 +311,23 @@ STDMETHODIMP_(BOOL) CDb3Mmap::WriteContactSetting(MCONTACT contactID, DBCONTACTW else { // replace existing setting at pBlob MoveAlong(1); // skip data type - switch (dbcwWork.value.type) { - case DBVT_BYTE: DBWrite(ofsBlobPtr, &dbcwWork.value.bVal, 1); break; - case DBVT_WORD: DBWrite(ofsBlobPtr, &dbcwWork.value.wVal, 2); break; - case DBVT_DWORD: DBWrite(ofsBlobPtr, &dbcwWork.value.dVal, 4); break; + switch (dbcws.value.type) { + case DBVT_BYTE: DBWrite(ofsBlobPtr, &dbcws.value.bVal, 1); break; + case DBVT_WORD: DBWrite(ofsBlobPtr, &dbcws.value.wVal, 2); break; + case DBVT_DWORD: DBWrite(ofsBlobPtr, &dbcws.value.dVal, 4); break; case DBVT_BLOB: - DBWrite(ofsBlobPtr + 2, dbcwWork.value.pbVal, dbcwWork.value.cpbVal); + DBWrite(ofsBlobPtr + 2, dbcws.value.pbVal, dbcws.value.cpbVal); break; case DBVT_ENCRYPTED: - DBWrite(ofsBlobPtr + 2, dbcwWork.value.pbVal, dbcwWork.value.cpbVal); + DBWrite(ofsBlobPtr + 2, dbcws.value.pbVal, dbcws.value.cpbVal); break; case DBVT_UTF8: case DBVT_ASCIIZ: - DBWrite(ofsBlobPtr + 2, dbcwWork.value.pszVal, dbcwWork.value.cchVal); + DBWrite(ofsBlobPtr + 2, dbcws.value.pszVal, dbcws.value.cchVal); break; } // quit DBFlush(1); - lck.unlock(); - // notify - NotifyEventHooks(g_hevSettingChanged, contactID, (LPARAM)&dbcwNotif); return 0; } } @@ -446,15 +336,15 @@ STDMETHODIMP_(BOOL) CDb3Mmap::WriteContactSetting(MCONTACT contactID, DBCONTACTW // cannot do a simple replace, add setting to end of list // pBlob already points to end of list // see if it fits - switch (dbcwWork.value.type) { + switch (dbcws.value.type) { case DBVT_ASCIIZ: case DBVT_UTF8: - bytesRequired = dbcwWork.value.cchVal + 2; + bytesRequired = dbcws.value.cchVal + 2; break; case DBVT_BLOB: case DBVT_ENCRYPTED: - bytesRequired = dbcwWork.value.cpbVal + 2; + bytesRequired = dbcws.value.cpbVal + 2; break; default: - bytesRequired = dbcwWork.value.type; + bytesRequired = dbcws.value.type; } bytesRequired += 2 + settingNameLen; @@ -501,31 +391,31 @@ STDMETHODIMP_(BOOL) CDb3Mmap::WriteContactSetting(MCONTACT contactID, DBCONTACTW // we now have a place to put it and enough space: make it DBWrite(ofsBlobPtr, &settingNameLen, 1); - DBWrite(ofsBlobPtr + 1, (PVOID)dbcwWork.szSetting, settingNameLen); + DBWrite(ofsBlobPtr + 1, (PVOID)dbcws.szSetting, settingNameLen); MoveAlong(1 + settingNameLen); - DBWrite(ofsBlobPtr, &dbcwWork.value.type, 1); + DBWrite(ofsBlobPtr, &dbcws.value.type, 1); MoveAlong(1); - switch (dbcwWork.value.type) { - case DBVT_BYTE: DBWrite(ofsBlobPtr, &dbcwWork.value.bVal, 1); MoveAlong(1); break; - case DBVT_WORD: DBWrite(ofsBlobPtr, &dbcwWork.value.wVal, 2); MoveAlong(2); break; - case DBVT_DWORD: DBWrite(ofsBlobPtr, &dbcwWork.value.dVal, 4); MoveAlong(4); break; + switch (dbcws.value.type) { + case DBVT_BYTE: DBWrite(ofsBlobPtr, &dbcws.value.bVal, 1); MoveAlong(1); break; + case DBVT_WORD: DBWrite(ofsBlobPtr, &dbcws.value.wVal, 2); MoveAlong(2); break; + case DBVT_DWORD: DBWrite(ofsBlobPtr, &dbcws.value.dVal, 4); MoveAlong(4); break; case DBVT_BLOB: - DBWrite(ofsBlobPtr, &dbcwWork.value.cpbVal, 2); - DBWrite(ofsBlobPtr + 2, dbcwWork.value.pbVal, dbcwWork.value.cpbVal); - MoveAlong(2 + dbcwWork.value.cpbVal); + DBWrite(ofsBlobPtr, &dbcws.value.cpbVal, 2); + DBWrite(ofsBlobPtr + 2, dbcws.value.pbVal, dbcws.value.cpbVal); + MoveAlong(2 + dbcws.value.cpbVal); break; case DBVT_ENCRYPTED: - DBWrite(ofsBlobPtr, &dbcwWork.value.cpbVal, 2); - DBWrite(ofsBlobPtr + 2, dbcwWork.value.pbVal, dbcwWork.value.cpbVal); - MoveAlong(2 + dbcwWork.value.cpbVal); + DBWrite(ofsBlobPtr, &dbcws.value.cpbVal, 2); + DBWrite(ofsBlobPtr + 2, dbcws.value.pbVal, dbcws.value.cpbVal); + MoveAlong(2 + dbcws.value.cpbVal); break; case DBVT_UTF8: case DBVT_ASCIIZ: - DBWrite(ofsBlobPtr, &dbcwWork.value.cchVal, 2); - DBWrite(ofsBlobPtr + 2, dbcwWork.value.pszVal, dbcwWork.value.cchVal); - MoveAlong(2 + dbcwWork.value.cchVal); + DBWrite(ofsBlobPtr, &dbcws.value.cchVal, 2); + DBWrite(ofsBlobPtr + 2, dbcws.value.pszVal, dbcws.value.cchVal); + MoveAlong(2 + dbcws.value.cchVal); break; } @@ -534,10 +424,6 @@ STDMETHODIMP_(BOOL) CDb3Mmap::WriteContactSetting(MCONTACT contactID, DBCONTACTW // quit DBFlush(1); - lck.unlock(); - - // notify - NotifyEventHooks(g_hevSettingChanged, contactID, (LPARAM)&dbcwNotif); return 0; } diff --git a/plugins/Db3x_mmap/src/ui.cpp b/plugins/Db3x_mmap/src/ui.cpp index 9b084edb4a..19e8a1c4f2 100644 --- a/plugins/Db3x_mmap/src/ui.cpp +++ b/plugins/Db3x_mmap/src/ui.cpp @@ -159,7 +159,7 @@ static bool CheckOldPassword(HWND hwndDlg, CDb3Mmap *db) if (db->usesPassword()) { wchar_t buf[100]; GetDlgItemText(hwndDlg, IDC_OLDPASS, buf, _countof(buf)); - if (!db->m_crypto->checkPassword(T2Utf(buf))) { + if (!db->getCrypt()->checkPassword(T2Utf(buf))) { SetDlgItemText(hwndDlg, IDC_HEADERBAR, TranslateT("Wrong old password entered!")); return false; } diff --git a/plugins/Dbx_mdbx/src/dbintf.h b/plugins/Dbx_mdbx/src/dbintf.h index cf3bda9553..0705359342 100644 --- a/plugins/Dbx_mdbx/src/dbintf.h +++ b/plugins/Dbx_mdbx/src/dbintf.h @@ -32,8 +32,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define DBMODE_SHARED 0x0001 #define DBMODE_READONLY 0x0002 -#define DBVT_ENCRYPTED 250 - #define MARKED_READ (DBEF_READ | DBEF_SENT) #include @@ -173,7 +171,7 @@ class CDbxMDBX : public MDatabaseCommon, public MIDatabaseChecker, public MZeroe // database stuff ptrW m_pwszProfileName; - bool m_safetyMode = true, m_bReadOnly, m_bEncrypted, m_bUsesPassword; + bool m_safetyMode = true, m_bReadOnly, m_bUsesPassword; MDBX_env *m_env; MDBX_txn *m_pWriteTran; @@ -278,8 +276,7 @@ public: STDMETHODIMP_(BOOL) EnumModuleNames(DBMODULEENUMPROC pFunc, void *pParam) override; - STDMETHODIMP_(BOOL) GetContactSettingWorker(MCONTACT contactID, const char *szModule, const char *szSetting, DBVARIANT *dbv, int isStatic) override; - STDMETHODIMP_(BOOL) WriteContactSetting(MCONTACT contactID, DBCONTACTWRITESETTING *dbcws) override; + STDMETHODIMP_(BOOL) WriteContactSettingWorker(MCONTACT contactID, DBCONTACTWRITESETTING &dbcws) override; STDMETHODIMP_(BOOL) DeleteContactSetting(MCONTACT contactID, const char *szModule, const char *szSetting) override; STDMETHODIMP_(BOOL) EnumContactSettings(MCONTACT hContact, DBSETTINGENUMPROC pfnEnumProc, const char *szModule, void *param) override; @@ -307,7 +304,4 @@ protected: STDMETHODIMP_(VOID) Destroy(); DBCHeckCallback *cb; - -public: - MICryptoEngine *m_crypto; }; diff --git a/plugins/Dbx_mdbx/src/dbsettings.cpp b/plugins/Dbx_mdbx/src/dbsettings.cpp index 429403a359..6a8f182125 100644 --- a/plugins/Dbx_mdbx/src/dbsettings.cpp +++ b/plugins/Dbx_mdbx/src/dbsettings.cpp @@ -82,233 +82,30 @@ void CDbxMDBX::FillSettings() ///////////////////////////////////////////////////////////////////////////////////////// -#define VLT(n) ((n == DBVT_UTF8 || n == DBVT_ENCRYPTED)?DBVT_ASCIIZ:n) - -static bool ValidLookupName(const char *szModule, const char *szSetting) -{ - if (!strcmp(szModule, META_PROTO)) - return strcmp(szSetting, "IsSubcontact") && strcmp(szSetting, "ParentMetaID"); - - return false; -} - -int CDbxMDBX::GetContactSettingWorker(MCONTACT contactID, const char *szModule, const char *szSetting, DBVARIANT *dbv, int isStatic) +BOOL CDbxMDBX::WriteContactSettingWorker(MCONTACT contactID, DBCONTACTWRITESETTING &dbcws) { - 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 faound, 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; -} - -BOOL CDbxMDBX::WriteContactSetting(MCONTACT contactID, DBCONTACTWRITESETTING *dbcws) -{ - if (dbcws == nullptr || dbcws->szSetting == nullptr || dbcws->szModule == nullptr || m_bReadOnly) - 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 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 resident settings we simply emulate change hook and return - if (szCachedSettingName[-1] != 0) { - lck.unlock(); - NotifyEventHooks(g_hevSettingChanged, contactID, (LPARAM)&dbcwNotif); - return 0; - } + size_t settingNameLen = mir_strlen(dbcws.szSetting); // write down a setting to database DBSettingKey *keyVal = (DBSettingKey *)_alloca(sizeof(DBSettingKey) + settingNameLen); keyVal->hContact = contactID; - keyVal->dwModuleId = GetModuleID(dbcws->szModule); - memcpy(&keyVal->szSettingName, dbcws->szSetting, settingNameLen + 1); + keyVal->dwModuleId = GetModuleID(dbcws.szModule); + memcpy(&keyVal->szSettingName, dbcws.szSetting, settingNameLen + 1); MDBX_val key = { keyVal, sizeof(DBSettingKey) + settingNameLen }, data; - switch (dbcwWork.value.type) { + switch (dbcws.value.type) { case DBVT_BYTE: data.iov_len = 2; break; case DBVT_WORD: data.iov_len = 3; break; case DBVT_DWORD: data.iov_len = 5; break; case DBVT_ASCIIZ: case DBVT_UTF8: - data.iov_len = 3 + dbcwWork.value.cchVal; break; + data.iov_len = 3 + dbcws.value.cchVal; break; case DBVT_BLOB: case DBVT_ENCRYPTED: - data.iov_len = 3 + dbcwWork.value.cpbVal; break; + data.iov_len = 3 + dbcws.value.cpbVal; break; default: return 1; @@ -317,24 +114,24 @@ BOOL CDbxMDBX::WriteContactSetting(MCONTACT contactID, DBCONTACTWRITESETTING *db data.iov_base = _alloca(data.iov_len); BYTE *pBlob = (BYTE*)data.iov_base; - *pBlob++ = dbcwWork.value.type; - switch (dbcwWork.value.type) { - case DBVT_BYTE: *pBlob = dbcwWork.value.bVal; break; - case DBVT_WORD: *(WORD*)pBlob = dbcwWork.value.wVal; break; - case DBVT_DWORD: *(DWORD*)pBlob = dbcwWork.value.dVal; break; + *pBlob++ = dbcws.value.type; + switch (dbcws.value.type) { + case DBVT_BYTE: *pBlob = dbcws.value.bVal; break; + case DBVT_WORD: *(WORD*)pBlob = dbcws.value.wVal; break; + case DBVT_DWORD: *(DWORD*)pBlob = dbcws.value.dVal; break; case DBVT_ASCIIZ: case DBVT_UTF8: - *(WORD*)pBlob = dbcwWork.value.cchVal; + *(WORD*)pBlob = dbcws.value.cchVal; pBlob += 2; - memcpy(pBlob, dbcwWork.value.pszVal, dbcwWork.value.cchVal); + memcpy(pBlob, dbcws.value.pszVal, dbcws.value.cchVal); break; case DBVT_BLOB: case DBVT_ENCRYPTED: - *(WORD*)pBlob = dbcwWork.value.cpbVal; + *(WORD*)pBlob = dbcws.value.cpbVal; pBlob += 2; - memcpy(pBlob, dbcwWork.value.pbVal, dbcwWork.value.cpbVal); + memcpy(pBlob, dbcws.value.pbVal, dbcws.value.cpbVal); } { @@ -343,11 +140,7 @@ BOOL CDbxMDBX::WriteContactSetting(MCONTACT contactID, DBCONTACTWRITESETTING *db return 1; } - // notify - lck.unlock(); - DBFlush(); - NotifyEventHooks(g_hevSettingChanged, contactID, (LPARAM)&dbcwNotif); return 0; } diff --git a/plugins/Dbx_mdbx/src/ui.cpp b/plugins/Dbx_mdbx/src/ui.cpp index c788d5b0ec..971f31c8db 100644 --- a/plugins/Dbx_mdbx/src/ui.cpp +++ b/plugins/Dbx_mdbx/src/ui.cpp @@ -48,7 +48,7 @@ static bool CheckOldPassword(HWND hwndDlg, CDbxMDBX *db) wchar_t buf[100]; GetDlgItemText(hwndDlg, IDC_OLDPASS, buf, _countof(buf)); pass_ptrA oldPass(mir_utf8encodeW(buf)); - if (!db->m_crypto->checkPassword(oldPass)) + if (!db->getCrypt()->checkPassword(oldPass)) { SetDlgItemText(hwndDlg, IDC_HEADERBAR, TranslateT("Wrong old password entered!")); return false; diff --git a/plugins/Dbx_sqlite/src/dbintf.h b/plugins/Dbx_sqlite/src/dbintf.h index 5b02d707b1..9fb06f84d8 100755 --- a/plugins/Dbx_sqlite/src/dbintf.h +++ b/plugins/Dbx_sqlite/src/dbintf.h @@ -34,9 +34,8 @@ private: sqlite3_stmt* cursor; }; -struct CDbxSQLite : public MDatabaseCommon, public MZeroedObject +class CDbxSQLite : public MDatabaseCommon, public MZeroedObject { -private: sqlite3 *m_db; sqlite3_stmt *evt_cur_fwd = nullptr, *evt_cur_backwd = nullptr; @@ -92,8 +91,7 @@ public: STDMETHODIMP_(BOOL) EnumModuleNames(DBMODULEENUMPROC pFunc, void *pParam) override; - STDMETHODIMP_(BOOL) GetContactSettingWorker(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv, int isStatic) override; - STDMETHODIMP_(BOOL) WriteContactSetting(MCONTACT contactID, DBCONTACTWRITESETTING *dbcws) override; + STDMETHODIMP_(BOOL) WriteContactSettingWorker(MCONTACT contactID, DBCONTACTWRITESETTING &dbcws) override; STDMETHODIMP_(BOOL) DeleteContactSetting(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting) override; STDMETHODIMP_(BOOL) EnumContactSettings(MCONTACT hContact, DBSETTINGENUMPROC pfnEnumProc, const char *szModule, void *param) override; diff --git a/plugins/Dbx_sqlite/src/dbsettings.cpp b/plugins/Dbx_sqlite/src/dbsettings.cpp index b4531c46e0..aab8f5f30c 100755 --- a/plugins/Dbx_sqlite/src/dbsettings.cpp +++ b/plugins/Dbx_sqlite/src/dbsettings.cpp @@ -24,6 +24,61 @@ void CDbxSQLite::InitSettings() for (auto &it : settings_stmts) sqlite3_prepare_v3(m_db, it.szQuery, -1, SQLITE_PREPARE_PERSISTENT, &it.pQuery, nullptr); + sqlite3_stmt *stmt = nullptr; + sqlite3_prepare_v2(m_db, "SELECT type, value, contact_id, module, setting FROM settings;", -1, &stmt, nullptr); + while (sqlite3_step(stmt) == SQLITE_ROW) { + MCONTACT hContact = sqlite3_column_int64(stmt, 2); + auto *szModule = (const char *)sqlite3_column_text(stmt, 3); + auto *szSetting = (const char *)sqlite3_column_text(stmt, 4); + + size_t settingNameLen = strlen(szSetting); + size_t moduleNameLen = strlen(szModule); + + char *szCachedSettingName = m_cache->GetCachedSetting(szModule, szSetting, moduleNameLen, settingNameLen); + + DBVARIANT *dbv = m_cache->GetCachedValuePtr(hContact, szCachedSettingName, 1); + if (dbv == nullptr) // garbage! a setting for removed/non-existent contact + continue; + + dbv->type = (int)sqlite3_column_int(stmt, 0); + switch (dbv->type) { + case DBVT_BYTE: + dbv->bVal = sqlite3_column_int(stmt, 1); + break; + + case DBVT_WORD: + dbv->wVal = sqlite3_column_int(stmt, 1); + break; + + case DBVT_DWORD: + dbv->dVal = sqlite3_column_int64(stmt, 1); + break; + + case DBVT_ASCIIZ: + case DBVT_UTF8: + dbv->cchVal = sqlite3_column_bytes(stmt, 1); + { + const char *value = (const char *)sqlite3_column_text(stmt, 1); + dbv->pszVal = (char *)mir_alloc(dbv->cchVal + 1); + memcpy(dbv->pszVal, value, dbv->cchVal); + dbv->pszVal[dbv->cchVal] = 0; + } + break; + + case DBVT_ENCRYPTED: + case DBVT_BLOB: + dbv->cpbVal = sqlite3_column_bytes(stmt, 1); + { + const char *data = (const char *)sqlite3_column_blob(stmt, 1); + dbv->pbVal = (BYTE *)mir_alloc(dbv->cpbVal + 1); + memcpy(dbv->pbVal, data, dbv->cpbVal); + dbv->pbVal[dbv->cpbVal] = 0; + } + break; + } + } + sqlite3_finalize(stmt); + FillContactSettings(); } @@ -33,6 +88,8 @@ void CDbxSQLite::UninitSettings() sqlite3_finalize(it.pQuery); } +///////////////////////////////////////////////////////////////////////////////////////// + BOOL CDbxSQLite::EnumModuleNames(DBMODULEENUMPROC pFunc, void *param) { LIST modules(100); @@ -55,223 +112,32 @@ BOOL CDbxSQLite::EnumModuleNames(DBMODULEENUMPROC pFunc, void *param) return result; } -static bool ValidLookupName(LPCSTR szModule, LPCSTR szSetting) -{ - if (!strcmp(szModule, META_PROTO)) - return strcmp(szSetting, "IsSubcontact") && strcmp(szSetting, "ParentMetaID"); - - if (!strcmp(szModule, "Ignore")) - return false; - - return true; -} +///////////////////////////////////////////////////////////////////////////////////////// -BOOL CDbxSQLite::GetContactSettingWorker(MCONTACT hContact, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv, int isStatic) +BOOL CDbxSQLite::WriteContactSettingWorker(MCONTACT hContact, DBCONTACTWRITESETTING &dbcws) { - if (szSetting == nullptr || szModule == nullptr) - return 1; - - DBCachedContact *cc = nullptr; - if (hContact) { - cc = m_cache->GetCachedContact(hContact); - if (cc == nullptr) - return 1; - } - - mir_cslock lock(m_csDbAccess); - -LBL_Seek: - char *cachedSettingName = m_cache->GetCachedSetting(szModule, szSetting, mir_strlen(szModule), mir_strlen(szSetting)); - DBVARIANT *pCachedValue = m_cache->GetCachedValuePtr(hContact, cachedSettingName, 0); - if (pCachedValue != nullptr) { - if (pCachedValue->type == DBVT_UTF8) { - int cbOrigLen = dbv->cchVal; - char *cbOrigPtr = dbv->pszVal; - memcpy(dbv, pCachedValue, sizeof(DBVARIANT)); - if (isStatic) { - int cbLen = 0; - if (pCachedValue->pszVal != nullptr) - cbLen = (int)mir_strlen(pCachedValue->pszVal); - - cbOrigLen--; - dbv->pszVal = cbOrigPtr; - if (cbLen < cbOrigLen) - cbOrigLen = cbLen; - memcpy(dbv->pszVal, pCachedValue->pszVal, cbOrigLen); - dbv->pszVal[cbOrigLen] = 0; - dbv->cchVal = cbLen; - } - else { - dbv->pszVal = (char *)mir_alloc(mir_strlen(pCachedValue->pszVal) + 1); - mir_strcpy(dbv->pszVal, pCachedValue->pszVal); - } - } - else memcpy(dbv, pCachedValue, sizeof(DBVARIANT)); - - return (pCachedValue->type == DBVT_DELETED) ? 1 : 0; - } - - // never look db for the resident variable - if (cachedSettingName[-1] != 0) - return 1; - - sqlite3_stmt *stmt = settings_stmts[SQL_SET_STMT_GET].pQuery; - sqlite3_bind_int64(stmt, 1, hContact); - sqlite3_bind_text(stmt, 2, szModule, (int)mir_strlen(szModule), nullptr); - sqlite3_bind_text(stmt, 3, szSetting, (int)mir_strlen(szSetting), nullptr); - int rc = sqlite3_step(stmt); - assert(rc == SQLITE_ROW || rc == SQLITE_DONE); - if (rc != SQLITE_ROW) { - sqlite3_reset(stmt); - if (rc == SQLITE_DONE && cc && cc->IsMeta() && ValidLookupName(szModule, szSetting)) { - if (hContact = db_mc_getDefault(hContact)) { - if (szModule = Proto_GetBaseAccountName(hContact)) - goto LBL_Seek; - } - } - return 1; - } - dbv->type = (int)sqlite3_column_int(stmt, 0); - switch (dbv->type) { - case DBVT_DELETED: - dbv->type = DBVT_DELETED; - sqlite3_reset(stmt); - return 2; - case DBVT_BYTE: - dbv->bVal = sqlite3_column_int(stmt, 1); - break; - case DBVT_WORD: - dbv->wVal = sqlite3_column_int(stmt, 1); - break; - case DBVT_DWORD: - dbv->dVal = sqlite3_column_int64(stmt, 1); - break; - case DBVT_UTF8: - dbv->cchVal = sqlite3_column_bytes(stmt, 1); - { - const char *value = (const char *)sqlite3_column_text(stmt, 1); - if (!isStatic) - dbv->pszVal = (char *)mir_alloc(dbv->cchVal + 1); - memcpy(dbv->pszVal, value, dbv->cchVal); - dbv->pszVal[dbv->cchVal] = 0; - } - break; - case DBVT_BLOB: - dbv->cpbVal = sqlite3_column_bytes(stmt, 1); - { - const char *data = (const char *)sqlite3_column_blob(stmt, 1); - if (!isStatic) - dbv->pbVal = (BYTE *)mir_alloc(dbv->cpbVal + 1); - memcpy(dbv->pbVal, data, dbv->cpbVal); - } - break; - } - sqlite3_reset(stmt); - - // add to cache - if (dbv->type != DBVT_BLOB) { - pCachedValue = m_cache->GetCachedValuePtr(hContact, cachedSettingName, 1); - if (pCachedValue != nullptr) - m_cache->SetCachedVariant(dbv, pCachedValue); - } - - return 0; -} - -BOOL CDbxSQLite::WriteContactSetting(MCONTACT hContact, DBCONTACTWRITESETTING *dbcws) -{ - if (dbcws == nullptr || dbcws->szSetting == nullptr || dbcws->szModule == nullptr) - return 1; - - if (hContact) { - DBCachedContact *cc = m_cache->GetCachedContact(hContact); - if (cc == nullptr) - return 1; - } - - DBCONTACTWRITESETTING dbcwNotif = *dbcws; - // we work only with utf-8 inside - switch (dbcwNotif.value.type) { - case DBVT_UTF8: - dbcwNotif.value.pszVal = mir_strdup(dbcws->value.pszVal); - break; - case DBVT_ASCIIZ: - { - ptrA value(mir_utf8encode(dbcws->value.pszVal)); - dbcwNotif.value.pszVal = NEWSTR_ALLOCA(value); - dbcwNotif.value.type = DBVT_UTF8; - break; - } - case DBVT_WCHAR: - { - T2Utf value(dbcwNotif.value.pwszVal); - dbcwNotif.value.pszVal = NEWSTR_ALLOCA(value); - dbcwNotif.value.type = DBVT_UTF8; - break; - } - } - DBCONTACTWRITESETTING dbcwWork = dbcwNotif; - if (dbcwWork.value.type == DBVT_UTF8) - dbcwWork.value.cchVal = (WORD)strlen(dbcwWork.value.pszVal); - - mir_cslockfull lock(m_csDbAccess); - - char *cachedSettingName = m_cache->GetCachedSetting(dbcwWork.szModule, dbcwWork.szSetting, mir_strlen(dbcwWork.szModule), mir_strlen(dbcwWork.szSetting)); - bool isResident = cachedSettingName[-1] != 0; - - // we don't cache blobs - if (dbcwWork.value.type != DBVT_BLOB) { - DBVARIANT *cachedValue = m_cache->GetCachedValuePtr(hContact, cachedSettingName, 1); - if (cachedValue != nullptr) { - bool isIdentical = false; - if (cachedValue->type == dbcwWork.value.type) { - switch (dbcwWork.value.type) { - case DBVT_BYTE: - isIdentical = cachedValue->bVal == dbcwWork.value.bVal; - break; - case DBVT_WORD: - isIdentical = cachedValue->wVal == dbcwWork.value.wVal; - break; - case DBVT_DWORD: - isIdentical = cachedValue->dVal == dbcwWork.value.dVal; - break; - case DBVT_UTF8: - isIdentical = mir_strcmp(cachedValue->pszVal, dbcwWork.value.pszVal) == 0; - break; - } - if (isIdentical) - return 0; - } - m_cache->SetCachedVariant(&dbcwWork.value, cachedValue); - } - if (isResident) { - lock.unlock(); - NotifyEventHooks(g_hevSettingChanged, hContact, (LPARAM)&dbcwWork); - return 0; - } - } - else m_cache->GetCachedValuePtr(hContact, cachedSettingName, -1); - sqlite3_stmt *stmt = settings_stmts[SQL_SET_STMT_REPLACE].pQuery; sqlite3_bind_int64(stmt, 1, hContact); - sqlite3_bind_text(stmt, 2, dbcwWork.szModule, (int)mir_strlen(dbcwWork.szModule), nullptr); - sqlite3_bind_text(stmt, 3, dbcwWork.szSetting, (int)mir_strlen(dbcwWork.szSetting), nullptr); - sqlite3_bind_int(stmt, 4, dbcwWork.value.type); - switch (dbcwWork.value.type) { + sqlite3_bind_text(stmt, 2, dbcws.szModule, (int)mir_strlen(dbcws.szModule), nullptr); + sqlite3_bind_text(stmt, 3, dbcws.szSetting, (int)mir_strlen(dbcws.szSetting), nullptr); + sqlite3_bind_int(stmt, 4, dbcws.value.type); + switch (dbcws.value.type) { case DBVT_BYTE: - sqlite3_bind_int(stmt, 5, dbcwWork.value.bVal); + sqlite3_bind_int(stmt, 5, dbcws.value.bVal); break; case DBVT_WORD: - sqlite3_bind_int(stmt, 5, dbcwWork.value.wVal); + sqlite3_bind_int(stmt, 5, dbcws.value.wVal); break; case DBVT_DWORD: - sqlite3_bind_int64(stmt, 5, dbcwWork.value.dVal); + sqlite3_bind_int64(stmt, 5, dbcws.value.dVal); break; + case DBVT_ASCIIZ: case DBVT_UTF8: - sqlite3_bind_text(stmt, 5, dbcwWork.value.pszVal, dbcwWork.value.cchVal, nullptr); + sqlite3_bind_text(stmt, 5, dbcws.value.pszVal, dbcws.value.cchVal, nullptr); break; + case DBVT_ENCRYPTED: case DBVT_BLOB: - sqlite3_bind_blob(stmt, 5, dbcwWork.value.pbVal, dbcwWork.value.cpbVal, nullptr); + sqlite3_bind_blob(stmt, 5, dbcws.value.pbVal, dbcws.value.cpbVal, nullptr); break; } @@ -281,13 +147,11 @@ BOOL CDbxSQLite::WriteContactSetting(MCONTACT hContact, DBCONTACTWRITESETTING *d if (rc != SQLITE_DONE) return 1; - lock.unlock(); - - NotifyEventHooks(g_hevSettingChanged, hContact, (LPARAM)&dbcwNotif); - return 0; } +///////////////////////////////////////////////////////////////////////////////////////// + BOOL CDbxSQLite::DeleteContactSetting(MCONTACT hContact, LPCSTR szModule, LPCSTR szSetting) { if (szSetting == nullptr || szModule == nullptr) @@ -329,6 +193,8 @@ BOOL CDbxSQLite::DeleteContactSetting(MCONTACT hContact, LPCSTR szModule, LPCSTR return 0; } +///////////////////////////////////////////////////////////////////////////////////////// + BOOL CDbxSQLite::EnumContactSettings(MCONTACT hContact, DBSETTINGENUMPROC pfnEnumProc, const char *szModule, void *param) { if (szModule == nullptr) diff --git a/plugins/Import/src/dbrw/dbintf.h b/plugins/Import/src/dbrw/dbintf.h index e6a171f87d..4749e8146d 100644 --- a/plugins/Import/src/dbrw/dbintf.h +++ b/plugins/Import/src/dbrw/dbintf.h @@ -148,7 +148,7 @@ public: STDMETHODIMP_(BOOL) EnumModuleNames(DBMODULEENUMPROC pFunc, void *pParam) override; STDMETHODIMP_(BOOL) GetContactSettingWorker(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv, int isStatic) override; - STDMETHODIMP_(BOOL) WriteContactSetting(MCONTACT contactID, DBCONTACTWRITESETTING *dbcws) override; + STDMETHODIMP_(BOOL) WriteContactSettingWorker(MCONTACT contactID, DBCONTACTWRITESETTING &dbcws) override; STDMETHODIMP_(BOOL) DeleteContactSetting(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting) override; STDMETHODIMP_(BOOL) EnumContactSettings(MCONTACT hContact, DBSETTINGENUMPROC pfnEnumProc, const char *szModule, void *param) override; diff --git a/plugins/Import/src/dbrw/dbsettings.cpp b/plugins/Import/src/dbrw/dbsettings.cpp index 1b233e601f..b09f1675b6 100644 --- a/plugins/Import/src/dbrw/dbsettings.cpp +++ b/plugins/Import/src/dbrw/dbsettings.cpp @@ -148,14 +148,14 @@ STDMETHODIMP_(BOOL) CDbxSQLite::GetContactSettingWorker(MCONTACT contactID, LPCS return 0; } -STDMETHODIMP_(BOOL) CDbxSQLite::WriteContactSetting(MCONTACT, DBCONTACTWRITESETTING*) +STDMETHODIMP_(BOOL) CDbxSQLite::WriteContactSettingWorker(MCONTACT, DBCONTACTWRITESETTING&) { - return FALSE; + return 1; } STDMETHODIMP_(BOOL) CDbxSQLite::DeleteContactSetting(MCONTACT, LPCSTR, LPCSTR) { - return FALSE; + return 1; } STDMETHODIMP_(BOOL) CDbxSQLite::EnumContactSettings(MCONTACT hContact, DBSETTINGENUMPROC pfnEnumProc, const char *szModule, void *param) 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; @@ -344,6 +459,105 @@ STDMETHODIMP_(BOOL) MDatabaseCommon::FreeVariant(DBVARIANT *dbv) return 0; } +///////////////////////////////////////////////////////////////////////////////////////// + +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 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 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 -- cgit v1.2.3