diff options
author | aunsane <aunsane@gmail.com> | 2018-03-03 20:36:35 +0300 |
---|---|---|
committer | aunsane <aunsane@gmail.com> | 2018-03-03 20:36:35 +0300 |
commit | 51022062562449eb9679a931bdc5cb4d62aca682 (patch) | |
tree | 93a56d484b80b0eab1eebef9e1fb067d7ea3e7be /plugins/dbrw/src/dbrw.c | |
parent | fa58f69fe117640e29cefb1b699bede4d045bc2f (diff) |
Tox: #1156
- more accurate transfer management
- unlockong file on transfer pause
- added additional logs
- cleanup
Diffstat (limited to 'plugins/dbrw/src/dbrw.c')
-rw-r--r-- | plugins/dbrw/src/dbrw.c | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/plugins/dbrw/src/dbrw.c b/plugins/dbrw/src/dbrw.c new file mode 100644 index 0000000000..204b596e14 --- /dev/null +++ b/plugins/dbrw/src/dbrw.c @@ -0,0 +1,311 @@ +/* +dbRW + +Copyright 2000-2017 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +PLUGININFOEX pluginInfo = +{ + sizeof(PLUGININFOEX), + __PLUGIN_NAME, + PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), + __DESCRIPTION, + __AUTHOR, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + // {F3CA0E5E-249A-40f0-8D74-80A80EF0C83D} + {0xf3ca0e5e, 0x249a, 0x40f0, {0x8d, 0x74, 0x80, 0xa8, 0xe, 0xf0, 0xc8, 0x3d}} +}; + +HINSTANCE g_hInst; + +sqlite3 *g_sqlite; +char g_szDbPath[MAX_PATH]; +HANDLE hSettingChangeEvent; +HANDLE hContactDeletedEvent; +HANDLE hContactAddedEvent; +HANDLE hEventFilterAddedEvent; +HANDLE hEventAddedEvent; +HANDLE hEventDeletedEvent; + +enum { + DBRW_TABLE_SETTINGS = 0, + DBRW_TABLE_CONTACTS, + DBRW_TABLE_EVENTS, + DBRW_TABLE_CORE, + DBRW_TABLE_COUNT +}; + +char *dbrw_tables[DBRW_TABLE_COUNT] = { +"create table dbrw_settings (id integer, module varchar(255), setting varchar(255), type integer, val any, primary key(id,module,setting));", +"create table dbrw_contacts (id integer primary key,createtime integer);", +"create table dbrw_events (id integer primary key,eventtime integer,flags integer,eventtype integer, blob any, blobsize integer, contactid integer,modulename varchar(255),inserttime integer);", +"create table dbrw_core (setting varchar(255) primary key not null, val any);" +}; + +char* utf8_encode(const char* src) { + size_t len; + char* result; + wchar_t* tempBuf; + + if (src == NULL) + return NULL; + len = strlen(src); + result = (char*)malloc(len * 3 + 1); + if (result == NULL) + return NULL; + tempBuf = (wchar_t*)alloca((len + 1) * sizeof(wchar_t)); + MultiByteToWideChar(CP_ACP, 0, src, -1, tempBuf, (int)len); + tempBuf[len] = 0; + { + wchar_t* s = tempBuf; + BYTE* d = (BYTE*)result; + + while (*s) { + int U = *s++; + + if (U < 0x80) { + *d++ = (BYTE)U; + } + else if (U < 0x800) { + *d++ = 0xC0 + ((U >> 6) & 0x3F); + *d++ = 0x80 + (U & 0x003F); + } + else { + *d++ = 0xE0 + (U >> 12); + *d++ = 0x80 + ((U >> 6) & 0x3F); + *d++ = 0x80 + (U & 0x3F); + } + } + *d = 0; + } + return result; +} + +static int dbrw_makeDatabase(char *profile, int *error) { + sqlite3 *sql = NULL; + int rc; + char *szPath = utf8_encode(profile); + + rc = sqlite3_open(szPath, &sql); + free(szPath); + if (rc == SQLITE_OK) { + int x; + + sqlite3_exec(sql, "PRAGMA page_size = 8192;", NULL, NULL, NULL); + for (x = 0; x < DBRW_TABLE_COUNT; x++) { + rc = sqlite3_exec(sql, dbrw_tables[x], NULL, NULL, NULL); + if (rc != SQLITE_OK) + break; + } + if (rc == SQLITE_OK) { + sqlite3_exec(sql, "CREATE INDEX idx_settings1 ON dbrw_settings(id, module, setting);", NULL, NULL, NULL); + sqlite3_exec(sql, "CREATE INDEX idx_settings2 ON dbrw_settings(id, module);", NULL, NULL, NULL); + sqlite3_exec(sql, "CREATE INDEX idx_settings3 ON dbrw_settings(module);", NULL, NULL, NULL); + sqlite3_exec(sql, "CREATE INDEX idx_events1 ON dbrw_events(contactid);", NULL, NULL, NULL); + sqlite3_exec(sql, "CREATE INDEX idx_events2 ON dbrw_events(id,contactid);", NULL, NULL, NULL); + sqlite3_exec(sql, "INSERT INTO dbrw_core VALUES(\"SchemaVersion\",\"" DBRW_SCHEMA_VERSION "\");", NULL, NULL, NULL); + } + } + sqlite3_close(sql); + rc = (rc == SQLITE_OK) ? 0 : 1; + if (error != NULL) *error = rc; + return rc; +} + +static int dbrw_grokHeader(char *profile, int *error) { + HANDLE hFile = CreateFileA(profile, GENERIC_READ, 0, NULL, OPEN_ALWAYS, 0, NULL); + int rc = 1; + int err = EGROKPRF_CANTREAD; + + if (hFile != INVALID_HANDLE_VALUE) { + BOOL r; + char buf[64]; + DWORD dwRead; + + ZeroMemory(buf, sizeof(buf)); + r = ReadFile(hFile, buf, sizeof(buf), &dwRead, NULL); + CloseHandle(hFile); + if (r && memcmp(buf, DBRW_HEADER_STR, strlen(DBRW_HEADER_STR)) == 0) { + sqlite3 *sqlcheck = NULL; + char *szPath = utf8_encode(profile); + + rc = sqlite3_open(szPath, &sqlcheck); + free(szPath); + if (rc == SQLITE_OK) { + sqlite3_stmt *stmt; + err = EGROKPRF_UNKHEADER; + + sqlite3_prepare_v2(sqlcheck, "select * from sqlite_master where type = 'table' and name = 'dbrw_core';", -1, &stmt, NULL); + if (sqlite3_step(stmt) == SQLITE_ROW) { + + sqlite3_finalize(stmt); + sqlite3_prepare_v2(sqlcheck, "select val from dbrw_core where setting = 'SchemaVersion';", -1, &stmt, NULL); + if (sqlite3_step(stmt) == SQLITE_ROW) { + int sVersion; + + sVersion = sqlite3_column_int(stmt, 0); + if (sVersion == atoi(DBRW_SCHEMA_VERSION)) + rc = 0; + else { + // TODO: Return as valid and upgrade in + // dbrw_Load() if schema version is upgradable + } + } + } + sqlite3_finalize(stmt); + sqlite3_close(sqlcheck); + } + } + else err = r ? EGROKPRF_UNKHEADER : EGROKPRF_CANTREAD; + } + if (error != NULL) + *error = err; + return rc; +} + +static int dbrw_Load(char *profile, void *link) +{ + { + char *szLocalPath = mir_utf8encode(profile); + mir_snprintf(g_szDbPath, sizeof(g_szDbPath), "%s", szLocalPath); + mir_free(szLocalPath); + } + sql_init(); // intialize sqlite library routines + if (sql_open(g_szDbPath, &g_sqlite) != SQLITE_OK) + return 1; +#ifdef DBRW_LOGGING + utils_log_init(); +#endif + log2("Loading SQLite Driver v%s (SQLite v%s)", DBRW_VER_STRING, SQLITE_VERSION); + utils_vacuum_check(); + { + sql_exec(g_sqlite, "BEGIN TRANSACTION;"); + sql_exec(g_sqlite, "PRAGMA locking_mode = EXCLUSIVE;"); + sql_exec(g_sqlite, "PRAGMA synchronous = NORMAL;"); + sql_exec(g_sqlite, "PRAGMA cache_size = 6000;"); + sql_exec(g_sqlite, "PRAGMA temp_store = MEMORY;"); + sql_exec(g_sqlite, "COMMIT;"); + } + + // Create Services + /*CreateServiceFunction(MS_DB_SETSAFETYMODE, utils_setSafetyMode); + CreateServiceFunction(MS_DB_CONTACT_GETSETTING, setting_getSetting); + CreateServiceFunction(MS_DB_CONTACT_GETSETTING_STR, setting_getSettingStr); + CreateServiceFunction(MS_DB_CONTACT_GETSETTINGSTATIC, setting_getSettingStatic); + CreateServiceFunction(MS_DB_CONTACT_FREEVARIANT, setting_freeVariant); + CreateServiceFunction(MS_DB_CONTACT_WRITESETTING, setting_writeSetting); + CreateServiceFunction(MS_DB_CONTACT_DELETESETTING, setting_deleteSetting); + CreateServiceFunction(MS_DB_CONTACT_ENUMSETTINGS, setting_enumSettings); + CreateServiceFunction(MS_DB_SETSETTINGRESIDENT, settings_setResident); + CreateServiceFunction(MS_DB_CONTACT_GETCOUNT, contacts_getCount); + CreateServiceFunction(MS_DB_CONTACT_FINDFIRST, contacts_findFirst); + CreateServiceFunction(MS_DB_CONTACT_FINDNEXT, contacts_findNext); + CreateServiceFunction(MS_DB_CONTACT_DELETE, contacts_delete); + CreateServiceFunction(MS_DB_CONTACT_ADD, contacts_add); + CreateServiceFunction(MS_DB_CONTACT_IS, contacts_isContact); + CreateServiceFunction(MS_DB_EVENT_GETCOUNT, events_getCount); + CreateServiceFunction(MS_DB_EVENT_ADD, events_add); + CreateServiceFunction(MS_DB_EVENT_DELETE, events_delete); + CreateServiceFunction(MS_DB_EVENT_GETBLOBSIZE, events_getBlobSize); + CreateServiceFunction(MS_DB_EVENT_GET, events_get); + CreateServiceFunction(MS_DB_EVENT_MARKREAD, events_markRead); + CreateServiceFunction(MS_DB_EVENT_GETCONTACT, events_getContact); + CreateServiceFunction(MS_DB_EVENT_FINDFIRST, events_findFirst); + CreateServiceFunction(MS_DB_EVENT_FINDFIRSTUNREAD, events_findFirstUnread); + CreateServiceFunction(MS_DB_EVENT_FINDLAST, events_findLast); + CreateServiceFunction(MS_DB_EVENT_FINDNEXT, events_findNext); + CreateServiceFunction(MS_DB_EVENT_FINDPREV, events_findPrev); + CreateServiceFunction(MS_DB_CRYPT_ENCODESTRING, utils_encodeString); + CreateServiceFunction(MS_DB_CRYPT_DECODESTRING, utils_decodeString); + CreateServiceFunction(MS_DB_MODULES_ENUM, setting_modulesEnum);*/ + + // Events Hooks + hSettingChangeEvent = CreateHookableEvent(ME_DB_CONTACT_SETTINGCHANGED); + hContactDeletedEvent = CreateHookableEvent(ME_DB_CONTACT_DELETED); + hContactAddedEvent = CreateHookableEvent(ME_DB_CONTACT_ADDED); + hEventFilterAddedEvent = CreateHookableEvent(ME_DB_EVENT_FILTER_ADD); + hEventAddedEvent = CreateHookableEvent(ME_DB_EVENT_ADDED); + hEventDeletedEvent = CreateHookableEvent(ME_DB_EVENT_DELETED); + + // Initialize modules + contacts_init(); + settings_init(); + events_init(); + + // Prepare SQL statements + sql_prepare_statements(); + + return 0; +} + +static int dbrw_Unload(int wasLoaded) { + if (!wasLoaded) + return 0; + events_destroy(); + settings_destroy(); + contacts_destroy(); + sql_close(g_sqlite); + sql_destroy(); + log0("SQLite Driver unloaded sucessfully"); +#ifdef DBRW_LOGGING + utils_log_destroy(); +#endif + return 0; +} + +static DATABASELINK dblink = +{ + sizeof(DATABASELINK), + "dbrw", + L"dbx SQLite driver", + dbrw_makeDatabase, + dbrw_grokHeader, + dbrw_Load, + dbrw_Unload +}; + +///////////////////////////////////////////////////////////////////////////////////////// + +BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD, LPVOID) +{ + g_hInst = hInstDLL; + return TRUE; +} + +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) +{ + return &pluginInfo; +} + +extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_DATABASE, MIID_LAST }; + +extern "C" __declspec(dllexport) int Load(void) +{ + RegisterDatabasePlugin(&dblink); + return 1; +} + +extern "C" __declspec(dllexport) int Unload(void) +{ + return 0; +} |