summaryrefslogtreecommitdiff
path: root/plugins/dbrw/src/dbrw.c
diff options
context:
space:
mode:
authoraunsane <aunsane@gmail.com>2018-03-03 20:36:35 +0300
committeraunsane <aunsane@gmail.com>2018-03-03 20:36:35 +0300
commit51022062562449eb9679a931bdc5cb4d62aca682 (patch)
tree93a56d484b80b0eab1eebef9e1fb067d7ea3e7be /plugins/dbrw/src/dbrw.c
parentfa58f69fe117640e29cefb1b699bede4d045bc2f (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.c311
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;
+}