From 1979fd80424d16b2e489f9b57d01d9c7811d25a2 Mon Sep 17 00:00:00 2001 From: dartraiden Date: Mon, 2 Jan 2023 21:10:29 +0300 Subject: Update copyrights --- plugins/Import/src/dbrw/dbcontacts.cpp | 136 +-- plugins/Import/src/dbrw/dbevents.cpp | 390 ++++----- plugins/Import/src/dbrw/dbintf.cpp | 174 ++-- plugins/Import/src/dbrw/dbintf.h | 318 +++---- plugins/Import/src/dbrw/dbrw.cpp | 210 ++--- plugins/Import/src/dbrw/dbrw.h | 60 +- plugins/Import/src/dbrw/dbsettings.cpp | 342 ++++---- plugins/Import/src/dbrw/dbsql.cpp | 324 +++---- plugins/Import/src/import.cpp | 2 +- plugins/Import/src/main.cpp | 2 +- plugins/Import/src/mcontacts.cpp | 644 +++++++------- plugins/Import/src/miranda.cpp | 2 +- plugins/Import/src/patterns.cpp | 1464 ++++++++++++++++---------------- plugins/Import/src/progress.cpp | 2 +- plugins/Import/src/stdafx.cxx | 2 +- plugins/Import/src/stdafx.h | 2 +- plugins/Import/src/textjson.cpp | 538 ++++++------ plugins/Import/src/ui.cpp | 260 +++--- plugins/Import/src/utils.cpp | 2 +- plugins/Import/src/version.h | 2 +- plugins/Import/src/wizard.cpp | 2 +- 21 files changed, 2439 insertions(+), 2439 deletions(-) (limited to 'plugins/Import/src') diff --git a/plugins/Import/src/dbrw/dbcontacts.cpp b/plugins/Import/src/dbrw/dbcontacts.cpp index ce5fd91a6d..bd989afb47 100644 --- a/plugins/Import/src/dbrw/dbcontacts.cpp +++ b/plugins/Import/src/dbrw/dbcontacts.cpp @@ -1,68 +1,68 @@ -/* - -Import plugin for Miranda NG - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) - -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" - -void CDbxSQLite::FillContacts() -{ - sqlite3_stmt *st = nullptr; - if (sql_prepare(m_sqlite, "SELECT c.id, s.val FROM dbrw_contacts as c INNER JOIN dbrw_settings as s on s.id = c.id WHERE s.module = 'Protocol' and s.setting = 'p';", &st) != SQLITE_OK) - return; - - while (sql_step(st) == SQLITE_ROW) { - MCONTACT contactID = sqlite3_column_int(st, 0); - const char *proto = (const char*)sqlite3_column_text(st, 1); - DBCachedContact *cc = m_cache->AddContactToCache(contactID); - cc->szProto = mir_strdup(proto); - } - sql_finalize(st); -} - -STDMETHODIMP_(BOOL) CDbxSQLite::IsDbContact(MCONTACT contactID) -{ - DBCachedContact *cc = m_cache->GetCachedContact(contactID); - return (cc != nullptr); -} - -STDMETHODIMP_(int) CDbxSQLite::GetContactCount(void) -{ - int res = 0; - if (sql_step(ctc_stmts_prep[SQL_CTC_STMT_COUNT]) == SQLITE_ROW) - res = sqlite3_column_int(ctc_stmts_prep[SQL_CTC_STMT_COUNT], 0); - sql_reset(ctc_stmts_prep[SQL_CTC_STMT_COUNT]); - return res; -} - -STDMETHODIMP_(int) CDbxSQLite::GetContactSize(void) -{ - return sizeof(DBCachedContact); -} - -STDMETHODIMP_(MCONTACT) CDbxSQLite::AddContact(void) -{ - return INVALID_CONTACT_ID; -} - -STDMETHODIMP_(int) CDbxSQLite::DeleteContact(MCONTACT) -{ - return 1; -} +/* + +Import plugin for Miranda NG + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) + +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" + +void CDbxSQLite::FillContacts() +{ + sqlite3_stmt *st = nullptr; + if (sql_prepare(m_sqlite, "SELECT c.id, s.val FROM dbrw_contacts as c INNER JOIN dbrw_settings as s on s.id = c.id WHERE s.module = 'Protocol' and s.setting = 'p';", &st) != SQLITE_OK) + return; + + while (sql_step(st) == SQLITE_ROW) { + MCONTACT contactID = sqlite3_column_int(st, 0); + const char *proto = (const char*)sqlite3_column_text(st, 1); + DBCachedContact *cc = m_cache->AddContactToCache(contactID); + cc->szProto = mir_strdup(proto); + } + sql_finalize(st); +} + +STDMETHODIMP_(BOOL) CDbxSQLite::IsDbContact(MCONTACT contactID) +{ + DBCachedContact *cc = m_cache->GetCachedContact(contactID); + return (cc != nullptr); +} + +STDMETHODIMP_(int) CDbxSQLite::GetContactCount(void) +{ + int res = 0; + if (sql_step(ctc_stmts_prep[SQL_CTC_STMT_COUNT]) == SQLITE_ROW) + res = sqlite3_column_int(ctc_stmts_prep[SQL_CTC_STMT_COUNT], 0); + sql_reset(ctc_stmts_prep[SQL_CTC_STMT_COUNT]); + return res; +} + +STDMETHODIMP_(int) CDbxSQLite::GetContactSize(void) +{ + return sizeof(DBCachedContact); +} + +STDMETHODIMP_(MCONTACT) CDbxSQLite::AddContact(void) +{ + return INVALID_CONTACT_ID; +} + +STDMETHODIMP_(int) CDbxSQLite::DeleteContact(MCONTACT) +{ + return 1; +} diff --git a/plugins/Import/src/dbrw/dbevents.cpp b/plugins/Import/src/dbrw/dbevents.cpp index 97091d0ab3..06995bd4a9 100644 --- a/plugins/Import/src/dbrw/dbevents.cpp +++ b/plugins/Import/src/dbrw/dbevents.cpp @@ -1,195 +1,195 @@ -/* - -Import plugin for Miranda NG - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) - -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" - -STDMETHODIMP_(int) CDbxSQLite::GetEventCount(MCONTACT contactID) -{ - mir_cslock lock(m_csDbAccess); - - int res = 0; - sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_COUNT], 1, contactID); - if (sql_step(evt_stmts_prep[SQL_EVT_STMT_COUNT]) == SQLITE_ROW) - res = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_COUNT], 0); - sql_reset(evt_stmts_prep[SQL_EVT_STMT_COUNT]); - return res; -} - -STDMETHODIMP_(MEVENT) CDbxSQLite::AddEvent(MCONTACT, const DBEVENTINFO*) -{ - return 0; -} - -STDMETHODIMP_(BOOL) CDbxSQLite::DeleteEvent(MEVENT) -{ - return FALSE; -} - -BOOL CDbxSQLite::EditEvent(MCONTACT, MEVENT, const DBEVENTINFO*) -{ - return 1; -} - -STDMETHODIMP_(int) CDbxSQLite::GetBlobSize(MEVENT hDbEvent) -{ - mir_cslock lock(m_csDbAccess); - - int res = -1; - sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_BLOBSIZE]; - sqlite3_bind_int(stmt, 1, hDbEvent); - if (sql_step(stmt) == SQLITE_ROW) - res = sqlite3_column_int(stmt, 0); - sql_reset(stmt); - return res; -} - -STDMETHODIMP_(BOOL) CDbxSQLite::GetEvent(MEVENT hDbEvent, DBEVENTINFO *dbei) -{ - if (dbei == nullptr) - return 1; - - if (dbei->cbBlob > 0 && dbei->pBlob == nullptr) { - dbei->cbBlob = 0; - return 1; - } - - mir_cslock lock(m_csDbAccess); - - int res = 1; - sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_GET]; - sqlite3_bind_int(stmt, 1, hDbEvent); - if (sql_step(stmt) == SQLITE_ROW) { - const void *blob = sqlite3_column_blob(stmt, 4); - - dbei->timestamp = (uint32_t)sqlite3_column_int(stmt, 1); - dbei->flags = (uint32_t)sqlite3_column_int(stmt, 2); - dbei->eventType = (uint16_t)sqlite3_column_int(stmt, 3); - dbei->szModule = mir_strdup((char*)sqlite3_column_text(stmt, 7)); - - uint32_t cbBlob = sqlite3_column_int(stmt, 5); - size_t bytesToCopy = cbBlob; - if (dbei->cbBlob == -1) - dbei->pBlob = (uint8_t*)mir_calloc(cbBlob + 2); - else if (dbei->cbBlob < cbBlob) - bytesToCopy = dbei->cbBlob; - - dbei->cbBlob = cbBlob; - if (bytesToCopy && dbei->pBlob) - memcpy(dbei->pBlob, blob, bytesToCopy); - res = 0; - } - sql_reset(stmt); - return res; -} - -STDMETHODIMP_(BOOL) CDbxSQLite::MarkEventRead(MCONTACT, MEVENT) -{ - return FALSE; -} - -STDMETHODIMP_(MCONTACT) CDbxSQLite::GetEventContact(MEVENT hDbEvent) -{ - mir_cslock lock(m_csDbAccess); - - int res = INVALID_CONTACT_ID; - sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_GETCONTACT]; - sqlite3_bind_int(stmt, 1, hDbEvent); - if (sql_step(stmt) == SQLITE_ROW) - res = sqlite3_column_int(stmt, 0); - sql_reset(stmt); - return res; -} - -STDMETHODIMP_(MEVENT) CDbxSQLite::FindFirstEvent(MCONTACT contactID) -{ - mir_cslock lock(m_csDbAccess); - - int res = 0; - sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDFIRST], 1, contactID); - if (sql_step(evt_stmts_prep[SQL_EVT_STMT_FINDFIRST]) == SQLITE_ROW) - res = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_FINDFIRST], 0); - sql_reset(evt_stmts_prep[SQL_EVT_STMT_FINDFIRST]); - return res; -} - -STDMETHODIMP_(MEVENT) CDbxSQLite::FindFirstUnreadEvent(MCONTACT contactID) -{ - mir_cslock lock(m_csDbAccess); - - int res = 0; - uint32_t flags = 0; - sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDFIRSTUNREAD], 1, contactID); - while (sql_step(evt_stmts_prep[SQL_EVT_STMT_FINDFIRSTUNREAD]) == SQLITE_ROW) { - flags = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_FINDFIRSTUNREAD], 0); - if (!(flags & (DBEF_READ | DBEF_SENT))) { - res = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_FINDFIRSTUNREAD], 1); - sql_reset(evt_stmts_prep[SQL_EVT_STMT_FINDFIRSTUNREAD]); - return res; - } - } - sql_reset(evt_stmts_prep[SQL_EVT_STMT_FINDFIRSTUNREAD]); - return res; -} - -STDMETHODIMP_(MEVENT) CDbxSQLite::FindLastEvent(MCONTACT contactID) -{ - mir_cslock lock(m_csDbAccess); - - int res = 0; - sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDLAST], 1, contactID); - if (sql_step(evt_stmts_prep[SQL_EVT_STMT_FINDLAST]) == SQLITE_ROW) - res = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_FINDLAST], 0); - sql_reset(evt_stmts_prep[SQL_EVT_STMT_FINDLAST]); - return res; -} - -STDMETHODIMP_(MEVENT) CDbxSQLite::FindNextEvent(MCONTACT contactID, MEVENT hDbEvent) -{ - if (hDbEvent == NULL) - return 0; - - mir_cslock lock(m_csDbAccess); - - int res = 0; - sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDNEXT], 1, contactID); - sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDNEXT], 2, hDbEvent); - if (sql_step(evt_stmts_prep[SQL_EVT_STMT_FINDNEXT]) == SQLITE_ROW) - res = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_FINDNEXT], 0); - sql_reset(evt_stmts_prep[SQL_EVT_STMT_FINDNEXT]); - return res; -} - -STDMETHODIMP_(MEVENT) CDbxSQLite::FindPrevEvent(MCONTACT contactID, MEVENT hDbEvent) -{ - if (!hDbEvent) - return 0; - - mir_cslock lock(m_csDbAccess); - - int res = 0; - sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDPREV], 1, contactID); - sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDPREV], 2, hDbEvent); - if (sql_step(evt_stmts_prep[SQL_EVT_STMT_FINDPREV]) == SQLITE_ROW) - res = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_FINDPREV], 0); - sql_reset(evt_stmts_prep[SQL_EVT_STMT_FINDPREV]); - return res; -} +/* + +Import plugin for Miranda NG + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) + +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" + +STDMETHODIMP_(int) CDbxSQLite::GetEventCount(MCONTACT contactID) +{ + mir_cslock lock(m_csDbAccess); + + int res = 0; + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_COUNT], 1, contactID); + if (sql_step(evt_stmts_prep[SQL_EVT_STMT_COUNT]) == SQLITE_ROW) + res = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_COUNT], 0); + sql_reset(evt_stmts_prep[SQL_EVT_STMT_COUNT]); + return res; +} + +STDMETHODIMP_(MEVENT) CDbxSQLite::AddEvent(MCONTACT, const DBEVENTINFO*) +{ + return 0; +} + +STDMETHODIMP_(BOOL) CDbxSQLite::DeleteEvent(MEVENT) +{ + return FALSE; +} + +BOOL CDbxSQLite::EditEvent(MCONTACT, MEVENT, const DBEVENTINFO*) +{ + return 1; +} + +STDMETHODIMP_(int) CDbxSQLite::GetBlobSize(MEVENT hDbEvent) +{ + mir_cslock lock(m_csDbAccess); + + int res = -1; + sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_BLOBSIZE]; + sqlite3_bind_int(stmt, 1, hDbEvent); + if (sql_step(stmt) == SQLITE_ROW) + res = sqlite3_column_int(stmt, 0); + sql_reset(stmt); + return res; +} + +STDMETHODIMP_(BOOL) CDbxSQLite::GetEvent(MEVENT hDbEvent, DBEVENTINFO *dbei) +{ + if (dbei == nullptr) + return 1; + + if (dbei->cbBlob > 0 && dbei->pBlob == nullptr) { + dbei->cbBlob = 0; + return 1; + } + + mir_cslock lock(m_csDbAccess); + + int res = 1; + sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_GET]; + sqlite3_bind_int(stmt, 1, hDbEvent); + if (sql_step(stmt) == SQLITE_ROW) { + const void *blob = sqlite3_column_blob(stmt, 4); + + dbei->timestamp = (uint32_t)sqlite3_column_int(stmt, 1); + dbei->flags = (uint32_t)sqlite3_column_int(stmt, 2); + dbei->eventType = (uint16_t)sqlite3_column_int(stmt, 3); + dbei->szModule = mir_strdup((char*)sqlite3_column_text(stmt, 7)); + + uint32_t cbBlob = sqlite3_column_int(stmt, 5); + size_t bytesToCopy = cbBlob; + if (dbei->cbBlob == -1) + dbei->pBlob = (uint8_t*)mir_calloc(cbBlob + 2); + else if (dbei->cbBlob < cbBlob) + bytesToCopy = dbei->cbBlob; + + dbei->cbBlob = cbBlob; + if (bytesToCopy && dbei->pBlob) + memcpy(dbei->pBlob, blob, bytesToCopy); + res = 0; + } + sql_reset(stmt); + return res; +} + +STDMETHODIMP_(BOOL) CDbxSQLite::MarkEventRead(MCONTACT, MEVENT) +{ + return FALSE; +} + +STDMETHODIMP_(MCONTACT) CDbxSQLite::GetEventContact(MEVENT hDbEvent) +{ + mir_cslock lock(m_csDbAccess); + + int res = INVALID_CONTACT_ID; + sqlite3_stmt *stmt = evt_stmts_prep[SQL_EVT_STMT_GETCONTACT]; + sqlite3_bind_int(stmt, 1, hDbEvent); + if (sql_step(stmt) == SQLITE_ROW) + res = sqlite3_column_int(stmt, 0); + sql_reset(stmt); + return res; +} + +STDMETHODIMP_(MEVENT) CDbxSQLite::FindFirstEvent(MCONTACT contactID) +{ + mir_cslock lock(m_csDbAccess); + + int res = 0; + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDFIRST], 1, contactID); + if (sql_step(evt_stmts_prep[SQL_EVT_STMT_FINDFIRST]) == SQLITE_ROW) + res = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_FINDFIRST], 0); + sql_reset(evt_stmts_prep[SQL_EVT_STMT_FINDFIRST]); + return res; +} + +STDMETHODIMP_(MEVENT) CDbxSQLite::FindFirstUnreadEvent(MCONTACT contactID) +{ + mir_cslock lock(m_csDbAccess); + + int res = 0; + uint32_t flags = 0; + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDFIRSTUNREAD], 1, contactID); + while (sql_step(evt_stmts_prep[SQL_EVT_STMT_FINDFIRSTUNREAD]) == SQLITE_ROW) { + flags = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_FINDFIRSTUNREAD], 0); + if (!(flags & (DBEF_READ | DBEF_SENT))) { + res = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_FINDFIRSTUNREAD], 1); + sql_reset(evt_stmts_prep[SQL_EVT_STMT_FINDFIRSTUNREAD]); + return res; + } + } + sql_reset(evt_stmts_prep[SQL_EVT_STMT_FINDFIRSTUNREAD]); + return res; +} + +STDMETHODIMP_(MEVENT) CDbxSQLite::FindLastEvent(MCONTACT contactID) +{ + mir_cslock lock(m_csDbAccess); + + int res = 0; + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDLAST], 1, contactID); + if (sql_step(evt_stmts_prep[SQL_EVT_STMT_FINDLAST]) == SQLITE_ROW) + res = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_FINDLAST], 0); + sql_reset(evt_stmts_prep[SQL_EVT_STMT_FINDLAST]); + return res; +} + +STDMETHODIMP_(MEVENT) CDbxSQLite::FindNextEvent(MCONTACT contactID, MEVENT hDbEvent) +{ + if (hDbEvent == NULL) + return 0; + + mir_cslock lock(m_csDbAccess); + + int res = 0; + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDNEXT], 1, contactID); + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDNEXT], 2, hDbEvent); + if (sql_step(evt_stmts_prep[SQL_EVT_STMT_FINDNEXT]) == SQLITE_ROW) + res = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_FINDNEXT], 0); + sql_reset(evt_stmts_prep[SQL_EVT_STMT_FINDNEXT]); + return res; +} + +STDMETHODIMP_(MEVENT) CDbxSQLite::FindPrevEvent(MCONTACT contactID, MEVENT hDbEvent) +{ + if (!hDbEvent) + return 0; + + mir_cslock lock(m_csDbAccess); + + int res = 0; + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDPREV], 1, contactID); + sqlite3_bind_int(evt_stmts_prep[SQL_EVT_STMT_FINDPREV], 2, hDbEvent); + if (sql_step(evt_stmts_prep[SQL_EVT_STMT_FINDPREV]) == SQLITE_ROW) + res = sqlite3_column_int(evt_stmts_prep[SQL_EVT_STMT_FINDPREV], 0); + sql_reset(evt_stmts_prep[SQL_EVT_STMT_FINDPREV]); + return res; +} diff --git a/plugins/Import/src/dbrw/dbintf.cpp b/plugins/Import/src/dbrw/dbintf.cpp index 9749ae4437..d7c1751371 100644 --- a/plugins/Import/src/dbrw/dbintf.cpp +++ b/plugins/Import/src/dbrw/dbintf.cpp @@ -1,87 +1,87 @@ -/* - -Import plugin for Miranda NG - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) - -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" - -CDbxSQLite::CDbxSQLite() - : sql_prepare_len(0) -{ - sql_prepare_add(ctc_stmts, ctc_stmts_prep, SQL_CTC_STMT_NUM); - sql_prepare_add(evt_stmts, evt_stmts_prep, SQL_EVT_STMT_NUM); - sql_prepare_add(set_stmts, set_stmts_prep, SQL_SET_STMT_NUM); -} - -CDbxSQLite::~CDbxSQLite() -{ - sql_close(m_sqlite); - - for (int i = 0; i < sql_prepare_len; i++) - sql_finalize(*sql_prepare_stmt[i]); - mir_free(sql_prepare_text); - mir_free(sql_prepare_stmt); -} - -int CDbxSQLite::Open(const wchar_t *profile) -{ - T2Utf path(profile); - if (sql_open(path, &m_sqlite) != SQLITE_OK) - return 1; - - //utils_vacuum_check(); - { - sql_exec(m_sqlite, "BEGIN TRANSACTION;"); - sql_exec(m_sqlite, "PRAGMA locking_mode = EXCLUSIVE;"); - sql_exec(m_sqlite, "PRAGMA synchronous = NORMAL;"); - sql_exec(m_sqlite, "PRAGMA cache_size = 6000;"); - sql_exec(m_sqlite, "PRAGMA temp_store = MEMORY;"); - sql_exec(m_sqlite, "COMMIT;"); - } - - sql_prepare_statements(); - - FillContacts(); - - return 0; -} - -STDMETHODIMP_(void) CDbxSQLite::SetCacheSafetyMode(BOOL safeMode) -{ - if (safeMode) - sql_exec(m_sqlite, "PRAGMA synchronous = NORMAL;"); - else - sql_exec(m_sqlite, "PRAGMA synchronous = OFF;"); -} - -STDMETHODIMP_(BOOL) CDbxSQLite::MetaMergeHistory(DBCachedContact*, DBCachedContact*) -{ - return FALSE; -} - -STDMETHODIMP_(BOOL) CDbxSQLite::MetaSplitHistory(DBCachedContact*, DBCachedContact*) -{ - return FALSE; -} - -STDMETHODIMP_(MEVENT) CDbxSQLite::GetEventById(LPCSTR, LPCSTR) -{ - return 0; -} +/* + +Import plugin for Miranda NG + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) + +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" + +CDbxSQLite::CDbxSQLite() + : sql_prepare_len(0) +{ + sql_prepare_add(ctc_stmts, ctc_stmts_prep, SQL_CTC_STMT_NUM); + sql_prepare_add(evt_stmts, evt_stmts_prep, SQL_EVT_STMT_NUM); + sql_prepare_add(set_stmts, set_stmts_prep, SQL_SET_STMT_NUM); +} + +CDbxSQLite::~CDbxSQLite() +{ + sql_close(m_sqlite); + + for (int i = 0; i < sql_prepare_len; i++) + sql_finalize(*sql_prepare_stmt[i]); + mir_free(sql_prepare_text); + mir_free(sql_prepare_stmt); +} + +int CDbxSQLite::Open(const wchar_t *profile) +{ + T2Utf path(profile); + if (sql_open(path, &m_sqlite) != SQLITE_OK) + return 1; + + //utils_vacuum_check(); + { + sql_exec(m_sqlite, "BEGIN TRANSACTION;"); + sql_exec(m_sqlite, "PRAGMA locking_mode = EXCLUSIVE;"); + sql_exec(m_sqlite, "PRAGMA synchronous = NORMAL;"); + sql_exec(m_sqlite, "PRAGMA cache_size = 6000;"); + sql_exec(m_sqlite, "PRAGMA temp_store = MEMORY;"); + sql_exec(m_sqlite, "COMMIT;"); + } + + sql_prepare_statements(); + + FillContacts(); + + return 0; +} + +STDMETHODIMP_(void) CDbxSQLite::SetCacheSafetyMode(BOOL safeMode) +{ + if (safeMode) + sql_exec(m_sqlite, "PRAGMA synchronous = NORMAL;"); + else + sql_exec(m_sqlite, "PRAGMA synchronous = OFF;"); +} + +STDMETHODIMP_(BOOL) CDbxSQLite::MetaMergeHistory(DBCachedContact*, DBCachedContact*) +{ + return FALSE; +} + +STDMETHODIMP_(BOOL) CDbxSQLite::MetaSplitHistory(DBCachedContact*, DBCachedContact*) +{ + return FALSE; +} + +STDMETHODIMP_(MEVENT) CDbxSQLite::GetEventById(LPCSTR, LPCSTR) +{ + return 0; +} diff --git a/plugins/Import/src/dbrw/dbintf.h b/plugins/Import/src/dbrw/dbintf.h index 9ff2ee40ff..2a843b025d 100644 --- a/plugins/Import/src/dbrw/dbintf.h +++ b/plugins/Import/src/dbrw/dbintf.h @@ -1,159 +1,159 @@ -/* - -Import plugin for Miranda NG - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) - -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. - -*/ - -#pragma once - -enum SQL_CTC_STMT -{ - SQL_CTC_STMT_COUNT = 0, - SQL_CTC_STMT_EXISTS, - SQL_CTC_STMT_NUM -}; - -static char *ctc_stmts[SQL_CTC_STMT_NUM] = -{ - "SELECT count(*) FROM dbrw_contacts;", - "SELECT id FROM dbrw_contacts WHERE id = ? LIMIT 1;" -}; - -enum SQL_EVT_STMT -{ - SQL_EVT_STMT_COUNT = 0, - SQL_EVT_STMT_BLOBSIZE, - SQL_EVT_STMT_GET, - SQL_EVT_STMT_GETFLAGS, - SQL_EVT_STMT_GETCONTACT, - SQL_EVT_STMT_FINDFIRST, - SQL_EVT_STMT_FINDFIRSTUNREAD, - SQL_EVT_STMT_FINDLAST, - SQL_EVT_STMT_FINDNEXT, - SQL_EVT_STMT_FINDPREV, - SQL_EVT_STMT_NUM -}; - -static char *evt_stmts[SQL_EVT_STMT_NUM] = -{ - "SELECT count(*) FROM dbrw_events where contactid = ?;", - "SELECT blobsize FROM dbrw_events where id = ? LIMIT 1;", - "SELECT * FROM dbrw_events where id = ? LIMIT 1;", - "SELECT flags FROM dbrw_events where id = ? LIMIT 1;", - "SELECT contactid FROM dbrw_events where id = ? LIMIT 1;", - "SELECT id FROM dbrw_events where contactid = ? ORDER by id LIMIT 1;", - "SELECT flags, id FROM dbrw_events where contactid = ? ORDER by id;", - "SELECT id FROM dbrw_events where contactid = ? ORDER by id DESC;", - "SELECT id FROM dbrw_events where contactid = ? AND id > ? ORDER by id LIMIT 1;", - "SELECT id FROM dbrw_events where contactid = ? AND id < ? ORDER by id DESC LIMIT 1;" -}; - -enum SQL_SET_STMT -{ - SQL_SET_STMT_READ = 0, - SQL_SET_STMT_ENUM, - SQL_SET_STMT_ENUMMODULES, - SQL_SET_STMT_SETTINGCHECK, - SQL_SET_STMT_NUM -}; - -static char *set_stmts[SQL_SET_STMT_NUM] = -{ - "SELECT type, val FROM dbrw_settings WHERE setting = ? AND module = ? AND id = ? LIMIT 1;", - "SELECT setting from dbrw_settings where id = ? AND module = ? ORDER by setting;", - "SELECT DISTINCT module from dbrw_settings;", - "SELECT count(*) FROM dbrw_settings WHERE setting = ? AND module = ? AND id = ?;", -}; - -struct TSqlMessage { - int op; - sqlite3 *pDb; - sqlite3_stmt *pStmt; - int retCode; - const char *zIn; - HANDLE hDoneEvent; -}; - -struct CDbxSQLite : public MDatabaseReadonly, public MZeroedObject -{ -private: - sqlite3 *m_sqlite; - - int sql_prepare_len; - char **sql_prepare_text; - sqlite3_stmt ***sql_prepare_stmt; - sqlite3_stmt *ctc_stmts_prep[SQL_CTC_STMT_NUM] = { 0 }; - sqlite3_stmt *evt_stmts_prep[SQL_EVT_STMT_NUM] = { 0 }; - sqlite3_stmt *set_stmts_prep[SQL_SET_STMT_NUM] = { 0 }; - - void sql_prepare_add(char **text, sqlite3_stmt **stmts, int len); - void sql_prepare_statements(); - static void CALLBACK sql_server_sync_apc(UINT_PTR dwParam); - void sql_server_sync(TSqlMessage *msg); - int sql_step(sqlite3_stmt *stmt); - int sql_reset(sqlite3_stmt *stmt); - int sql_exec(sqlite3 *sql, const char *query); - int sql_open(const char *path, sqlite3 **sql); - int sql_close(sqlite3 *sql); - int sql_prepare(sqlite3 *sql, const char *query, sqlite3_stmt **stmt); - int sql_finalize(sqlite3_stmt *stmt); - - void FillContacts(); - -public: - CDbxSQLite(); - ~CDbxSQLite(); - - int Open(const wchar_t *profile); - - STDMETHODIMP_(BOOL) IsRelational(void) override { return FALSE; } - STDMETHODIMP_(void) SetCacheSafetyMode(BOOL) override; - - STDMETHODIMP_(int) GetContactCount(void) override; - STDMETHODIMP_(int) DeleteContact(MCONTACT contactID) override; - STDMETHODIMP_(MCONTACT) AddContact(void) override; - STDMETHODIMP_(BOOL) IsDbContact(MCONTACT contactID) override; - STDMETHODIMP_(int) GetContactSize(void) override; - - STDMETHODIMP_(int) GetEventCount(MCONTACT contactID) override; - STDMETHODIMP_(MEVENT) AddEvent(MCONTACT contactID, const DBEVENTINFO *dbe) override; - STDMETHODIMP_(BOOL) DeleteEvent(MEVENT hDbEvent) override; - STDMETHODIMP_(BOOL) EditEvent(MCONTACT contactID, MEVENT hDbEvent, const DBEVENTINFO *dbe) override; - STDMETHODIMP_(int) GetBlobSize(MEVENT hDbEvent) override; - STDMETHODIMP_(BOOL) GetEvent(MEVENT hDbEvent, DBEVENTINFO *dbe) override; - STDMETHODIMP_(BOOL) MarkEventRead(MCONTACT contactID, MEVENT hDbEvent) override; - STDMETHODIMP_(MCONTACT) GetEventContact(MEVENT hDbEvent) override; - STDMETHODIMP_(MEVENT) FindFirstEvent(MCONTACT contactID) override; - STDMETHODIMP_(MEVENT) FindFirstUnreadEvent(MCONTACT contactID) override; - STDMETHODIMP_(MEVENT) FindLastEvent(MCONTACT contactID) override; - STDMETHODIMP_(MEVENT) FindNextEvent(MCONTACT contactID, MEVENT hDbEvent) override; - STDMETHODIMP_(MEVENT) FindPrevEvent(MCONTACT contactID, MEVENT hDbEvent) override; - - STDMETHODIMP_(BOOL) EnumModuleNames(DBMODULEENUMPROC pFunc, void *pParam) override; - - STDMETHODIMP_(BOOL) GetContactSettingWorker(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv, int isStatic) override; - STDMETHODIMP_(BOOL) EnumContactSettings(MCONTACT hContact, DBSETTINGENUMPROC pfnEnumProc, const char *szModule, void *param) override; - - STDMETHODIMP_(BOOL) MetaMergeHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub) override; - STDMETHODIMP_(BOOL) MetaSplitHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub) override; - - STDMETHODIMP_(MEVENT) GetEventById(LPCSTR szModule, LPCSTR szId) override; - - STDMETHODIMP_(DATABASELINK *) GetDriver(); -}; +/* + +Import plugin for Miranda NG + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) + +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. + +*/ + +#pragma once + +enum SQL_CTC_STMT +{ + SQL_CTC_STMT_COUNT = 0, + SQL_CTC_STMT_EXISTS, + SQL_CTC_STMT_NUM +}; + +static char *ctc_stmts[SQL_CTC_STMT_NUM] = +{ + "SELECT count(*) FROM dbrw_contacts;", + "SELECT id FROM dbrw_contacts WHERE id = ? LIMIT 1;" +}; + +enum SQL_EVT_STMT +{ + SQL_EVT_STMT_COUNT = 0, + SQL_EVT_STMT_BLOBSIZE, + SQL_EVT_STMT_GET, + SQL_EVT_STMT_GETFLAGS, + SQL_EVT_STMT_GETCONTACT, + SQL_EVT_STMT_FINDFIRST, + SQL_EVT_STMT_FINDFIRSTUNREAD, + SQL_EVT_STMT_FINDLAST, + SQL_EVT_STMT_FINDNEXT, + SQL_EVT_STMT_FINDPREV, + SQL_EVT_STMT_NUM +}; + +static char *evt_stmts[SQL_EVT_STMT_NUM] = +{ + "SELECT count(*) FROM dbrw_events where contactid = ?;", + "SELECT blobsize FROM dbrw_events where id = ? LIMIT 1;", + "SELECT * FROM dbrw_events where id = ? LIMIT 1;", + "SELECT flags FROM dbrw_events where id = ? LIMIT 1;", + "SELECT contactid FROM dbrw_events where id = ? LIMIT 1;", + "SELECT id FROM dbrw_events where contactid = ? ORDER by id LIMIT 1;", + "SELECT flags, id FROM dbrw_events where contactid = ? ORDER by id;", + "SELECT id FROM dbrw_events where contactid = ? ORDER by id DESC;", + "SELECT id FROM dbrw_events where contactid = ? AND id > ? ORDER by id LIMIT 1;", + "SELECT id FROM dbrw_events where contactid = ? AND id < ? ORDER by id DESC LIMIT 1;" +}; + +enum SQL_SET_STMT +{ + SQL_SET_STMT_READ = 0, + SQL_SET_STMT_ENUM, + SQL_SET_STMT_ENUMMODULES, + SQL_SET_STMT_SETTINGCHECK, + SQL_SET_STMT_NUM +}; + +static char *set_stmts[SQL_SET_STMT_NUM] = +{ + "SELECT type, val FROM dbrw_settings WHERE setting = ? AND module = ? AND id = ? LIMIT 1;", + "SELECT setting from dbrw_settings where id = ? AND module = ? ORDER by setting;", + "SELECT DISTINCT module from dbrw_settings;", + "SELECT count(*) FROM dbrw_settings WHERE setting = ? AND module = ? AND id = ?;", +}; + +struct TSqlMessage { + int op; + sqlite3 *pDb; + sqlite3_stmt *pStmt; + int retCode; + const char *zIn; + HANDLE hDoneEvent; +}; + +struct CDbxSQLite : public MDatabaseReadonly, public MZeroedObject +{ +private: + sqlite3 *m_sqlite; + + int sql_prepare_len; + char **sql_prepare_text; + sqlite3_stmt ***sql_prepare_stmt; + sqlite3_stmt *ctc_stmts_prep[SQL_CTC_STMT_NUM] = { 0 }; + sqlite3_stmt *evt_stmts_prep[SQL_EVT_STMT_NUM] = { 0 }; + sqlite3_stmt *set_stmts_prep[SQL_SET_STMT_NUM] = { 0 }; + + void sql_prepare_add(char **text, sqlite3_stmt **stmts, int len); + void sql_prepare_statements(); + static void CALLBACK sql_server_sync_apc(UINT_PTR dwParam); + void sql_server_sync(TSqlMessage *msg); + int sql_step(sqlite3_stmt *stmt); + int sql_reset(sqlite3_stmt *stmt); + int sql_exec(sqlite3 *sql, const char *query); + int sql_open(const char *path, sqlite3 **sql); + int sql_close(sqlite3 *sql); + int sql_prepare(sqlite3 *sql, const char *query, sqlite3_stmt **stmt); + int sql_finalize(sqlite3_stmt *stmt); + + void FillContacts(); + +public: + CDbxSQLite(); + ~CDbxSQLite(); + + int Open(const wchar_t *profile); + + STDMETHODIMP_(BOOL) IsRelational(void) override { return FALSE; } + STDMETHODIMP_(void) SetCacheSafetyMode(BOOL) override; + + STDMETHODIMP_(int) GetContactCount(void) override; + STDMETHODIMP_(int) DeleteContact(MCONTACT contactID) override; + STDMETHODIMP_(MCONTACT) AddContact(void) override; + STDMETHODIMP_(BOOL) IsDbContact(MCONTACT contactID) override; + STDMETHODIMP_(int) GetContactSize(void) override; + + STDMETHODIMP_(int) GetEventCount(MCONTACT contactID) override; + STDMETHODIMP_(MEVENT) AddEvent(MCONTACT contactID, const DBEVENTINFO *dbe) override; + STDMETHODIMP_(BOOL) DeleteEvent(MEVENT hDbEvent) override; + STDMETHODIMP_(BOOL) EditEvent(MCONTACT contactID, MEVENT hDbEvent, const DBEVENTINFO *dbe) override; + STDMETHODIMP_(int) GetBlobSize(MEVENT hDbEvent) override; + STDMETHODIMP_(BOOL) GetEvent(MEVENT hDbEvent, DBEVENTINFO *dbe) override; + STDMETHODIMP_(BOOL) MarkEventRead(MCONTACT contactID, MEVENT hDbEvent) override; + STDMETHODIMP_(MCONTACT) GetEventContact(MEVENT hDbEvent) override; + STDMETHODIMP_(MEVENT) FindFirstEvent(MCONTACT contactID) override; + STDMETHODIMP_(MEVENT) FindFirstUnreadEvent(MCONTACT contactID) override; + STDMETHODIMP_(MEVENT) FindLastEvent(MCONTACT contactID) override; + STDMETHODIMP_(MEVENT) FindNextEvent(MCONTACT contactID, MEVENT hDbEvent) override; + STDMETHODIMP_(MEVENT) FindPrevEvent(MCONTACT contactID, MEVENT hDbEvent) override; + + STDMETHODIMP_(BOOL) EnumModuleNames(DBMODULEENUMPROC pFunc, void *pParam) override; + + STDMETHODIMP_(BOOL) GetContactSettingWorker(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv, int isStatic) override; + STDMETHODIMP_(BOOL) EnumContactSettings(MCONTACT hContact, DBSETTINGENUMPROC pfnEnumProc, const char *szModule, void *param) override; + + STDMETHODIMP_(BOOL) MetaMergeHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub) override; + STDMETHODIMP_(BOOL) MetaSplitHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub) override; + + STDMETHODIMP_(MEVENT) GetEventById(LPCSTR szModule, LPCSTR szId) override; + + STDMETHODIMP_(DATABASELINK *) GetDriver(); +}; diff --git a/plugins/Import/src/dbrw/dbrw.cpp b/plugins/Import/src/dbrw/dbrw.cpp index fded599583..7be7b2634d 100644 --- a/plugins/Import/src/dbrw/dbrw.cpp +++ b/plugins/Import/src/dbrw/dbrw.cpp @@ -1,105 +1,105 @@ -/* - -Import plugin for Miranda NG - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) - -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" - -static int dbrw_makeDatabase(const wchar_t*) -{ - return 1; -} - -static int dbrw_grokHeader(const wchar_t *profile) -{ - HANDLE hFile = CreateFile(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 = mir_utf8encodeW(profile); - - rc = sqlite3_open(szPath, &sqlcheck); - mir_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; - } - return rc; -} - -static MDatabaseCommon* dbrw_Load(const wchar_t *profile, BOOL) -{ - CDbxSQLite *db = new CDbxSQLite(); - db->Open(profile); - return db; -} - -static DATABASELINK dblink = -{ - 0, - "dbrw", - L"dbx SQLite driver", - dbrw_makeDatabase, - dbrw_grokHeader, - dbrw_Load -}; - -STDMETHODIMP_(DATABASELINK *) CDbxSQLite::GetDriver() -{ - return &g_patternDbLink; -} - -void RegisterDbrw() -{ - RegisterDatabasePlugin(&dblink); -} +/* + +Import plugin for Miranda NG + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) + +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" + +static int dbrw_makeDatabase(const wchar_t*) +{ + return 1; +} + +static int dbrw_grokHeader(const wchar_t *profile) +{ + HANDLE hFile = CreateFile(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 = mir_utf8encodeW(profile); + + rc = sqlite3_open(szPath, &sqlcheck); + mir_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; + } + return rc; +} + +static MDatabaseCommon* dbrw_Load(const wchar_t *profile, BOOL) +{ + CDbxSQLite *db = new CDbxSQLite(); + db->Open(profile); + return db; +} + +static DATABASELINK dblink = +{ + 0, + "dbrw", + L"dbx SQLite driver", + dbrw_makeDatabase, + dbrw_grokHeader, + dbrw_Load +}; + +STDMETHODIMP_(DATABASELINK *) CDbxSQLite::GetDriver() +{ + return &g_patternDbLink; +} + +void RegisterDbrw() +{ + RegisterDatabasePlugin(&dblink); +} diff --git a/plugins/Import/src/dbrw/dbrw.h b/plugins/Import/src/dbrw/dbrw.h index daf32ba745..11b153221a 100644 --- a/plugins/Import/src/dbrw/dbrw.h +++ b/plugins/Import/src/dbrw/dbrw.h @@ -1,30 +1,30 @@ -/* - -Import plugin for Miranda NG - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) - -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. - -*/ - -#pragma once - -#include - -#define DBRW_SCHEMA_VERSION "2" -#define DBRW_HEADER_STR "SQLite format 3" - -void RegisterDbrw(); +/* + +Import plugin for Miranda NG + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) + +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. + +*/ + +#pragma once + +#include + +#define DBRW_SCHEMA_VERSION "2" +#define DBRW_HEADER_STR "SQLite format 3" + +void RegisterDbrw(); diff --git a/plugins/Import/src/dbrw/dbsettings.cpp b/plugins/Import/src/dbrw/dbsettings.cpp index 360a56ea94..9efe213bcf 100644 --- a/plugins/Import/src/dbrw/dbsettings.cpp +++ b/plugins/Import/src/dbrw/dbsettings.cpp @@ -1,171 +1,171 @@ -/* - -Import plugin for Miranda NG - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) - -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" - -STDMETHODIMP_(BOOL) CDbxSQLite::EnumModuleNames(DBMODULEENUMPROC pFunc, void *pParam) -{ - mir_cslockfull lock(m_csDbAccess); - - int res = 0; - while (sql_step(set_stmts_prep[SQL_SET_STMT_ENUMMODULES]) == SQLITE_ROW && !res) { - const char *szModule = (const char *)sqlite3_column_text(set_stmts_prep[SQL_SET_STMT_ENUMMODULES], 0); - lock.unlock(); - res = (pFunc)(szModule, pParam); - lock.lock(); - } - sql_reset(set_stmts_prep[SQL_SET_STMT_ENUMMODULES]); - return res; -} - -STDMETHODIMP_(BOOL) CDbxSQLite::GetContactSettingWorker(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv, int isStatic) -{ - if (!szSetting || !szModule) - return 1; - - size_t settingNameLen = strlen(szSetting); - size_t moduleNameLen = strlen(szModule); - - mir_cslock lock(m_csDbAccess); - - char *szCachedSettingName = m_cache->GetCachedSetting(szModule, szSetting, moduleNameLen, settingNameLen); - DBVARIANT *pCachedValue = m_cache->GetCachedValuePtr(contactID, szCachedSettingName, 0); - if (pCachedValue != nullptr) { - if (pCachedValue->type == DBVT_ASCIIZ || 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)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(strlen(pCachedValue->pszVal) + 1); - 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 (szCachedSettingName[-1] != 0) - return 1; - - sqlite3_bind_text(set_stmts_prep[SQL_SET_STMT_READ], 1, szSetting, -1, SQLITE_STATIC); - sqlite3_bind_text(set_stmts_prep[SQL_SET_STMT_READ], 2, szModule, -1, SQLITE_STATIC); - sqlite3_bind_int(set_stmts_prep[SQL_SET_STMT_READ], 3, contactID); - if (sql_step(set_stmts_prep[SQL_SET_STMT_READ]) != SQLITE_ROW) { - /*if (dbv->type != DBVT_BLOB) { - DBVARIANT* pCachedValue = settings_getCachedValue(contactID, szCachedSettingName, 1); - - if (pCachedValue != NULL) - pCachedValue->type = DBVT_DELETED; - }*/ - sql_reset(set_stmts_prep[SQL_SET_STMT_READ]); - return 1; - } - dbv->type = (int)sqlite3_column_int(set_stmts_prep[SQL_SET_STMT_READ], 0); - switch (dbv->type) { - case DBVT_BYTE: - dbv->bVal = (uint8_t)sqlite3_column_int(set_stmts_prep[SQL_SET_STMT_READ], 1); - break; - case DBVT_WORD: - dbv->wVal = (uint16_t)sqlite3_column_int(set_stmts_prep[SQL_SET_STMT_READ], 1); - break; - case DBVT_DWORD: - dbv->dVal = (uint32_t)sqlite3_column_int(set_stmts_prep[SQL_SET_STMT_READ], 1); - break; - case DBVT_UTF8: - case DBVT_ASCIIZ: - { - const char *p = (const char *)sqlite3_column_text(set_stmts_prep[SQL_SET_STMT_READ], 1); - - if (p != NULL) { - size_t len = strlen(p) + 1; - size_t copylen = isStatic ? (len < dbv->cchVal ? len : dbv->cchVal) : len; - if (!isStatic) - dbv->pszVal = (char*)mir_alloc(len); - memmove(dbv->pszVal, p, copylen); - } - else - dbv->pszVal = 0; - break; - } - case DBVT_BLOB: - { - size_t len = sqlite3_column_bytes(set_stmts_prep[SQL_SET_STMT_READ], 1); - - if (len) { - size_t copylen = isStatic ? (len < dbv->cpbVal ? len : dbv->cpbVal) : len; - if (!isStatic) - dbv->pbVal = (uint8_t*)mir_alloc(copylen); - memcpy(dbv->pbVal, sqlite3_column_blob(set_stmts_prep[SQL_SET_STMT_READ], 1), copylen); - dbv->cpbVal = (uint16_t)copylen; - } - else { - dbv = 0; - } - } - } - sql_reset(set_stmts_prep[SQL_SET_STMT_READ]); - // add to cache - if (dbv->type != DBVT_BLOB/* && dbv->type != DBVT_ENCRYPTED*/) { - pCachedValue = m_cache->GetCachedValuePtr(contactID, szCachedSettingName, 1); - if (pCachedValue != nullptr) - m_cache->SetCachedVariant(dbv, pCachedValue); - } - - return 0; -} - -STDMETHODIMP_(BOOL) CDbxSQLite::EnumContactSettings(MCONTACT hContact, DBSETTINGENUMPROC pfnEnumProc, const char *szModule, void *param) -{ - if (szModule == nullptr) - return -1; - - mir_cslockfull lock(m_csDbAccess); - - int res = -1; - sqlite3_bind_int(set_stmts_prep[SQL_SET_STMT_ENUM], 1, hContact); - sqlite3_bind_text(set_stmts_prep[SQL_SET_STMT_ENUM], 2, szModule, -1, SQLITE_STATIC); - while (sql_step(set_stmts_prep[SQL_SET_STMT_ENUM]) == SQLITE_ROW) { - const char *sczSetting = (const char*)sqlite3_column_text(set_stmts_prep[SQL_SET_STMT_ENUM], 0); - if (sczSetting) { - lock.unlock(); - res = (pfnEnumProc)(sczSetting, param); - lock.lock(); - } - } - sql_reset(set_stmts_prep[SQL_SET_STMT_ENUM]); - return res; -} +/* + +Import plugin for Miranda NG + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) + +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" + +STDMETHODIMP_(BOOL) CDbxSQLite::EnumModuleNames(DBMODULEENUMPROC pFunc, void *pParam) +{ + mir_cslockfull lock(m_csDbAccess); + + int res = 0; + while (sql_step(set_stmts_prep[SQL_SET_STMT_ENUMMODULES]) == SQLITE_ROW && !res) { + const char *szModule = (const char *)sqlite3_column_text(set_stmts_prep[SQL_SET_STMT_ENUMMODULES], 0); + lock.unlock(); + res = (pFunc)(szModule, pParam); + lock.lock(); + } + sql_reset(set_stmts_prep[SQL_SET_STMT_ENUMMODULES]); + return res; +} + +STDMETHODIMP_(BOOL) CDbxSQLite::GetContactSettingWorker(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv, int isStatic) +{ + if (!szSetting || !szModule) + return 1; + + size_t settingNameLen = strlen(szSetting); + size_t moduleNameLen = strlen(szModule); + + mir_cslock lock(m_csDbAccess); + + char *szCachedSettingName = m_cache->GetCachedSetting(szModule, szSetting, moduleNameLen, settingNameLen); + DBVARIANT *pCachedValue = m_cache->GetCachedValuePtr(contactID, szCachedSettingName, 0); + if (pCachedValue != nullptr) { + if (pCachedValue->type == DBVT_ASCIIZ || 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)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(strlen(pCachedValue->pszVal) + 1); + 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 (szCachedSettingName[-1] != 0) + return 1; + + sqlite3_bind_text(set_stmts_prep[SQL_SET_STMT_READ], 1, szSetting, -1, SQLITE_STATIC); + sqlite3_bind_text(set_stmts_prep[SQL_SET_STMT_READ], 2, szModule, -1, SQLITE_STATIC); + sqlite3_bind_int(set_stmts_prep[SQL_SET_STMT_READ], 3, contactID); + if (sql_step(set_stmts_prep[SQL_SET_STMT_READ]) != SQLITE_ROW) { + /*if (dbv->type != DBVT_BLOB) { + DBVARIANT* pCachedValue = settings_getCachedValue(contactID, szCachedSettingName, 1); + + if (pCachedValue != NULL) + pCachedValue->type = DBVT_DELETED; + }*/ + sql_reset(set_stmts_prep[SQL_SET_STMT_READ]); + return 1; + } + dbv->type = (int)sqlite3_column_int(set_stmts_prep[SQL_SET_STMT_READ], 0); + switch (dbv->type) { + case DBVT_BYTE: + dbv->bVal = (uint8_t)sqlite3_column_int(set_stmts_prep[SQL_SET_STMT_READ], 1); + break; + case DBVT_WORD: + dbv->wVal = (uint16_t)sqlite3_column_int(set_stmts_prep[SQL_SET_STMT_READ], 1); + break; + case DBVT_DWORD: + dbv->dVal = (uint32_t)sqlite3_column_int(set_stmts_prep[SQL_SET_STMT_READ], 1); + break; + case DBVT_UTF8: + case DBVT_ASCIIZ: + { + const char *p = (const char *)sqlite3_column_text(set_stmts_prep[SQL_SET_STMT_READ], 1); + + if (p != NULL) { + size_t len = strlen(p) + 1; + size_t copylen = isStatic ? (len < dbv->cchVal ? len : dbv->cchVal) : len; + if (!isStatic) + dbv->pszVal = (char*)mir_alloc(len); + memmove(dbv->pszVal, p, copylen); + } + else + dbv->pszVal = 0; + break; + } + case DBVT_BLOB: + { + size_t len = sqlite3_column_bytes(set_stmts_prep[SQL_SET_STMT_READ], 1); + + if (len) { + size_t copylen = isStatic ? (len < dbv->cpbVal ? len : dbv->cpbVal) : len; + if (!isStatic) + dbv->pbVal = (uint8_t*)mir_alloc(copylen); + memcpy(dbv->pbVal, sqlite3_column_blob(set_stmts_prep[SQL_SET_STMT_READ], 1), copylen); + dbv->cpbVal = (uint16_t)copylen; + } + else { + dbv = 0; + } + } + } + sql_reset(set_stmts_prep[SQL_SET_STMT_READ]); + // add to cache + if (dbv->type != DBVT_BLOB/* && dbv->type != DBVT_ENCRYPTED*/) { + pCachedValue = m_cache->GetCachedValuePtr(contactID, szCachedSettingName, 1); + if (pCachedValue != nullptr) + m_cache->SetCachedVariant(dbv, pCachedValue); + } + + return 0; +} + +STDMETHODIMP_(BOOL) CDbxSQLite::EnumContactSettings(MCONTACT hContact, DBSETTINGENUMPROC pfnEnumProc, const char *szModule, void *param) +{ + if (szModule == nullptr) + return -1; + + mir_cslockfull lock(m_csDbAccess); + + int res = -1; + sqlite3_bind_int(set_stmts_prep[SQL_SET_STMT_ENUM], 1, hContact); + sqlite3_bind_text(set_stmts_prep[SQL_SET_STMT_ENUM], 2, szModule, -1, SQLITE_STATIC); + while (sql_step(set_stmts_prep[SQL_SET_STMT_ENUM]) == SQLITE_ROW) { + const char *sczSetting = (const char*)sqlite3_column_text(set_stmts_prep[SQL_SET_STMT_ENUM], 0); + if (sczSetting) { + lock.unlock(); + res = (pfnEnumProc)(sczSetting, param); + lock.lock(); + } + } + sql_reset(set_stmts_prep[SQL_SET_STMT_ENUM]); + return res; +} diff --git a/plugins/Import/src/dbrw/dbsql.cpp b/plugins/Import/src/dbrw/dbsql.cpp index 516f378435..3eaf3ef0d6 100644 --- a/plugins/Import/src/dbrw/dbsql.cpp +++ b/plugins/Import/src/dbrw/dbsql.cpp @@ -1,162 +1,162 @@ -/* - -Import plugin for Miranda NG - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) - -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" - -enum SQL -{ - SQL_STEP, - SQL_RESET, - SQL_EXEC, - SQL_OPEN, - SQL_CLOSE, - SQL_PREPARE, - SQL_FINALIZE -}; - -void CDbxSQLite::sql_prepare_add(char **text, sqlite3_stmt **stmts, int len) -{ - sql_prepare_text = (char**)mir_realloc(sql_prepare_text, (sql_prepare_len + len) * sizeof(char*)); - sql_prepare_stmt = (sqlite3_stmt***)mir_realloc(sql_prepare_stmt, (sql_prepare_len + len) * sizeof(sqlite3_stmt**)); - for (int i = 0; i < len; i++) { - sql_prepare_text[sql_prepare_len + i] = text[i]; - sql_prepare_stmt[sql_prepare_len + i] = &stmts[i]; - } - sql_prepare_len += len; -} - -void CDbxSQLite::sql_prepare_statements() -{ - for (int i = 0; i < sql_prepare_len; i++) - sql_prepare(m_sqlite, sql_prepare_text[i], sql_prepare_stmt[i]); -} - -void CALLBACK CDbxSQLite::sql_server_sync_apc(UINT_PTR dwParam) -{ - TSqlMessage *msg = (TSqlMessage*)dwParam; - - if (!msg) - return; - - switch (msg->op) { - case SQL_STEP: - msg->retCode = sqlite3_step(msg->pStmt); - break; - case SQL_RESET: - msg->retCode = sqlite3_reset(msg->pStmt); - break; - case SQL_EXEC: - msg->retCode = sqlite3_exec(msg->pDb, msg->zIn, NULL, NULL, NULL); - break; - case SQL_OPEN: - msg->retCode = sqlite3_open(msg->zIn, &msg->pDb); - break; - case SQL_CLOSE: - msg->retCode = sqlite3_close(msg->pDb); - break; - case SQL_PREPARE: - msg->retCode = sqlite3_prepare_v2(msg->pDb, msg->zIn, -1, &msg->pStmt, NULL); - break; - case SQL_FINALIZE: - msg->retCode = sqlite3_finalize(msg->pStmt); - break; - default: - return; - } - SetEvent(msg->hDoneEvent); -} - -void CDbxSQLite::sql_server_sync(TSqlMessage *msg) -{ - msg->hDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - sql_server_sync_apc((UINT_PTR)msg); - PostMessage(Miranda_GetSystemWindow()->GetHwnd(), WM_NULL, 0, 0); - WaitForSingleObject(msg->hDoneEvent, INFINITE); - CloseHandle(msg->hDoneEvent); -} - -int CDbxSQLite::sql_step(sqlite3_stmt *stmt) -{ - TSqlMessage msg; - msg.op = SQL_STEP; - msg.pStmt = stmt; - sql_server_sync(&msg); - return msg.retCode; -} - -int CDbxSQLite::sql_reset(sqlite3_stmt *stmt) -{ - TSqlMessage msg; - msg.op = SQL_RESET; - msg.pStmt = stmt; - sql_server_sync(&msg); - return msg.retCode; -} - -int CDbxSQLite::sql_exec(sqlite3 *sql, const char *query) -{ - TSqlMessage msg; - msg.op = SQL_EXEC; - msg.pDb = sql; - msg.zIn = query; - sql_server_sync(&msg); - return msg.retCode; -} - -int CDbxSQLite::sql_open(const char *path, sqlite3 **sql) -{ - TSqlMessage msg; - msg.op = SQL_OPEN; - msg.zIn = path; - sql_server_sync(&msg); - *sql = msg.pDb; - return msg.retCode; -} - -int CDbxSQLite::sql_close(sqlite3 *sql) -{ - TSqlMessage msg; - msg.op = SQL_CLOSE; - msg.pDb = sql; - sql_server_sync(&msg); - return msg.retCode; -} - -int CDbxSQLite::sql_prepare(sqlite3 *sql, const char *query, sqlite3_stmt **stmt) -{ - TSqlMessage msg; - msg.op = SQL_PREPARE; - msg.pDb = sql; - msg.zIn = query; - sql_server_sync(&msg); - *stmt = msg.pStmt; - return msg.retCode; -} - -int CDbxSQLite::sql_finalize(sqlite3_stmt *stmt) -{ - TSqlMessage msg; - msg.op = SQL_FINALIZE; - msg.pStmt = stmt; - sql_server_sync(&msg); - return msg.retCode; -} +/* + +Import plugin for Miranda NG + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) + +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" + +enum SQL +{ + SQL_STEP, + SQL_RESET, + SQL_EXEC, + SQL_OPEN, + SQL_CLOSE, + SQL_PREPARE, + SQL_FINALIZE +}; + +void CDbxSQLite::sql_prepare_add(char **text, sqlite3_stmt **stmts, int len) +{ + sql_prepare_text = (char**)mir_realloc(sql_prepare_text, (sql_prepare_len + len) * sizeof(char*)); + sql_prepare_stmt = (sqlite3_stmt***)mir_realloc(sql_prepare_stmt, (sql_prepare_len + len) * sizeof(sqlite3_stmt**)); + for (int i = 0; i < len; i++) { + sql_prepare_text[sql_prepare_len + i] = text[i]; + sql_prepare_stmt[sql_prepare_len + i] = &stmts[i]; + } + sql_prepare_len += len; +} + +void CDbxSQLite::sql_prepare_statements() +{ + for (int i = 0; i < sql_prepare_len; i++) + sql_prepare(m_sqlite, sql_prepare_text[i], sql_prepare_stmt[i]); +} + +void CALLBACK CDbxSQLite::sql_server_sync_apc(UINT_PTR dwParam) +{ + TSqlMessage *msg = (TSqlMessage*)dwParam; + + if (!msg) + return; + + switch (msg->op) { + case SQL_STEP: + msg->retCode = sqlite3_step(msg->pStmt); + break; + case SQL_RESET: + msg->retCode = sqlite3_reset(msg->pStmt); + break; + case SQL_EXEC: + msg->retCode = sqlite3_exec(msg->pDb, msg->zIn, NULL, NULL, NULL); + break; + case SQL_OPEN: + msg->retCode = sqlite3_open(msg->zIn, &msg->pDb); + break; + case SQL_CLOSE: + msg->retCode = sqlite3_close(msg->pDb); + break; + case SQL_PREPARE: + msg->retCode = sqlite3_prepare_v2(msg->pDb, msg->zIn, -1, &msg->pStmt, NULL); + break; + case SQL_FINALIZE: + msg->retCode = sqlite3_finalize(msg->pStmt); + break; + default: + return; + } + SetEvent(msg->hDoneEvent); +} + +void CDbxSQLite::sql_server_sync(TSqlMessage *msg) +{ + msg->hDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + sql_server_sync_apc((UINT_PTR)msg); + PostMessage(Miranda_GetSystemWindow()->GetHwnd(), WM_NULL, 0, 0); + WaitForSingleObject(msg->hDoneEvent, INFINITE); + CloseHandle(msg->hDoneEvent); +} + +int CDbxSQLite::sql_step(sqlite3_stmt *stmt) +{ + TSqlMessage msg; + msg.op = SQL_STEP; + msg.pStmt = stmt; + sql_server_sync(&msg); + return msg.retCode; +} + +int CDbxSQLite::sql_reset(sqlite3_stmt *stmt) +{ + TSqlMessage msg; + msg.op = SQL_RESET; + msg.pStmt = stmt; + sql_server_sync(&msg); + return msg.retCode; +} + +int CDbxSQLite::sql_exec(sqlite3 *sql, const char *query) +{ + TSqlMessage msg; + msg.op = SQL_EXEC; + msg.pDb = sql; + msg.zIn = query; + sql_server_sync(&msg); + return msg.retCode; +} + +int CDbxSQLite::sql_open(const char *path, sqlite3 **sql) +{ + TSqlMessage msg; + msg.op = SQL_OPEN; + msg.zIn = path; + sql_server_sync(&msg); + *sql = msg.pDb; + return msg.retCode; +} + +int CDbxSQLite::sql_close(sqlite3 *sql) +{ + TSqlMessage msg; + msg.op = SQL_CLOSE; + msg.pDb = sql; + sql_server_sync(&msg); + return msg.retCode; +} + +int CDbxSQLite::sql_prepare(sqlite3 *sql, const char *query, sqlite3_stmt **stmt) +{ + TSqlMessage msg; + msg.op = SQL_PREPARE; + msg.pDb = sql; + msg.zIn = query; + sql_server_sync(&msg); + *stmt = msg.pStmt; + return msg.retCode; +} + +int CDbxSQLite::sql_finalize(sqlite3_stmt *stmt) +{ + TSqlMessage msg; + msg.op = SQL_FINALIZE; + msg.pStmt = stmt; + sql_server_sync(&msg); + return msg.retCode; +} diff --git a/plugins/Import/src/import.cpp b/plugins/Import/src/import.cpp index 865d786b93..17aeaa073a 100644 --- a/plugins/Import/src/import.cpp +++ b/plugins/Import/src/import.cpp @@ -2,7 +2,7 @@ Import plugin for Miranda NG -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/plugins/Import/src/main.cpp b/plugins/Import/src/main.cpp index c800b5d611..f1c62ba97b 100644 --- a/plugins/Import/src/main.cpp +++ b/plugins/Import/src/main.cpp @@ -2,7 +2,7 @@ Import plugin for Miranda NG -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/plugins/Import/src/mcontacts.cpp b/plugins/Import/src/mcontacts.cpp index cfa826769f..5eb09ed6aa 100644 --- a/plugins/Import/src/mcontacts.cpp +++ b/plugins/Import/src/mcontacts.cpp @@ -1,322 +1,322 @@ -/* - -Import plugin for Miranda NG - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) - -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" - -#include -#include - -#define HEADER_STR "HB" - -///////////////////////////////////////////////////////////////////////////////////////// -// CDbxMcontacts database driver, read-only - -#pragma pack(push, 1) - -struct MC_FileHeader -{ - uint8_t signature[2]; - uint32_t version; - uint32_t dataSize; -}; - -struct MC_MsgHeader32 -{ - uint32_t cbSize; // size of the structure in bytes - uint32_t szModule; // pointer to name of the module that 'owns' this - // event, ie the one that is in control of the data format - uint32_t timestamp; // seconds since 00:00, 01/01/1970. Gives us times until - // 2106 unless you use the standard C library which is - // signed and can only do until 2038. In GMT. - uint32_t flags; // the omnipresent flags - uint32_t eventType; // module-defined event type field - uint32_t cbBlob; // size of pBlob in bytes - uint32_t pBlob; // pointer to buffer containing module-defined event data -}; - -struct MC_MsgHeader64 -{ - uint64_t cbSize; // size of the structure in bytes - uint64_t szModule; // pointer to name of the module that 'owns' this - // event, ie the one that is in control of the data format - uint32_t timestamp; // seconds since 00:00, 01/01/1970. Gives us times until - // 2106 unless you use the standard C library which is - // signed and can only do until 2038. In GMT. - uint32_t flags; // the omnipresent flags - uint32_t eventType; // module-defined event type field - uint32_t cbBlob; // size of pBlob in bytes - uint64_t pBlob; // pointer to buffer containing module-defined event data -}; - -#pragma pack(pop) - -class CDbxMc : public MDatabaseReadonly, public MZeroedObject -{ - HANDLE m_hFile = INVALID_HANDLE_VALUE; - - MC_FileHeader m_hdr; - - std::vector m_events; - std::vector::iterator m_curr; - - CMStringA readString() - { - CMStringA res; - char c; - DWORD dwRead; - while (ReadFile(m_hFile, &c, 1, &dwRead, 0)) { - if (c == 0) - break; - res.AppendChar(c); - } - return res; - } - -public: - CDbxMc() - {} - - ~CDbxMc() - { - if (m_hFile != INVALID_HANDLE_VALUE) - ::CloseHandle(m_hFile); - } - - void Load() - { - // mcontacts operates with the only contact with pseudo id=1 - m_cache->AddContactToCache(1); - - uint32_t pos = 0; - while (pos < m_hdr.dataSize) { - DWORD dwPos = SetFilePointer(m_hFile, 0, 0, FILE_CURRENT), dwRead, dwSize; - BOOL r = ReadFile(m_hFile, &dwSize, sizeof(dwSize), &dwRead, 0); - if (!r || dwRead < sizeof(dwSize)) - return; - if (dwSize != sizeof(MC_MsgHeader32) && dwSize != sizeof(MC_MsgHeader64)) - return; - - m_events.push_back(dwPos); - SetFilePointer(m_hFile, -4, 0, FILE_CURRENT); - - if (dwSize == sizeof(MC_MsgHeader32)) { - MC_MsgHeader32 hdr; - r = ReadFile(m_hFile, &hdr, sizeof(hdr), &dwRead, 0); - if (!r || dwRead < sizeof(hdr)) - return; - SetFilePointer(m_hFile, hdr.cbBlob, 0, FILE_CURRENT); - } - else { - MC_MsgHeader64 hdr; - r = ReadFile(m_hFile, &hdr, sizeof(hdr), &dwRead, 0); - if (!r || dwRead < sizeof(hdr)) - return; - SetFilePointer(m_hFile, hdr.cbBlob, 0, FILE_CURRENT); - } - pos += dwSize; - } - } - - int Open(const wchar_t *profile) - { - m_hFile = CreateFile(profile, GENERIC_READ, 0, 0, OPEN_ALWAYS, 0, 0); - if (m_hFile == INVALID_HANDLE_VALUE) - return EGROKPRF_CANTREAD; - - DWORD dwRead; - BOOL r = ReadFile(m_hFile, &m_hdr, sizeof(m_hdr), &dwRead, nullptr); - if (!r) - return EGROKPRF_CANTREAD; - - return memcmp(&m_hdr.signature, HEADER_STR, 2) ? EGROKPRF_UNKHEADER : EGROKPRF_NOERROR; - } - - // mcontacts format always store history for one contact only - STDMETHODIMP_(int) GetBlobSize(MEVENT dwOffset) override - { - if (INVALID_SET_FILE_POINTER == SetFilePointer(m_hFile, dwOffset, 0, FILE_BEGIN)) - return 0; - - DWORD dwRead, dwSize; - BOOL r = ReadFile(m_hFile, &dwSize, sizeof(dwSize), &dwRead, nullptr); - if (!r || dwRead != sizeof(dwSize)) - return 0; - - SetFilePointer(m_hFile, -4, 0, FILE_CURRENT); - - if (dwSize == sizeof(MC_MsgHeader32)) { - MC_MsgHeader32 hdr; - r = ReadFile(m_hFile, &hdr, sizeof(hdr), &dwRead, 0); - if (!r || dwRead != sizeof(hdr)) - return 0; - return hdr.cbBlob+1; - } - if (dwSize == sizeof(MC_MsgHeader64)) { - MC_MsgHeader64 hdr; - r = ReadFile(m_hFile, &hdr, sizeof(hdr), &dwRead, 0); - if (!r || dwRead != sizeof(hdr)) - return 0; - return hdr.cbBlob+1; - } - return 0; - } - - STDMETHODIMP_(int) GetContactCount(void) override - { - return 1; - } - - STDMETHODIMP_(int) GetEventCount(MCONTACT) override - { - return (int)m_events.size(); - } - - STDMETHODIMP_(BOOL) GetEvent(MEVENT dwOffset, DBEVENTINFO *dbei) override - { - if (INVALID_SET_FILE_POINTER == SetFilePointer(m_hFile, dwOffset, 0, FILE_BEGIN)) - return 1; - - DWORD dwRead, dwSize; - BOOL r = ReadFile(m_hFile, &dwSize, sizeof(dwSize), &dwRead, nullptr); - if (!r || dwRead != sizeof(dwSize)) - return 1; - - SetFilePointer(m_hFile, -4, 0, FILE_CURRENT); - - int cbLen; - if (dwSize == sizeof(MC_MsgHeader32)) { - MC_MsgHeader32 hdr; - r = ReadFile(m_hFile, &hdr, sizeof(hdr), &dwRead, 0); - if (!r || dwRead != sizeof(hdr)) - return 1; - - dbei->eventType = hdr.eventType; - cbLen = hdr.cbBlob; - dbei->flags = hdr.flags; - dbei->timestamp = hdr.timestamp; - } - else if (dwSize == sizeof(MC_MsgHeader64)) { - MC_MsgHeader64 hdr; - r = ReadFile(m_hFile, &hdr, sizeof(hdr), &dwRead, 0); - if (!r || dwRead != sizeof(hdr)) - return 1; - - dbei->eventType = hdr.eventType; - cbLen = hdr.cbBlob; - dbei->flags = hdr.flags; - dbei->timestamp = hdr.timestamp; - } - else return 1; - - if (dbei->cbBlob && cbLen) { - uint32_t copySize = min(uint32_t(cbLen), dbei->cbBlob-1); - if (!ReadFile(m_hFile, dbei->pBlob, copySize, &dwRead, 0) || dwRead != copySize) - return 0; - - dbei->cbBlob = copySize; - dbei->pBlob[copySize] = 0; - } - - return 0; - } - - STDMETHODIMP_(MEVENT) FindFirstEvent(MCONTACT) override - { - if (m_events.empty()) - return 0; - - m_curr = m_events.begin(); - return *m_curr; - } - - STDMETHODIMP_(MEVENT) FindNextEvent(MCONTACT, MEVENT) override - { - if (m_curr == m_events.end()) - return 0; - - ++m_curr; - return *m_curr; - } - - STDMETHODIMP_(MEVENT) FindLastEvent(MCONTACT) override - { - if (m_events.empty()) - return 0; - - m_curr = m_events.end(); - return *m_curr; - } - - STDMETHODIMP_(MEVENT) FindPrevEvent(MCONTACT, MEVENT) override - { - if (m_curr == m_events.begin()) - return 0; - - --m_curr; - return *m_curr; - } - - STDMETHODIMP_(DATABASELINK *) GetDriver() override; -}; - -///////////////////////////////////////////////////////////////////////////////////////// -// database link functions - -static int mc_makeDatabase(const wchar_t*) -{ - return 1; -} - -static int mc_grokHeader(const wchar_t *profile) -{ - return CDbxMc().Open(profile); -} - -static MDatabaseCommon* mc_load(const wchar_t *profile, BOOL) -{ - std::unique_ptr db(new CDbxMc()); - if (db->Open(profile)) - return nullptr; - - db->Load(); - return db.release(); -} - -static DATABASELINK dblink = -{ - 0, - "mcontacts", - L"mContacts file driver", - mc_makeDatabase, - mc_grokHeader, - mc_load -}; - -STDMETHODIMP_(DATABASELINK *) CDbxMc::GetDriver() -{ - return &dblink; -} - -void RegisterMContacts() -{ - RegisterDatabasePlugin(&dblink); -} +/* + +Import plugin for Miranda NG + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) + +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" + +#include +#include + +#define HEADER_STR "HB" + +///////////////////////////////////////////////////////////////////////////////////////// +// CDbxMcontacts database driver, read-only + +#pragma pack(push, 1) + +struct MC_FileHeader +{ + uint8_t signature[2]; + uint32_t version; + uint32_t dataSize; +}; + +struct MC_MsgHeader32 +{ + uint32_t cbSize; // size of the structure in bytes + uint32_t szModule; // pointer to name of the module that 'owns' this + // event, ie the one that is in control of the data format + uint32_t timestamp; // seconds since 00:00, 01/01/1970. Gives us times until + // 2106 unless you use the standard C library which is + // signed and can only do until 2038. In GMT. + uint32_t flags; // the omnipresent flags + uint32_t eventType; // module-defined event type field + uint32_t cbBlob; // size of pBlob in bytes + uint32_t pBlob; // pointer to buffer containing module-defined event data +}; + +struct MC_MsgHeader64 +{ + uint64_t cbSize; // size of the structure in bytes + uint64_t szModule; // pointer to name of the module that 'owns' this + // event, ie the one that is in control of the data format + uint32_t timestamp; // seconds since 00:00, 01/01/1970. Gives us times until + // 2106 unless you use the standard C library which is + // signed and can only do until 2038. In GMT. + uint32_t flags; // the omnipresent flags + uint32_t eventType; // module-defined event type field + uint32_t cbBlob; // size of pBlob in bytes + uint64_t pBlob; // pointer to buffer containing module-defined event data +}; + +#pragma pack(pop) + +class CDbxMc : public MDatabaseReadonly, public MZeroedObject +{ + HANDLE m_hFile = INVALID_HANDLE_VALUE; + + MC_FileHeader m_hdr; + + std::vector m_events; + std::vector::iterator m_curr; + + CMStringA readString() + { + CMStringA res; + char c; + DWORD dwRead; + while (ReadFile(m_hFile, &c, 1, &dwRead, 0)) { + if (c == 0) + break; + res.AppendChar(c); + } + return res; + } + +public: + CDbxMc() + {} + + ~CDbxMc() + { + if (m_hFile != INVALID_HANDLE_VALUE) + ::CloseHandle(m_hFile); + } + + void Load() + { + // mcontacts operates with the only contact with pseudo id=1 + m_cache->AddContactToCache(1); + + uint32_t pos = 0; + while (pos < m_hdr.dataSize) { + DWORD dwPos = SetFilePointer(m_hFile, 0, 0, FILE_CURRENT), dwRead, dwSize; + BOOL r = ReadFile(m_hFile, &dwSize, sizeof(dwSize), &dwRead, 0); + if (!r || dwRead < sizeof(dwSize)) + return; + if (dwSize != sizeof(MC_MsgHeader32) && dwSize != sizeof(MC_MsgHeader64)) + return; + + m_events.push_back(dwPos); + SetFilePointer(m_hFile, -4, 0, FILE_CURRENT); + + if (dwSize == sizeof(MC_MsgHeader32)) { + MC_MsgHeader32 hdr; + r = ReadFile(m_hFile, &hdr, sizeof(hdr), &dwRead, 0); + if (!r || dwRead < sizeof(hdr)) + return; + SetFilePointer(m_hFile, hdr.cbBlob, 0, FILE_CURRENT); + } + else { + MC_MsgHeader64 hdr; + r = ReadFile(m_hFile, &hdr, sizeof(hdr), &dwRead, 0); + if (!r || dwRead < sizeof(hdr)) + return; + SetFilePointer(m_hFile, hdr.cbBlob, 0, FILE_CURRENT); + } + pos += dwSize; + } + } + + int Open(const wchar_t *profile) + { + m_hFile = CreateFile(profile, GENERIC_READ, 0, 0, OPEN_ALWAYS, 0, 0); + if (m_hFile == INVALID_HANDLE_VALUE) + return EGROKPRF_CANTREAD; + + DWORD dwRead; + BOOL r = ReadFile(m_hFile, &m_hdr, sizeof(m_hdr), &dwRead, nullptr); + if (!r) + return EGROKPRF_CANTREAD; + + return memcmp(&m_hdr.signature, HEADER_STR, 2) ? EGROKPRF_UNKHEADER : EGROKPRF_NOERROR; + } + + // mcontacts format always store history for one contact only + STDMETHODIMP_(int) GetBlobSize(MEVENT dwOffset) override + { + if (INVALID_SET_FILE_POINTER == SetFilePointer(m_hFile, dwOffset, 0, FILE_BEGIN)) + return 0; + + DWORD dwRead, dwSize; + BOOL r = ReadFile(m_hFile, &dwSize, sizeof(dwSize), &dwRead, nullptr); + if (!r || dwRead != sizeof(dwSize)) + return 0; + + SetFilePointer(m_hFile, -4, 0, FILE_CURRENT); + + if (dwSize == sizeof(MC_MsgHeader32)) { + MC_MsgHeader32 hdr; + r = ReadFile(m_hFile, &hdr, sizeof(hdr), &dwRead, 0); + if (!r || dwRead != sizeof(hdr)) + return 0; + return hdr.cbBlob+1; + } + if (dwSize == sizeof(MC_MsgHeader64)) { + MC_MsgHeader64 hdr; + r = ReadFile(m_hFile, &hdr, sizeof(hdr), &dwRead, 0); + if (!r || dwRead != sizeof(hdr)) + return 0; + return hdr.cbBlob+1; + } + return 0; + } + + STDMETHODIMP_(int) GetContactCount(void) override + { + return 1; + } + + STDMETHODIMP_(int) GetEventCount(MCONTACT) override + { + return (int)m_events.size(); + } + + STDMETHODIMP_(BOOL) GetEvent(MEVENT dwOffset, DBEVENTINFO *dbei) override + { + if (INVALID_SET_FILE_POINTER == SetFilePointer(m_hFile, dwOffset, 0, FILE_BEGIN)) + return 1; + + DWORD dwRead, dwSize; + BOOL r = ReadFile(m_hFile, &dwSize, sizeof(dwSize), &dwRead, nullptr); + if (!r || dwRead != sizeof(dwSize)) + return 1; + + SetFilePointer(m_hFile, -4, 0, FILE_CURRENT); + + int cbLen; + if (dwSize == sizeof(MC_MsgHeader32)) { + MC_MsgHeader32 hdr; + r = ReadFile(m_hFile, &hdr, sizeof(hdr), &dwRead, 0); + if (!r || dwRead != sizeof(hdr)) + return 1; + + dbei->eventType = hdr.eventType; + cbLen = hdr.cbBlob; + dbei->flags = hdr.flags; + dbei->timestamp = hdr.timestamp; + } + else if (dwSize == sizeof(MC_MsgHeader64)) { + MC_MsgHeader64 hdr; + r = ReadFile(m_hFile, &hdr, sizeof(hdr), &dwRead, 0); + if (!r || dwRead != sizeof(hdr)) + return 1; + + dbei->eventType = hdr.eventType; + cbLen = hdr.cbBlob; + dbei->flags = hdr.flags; + dbei->timestamp = hdr.timestamp; + } + else return 1; + + if (dbei->cbBlob && cbLen) { + uint32_t copySize = min(uint32_t(cbLen), dbei->cbBlob-1); + if (!ReadFile(m_hFile, dbei->pBlob, copySize, &dwRead, 0) || dwRead != copySize) + return 0; + + dbei->cbBlob = copySize; + dbei->pBlob[copySize] = 0; + } + + return 0; + } + + STDMETHODIMP_(MEVENT) FindFirstEvent(MCONTACT) override + { + if (m_events.empty()) + return 0; + + m_curr = m_events.begin(); + return *m_curr; + } + + STDMETHODIMP_(MEVENT) FindNextEvent(MCONTACT, MEVENT) override + { + if (m_curr == m_events.end()) + return 0; + + ++m_curr; + return *m_curr; + } + + STDMETHODIMP_(MEVENT) FindLastEvent(MCONTACT) override + { + if (m_events.empty()) + return 0; + + m_curr = m_events.end(); + return *m_curr; + } + + STDMETHODIMP_(MEVENT) FindPrevEvent(MCONTACT, MEVENT) override + { + if (m_curr == m_events.begin()) + return 0; + + --m_curr; + return *m_curr; + } + + STDMETHODIMP_(DATABASELINK *) GetDriver() override; +}; + +///////////////////////////////////////////////////////////////////////////////////////// +// database link functions + +static int mc_makeDatabase(const wchar_t*) +{ + return 1; +} + +static int mc_grokHeader(const wchar_t *profile) +{ + return CDbxMc().Open(profile); +} + +static MDatabaseCommon* mc_load(const wchar_t *profile, BOOL) +{ + std::unique_ptr db(new CDbxMc()); + if (db->Open(profile)) + return nullptr; + + db->Load(); + return db.release(); +} + +static DATABASELINK dblink = +{ + 0, + "mcontacts", + L"mContacts file driver", + mc_makeDatabase, + mc_grokHeader, + mc_load +}; + +STDMETHODIMP_(DATABASELINK *) CDbxMc::GetDriver() +{ + return &dblink; +} + +void RegisterMContacts() +{ + RegisterDatabasePlugin(&dblink); +} diff --git a/plugins/Import/src/miranda.cpp b/plugins/Import/src/miranda.cpp index 7970027fe6..c43fc61a4d 100644 --- a/plugins/Import/src/miranda.cpp +++ b/plugins/Import/src/miranda.cpp @@ -2,7 +2,7 @@ Import plugin for Miranda NG -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/plugins/Import/src/patterns.cpp b/plugins/Import/src/patterns.cpp index 094bf1f33c..9dadce018c 100644 --- a/plugins/Import/src/patterns.cpp +++ b/plugins/Import/src/patterns.cpp @@ -1,732 +1,732 @@ -/* - -Import plugin for Miranda NG - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) - -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" - -#include -#include - -void CMPlugin::LoadPatterns() -{ - wchar_t wszPath[MAX_PATH], wszFullPath[MAX_PATH]; - GetModuleFileNameW(m_hInst, wszPath, _countof(wszPath)); - if (auto *p = wcsrchr(wszPath, '\\')) - *p = 0; - - mir_snwprintf(wszFullPath, L"%s\\Import\\*.ini", wszPath); - - WIN32_FIND_DATAW fd; - HANDLE hFind = FindFirstFileW(wszFullPath, &fd); - if (hFind == INVALID_HANDLE_VALUE) - return; - - do { - mir_snwprintf(wszFullPath, L"%s\\Import\\%s", wszPath, fd.cFileName); - LoadPattern(wszFullPath); - } - while (FindNextFileW(hFind, &fd) != 0); -} - -void CMPlugin::LoadPattern(const wchar_t *pwszFileName) -{ - // [General] section - wchar_t buf[1024]; - if (!GetPrivateProfileStringW(L"General", L"Name", L"", buf, _countof(buf), pwszFileName)) - return; - - std::unique_ptr pNew(new CImportPattern()); - pNew->wszName = buf; - pNew->iType = GetPrivateProfileIntW(L"General", L"Type", 1, pwszFileName); - - if (GetPrivateProfileStringW(L"General", L"DefaultExtension", L"", buf, _countof(buf), pwszFileName)) - pNew->wszExt = buf; - - if (pNew->iType == 1) { - if (GetPrivateProfileStringW(L"General", L"Charset", L"", buf, _countof(buf), pwszFileName)) { - if (!wcsicmp(buf, L"ANSI")) - pNew->iCodePage = GetPrivateProfileIntW(L"General", L"Codepage", CP_ACP, pwszFileName); - else if (!wcsicmp(buf, L"UCS2")) - pNew->iCodePage = 1200; - } - else return; - } - - pNew->iUseHeader = GetPrivateProfileIntW(L"General", L"UseHeader", 0, pwszFileName); - pNew->iUsePreMsg = GetPrivateProfileIntW(L"General", L"UsePreMsg", 0, pwszFileName); - pNew->iUseFilename = GetPrivateProfileIntW(L"General", L"UseFileName", 0, pwszFileName); - - // [Message] section - int erroffset; - const char *err; - if (pNew->iType == 1) { - if (GetPrivateProfileStringW(L"Message", L"Pattern", L"", buf, _countof(buf), pwszFileName)) { - if ((pNew->regMessage.pattern = pcre16_compile(buf, PCRE_MULTILINE, &err, &erroffset, nullptr)) == nullptr) - return; - pNew->regMessage.extra = pcre16_study(pNew->regMessage.pattern, 0, &err); - } - else return; - - if (GetPrivateProfileStringW(L"Message", L"In", L"", buf, _countof(buf), pwszFileName)) - pNew->wszIncoming = buf; - if (GetPrivateProfileStringW(L"Message", L"Out", L"", buf, _countof(buf), pwszFileName)) - pNew->wszOutgoing = buf; - - pNew->iDirection = GetPrivateProfileIntW(L"Message", L"Direction", 0, pwszFileName); - pNew->iDay = GetPrivateProfileIntW(L"Message", L"Day", 0, pwszFileName); - pNew->iMonth = GetPrivateProfileIntW(L"Message", L"Month", 0, pwszFileName); - pNew->iYear = GetPrivateProfileIntW(L"Message", L"Year", 0, pwszFileName); - pNew->iHours = GetPrivateProfileIntW(L"Message", L"Hours", 0, pwszFileName); - pNew->iMinutes = GetPrivateProfileIntW(L"Message", L"Minutes", 0, pwszFileName); - pNew->iSeconds = GetPrivateProfileIntW(L"Message", L"Seconds", 0, pwszFileName); - } - - if (pNew->iUseHeader) { - if (GetPrivateProfileStringW(L"Header", L"Pattern", L"", buf, _countof(buf), pwszFileName)) { - if ((pNew->regHeader.pattern = pcre16_compile(buf, PCRE_MULTILINE, &err, &erroffset, nullptr)) == nullptr) - return; - pNew->regHeader.extra = pcre16_study(pNew->regMessage.pattern, 0, &err); - } - else return; - - pNew->iHdrIncoming = GetPrivateProfileIntW(L"Header", L"In", 0, pwszFileName); - pNew->iHdrOutgoing = GetPrivateProfileIntW(L"Header", L"Out", 0, pwszFileName); - pNew->iHdrInNick = GetPrivateProfileIntW(L"Header", L"InNick", 0, pwszFileName); - pNew->iHdrOutNick = GetPrivateProfileIntW(L"Header", L"OutNick", 0, pwszFileName); - pNew->iHdrInUID = GetPrivateProfileIntW(L"Header", L"InUID", 0, pwszFileName); - pNew->iHdrOutUID = GetPrivateProfileIntW(L"Header", L"OutUID", 0, pwszFileName); - } - - if (pNew->iUsePreMsg) { - pNew->preRN = GetPrivateProfileIntW(L"PreMessage", L"PreRN", -1, pwszFileName); - pNew->preSP = GetPrivateProfileIntW(L"PreMessage", L"PreSP", 0, pwszFileName); - pNew->afterRN = GetPrivateProfileIntW(L"PreMessage", L"AfterRN", -1, pwszFileName); - pNew->afterSP = GetPrivateProfileIntW(L"PreMessage", L"AfterSP", 0, pwszFileName); - } - - if (pNew->iUseFilename) { - if (!GetPrivateProfileStringW(L"FileName", L"Pattern", L"", buf, _countof(buf), pwszFileName)) - return; - if ((pNew->regFilename.pattern = pcre16_compile(buf, 0, &err, &erroffset, nullptr)) == nullptr) - return; - pNew->regFilename.extra = pcre16_study(pNew->regFilename.pattern, 0, &err); - - pNew->iInNick = GetPrivateProfileIntW(L"FileName", L"InNick", 0, pwszFileName); - pNew->iInUID = GetPrivateProfileIntW(L"FileName", L"InUID", 0, pwszFileName); - pNew->iOutNick = GetPrivateProfileIntW(L"FileName", L"OutNick", 0, pwszFileName); - pNew->iOutUID = GetPrivateProfileIntW(L"FileName", L"OutUID", 0, pwszFileName); - } - - m_patterns.insert(pNew.release()); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// pattern-based database driver - -class CDbxPattern : public MDatabaseReadonly, public MZeroedObject -{ - typedef MDatabaseReadonly CSuper; - - CMStringW m_buf, m_folder; - MCONTACT m_hCurrContact = INVALID_CONTACT_ID; - HANDLE m_hFile = INVALID_HANDLE_VALUE, m_hMap = 0; - const uint8_t *m_pFile = 0; - int m_iFileVersion = 0, m_iMsgHeaderSize = 0; - - std::vector m_events; - std::vector m_files; - - bool CheckContact(MCONTACT hContact) - { - if (hContact != m_hCurrContact) { - m_hCurrContact = hContact; - if (!Load(m_files[hContact - 1])) - return false; - } - return true; - } - - //////////////////////////////////////////////////////////////////////////////////////// - // QHF file format - - bool LoadBinaryFile(const uint8_t *pFile, uint32_t iSize) - { - if (memicmp(pFile, "QHF", 3)) { - AddMessage(LPGENW("Invalid file header")); - return false; - } - - m_iFileVersion = pFile[3]; - - uint32_t fsz = RLInteger(&pFile[4]); pFile += 0x2C; - uint32_t UIDLen = RLWord(pFile); pFile += 2; - char *UIDStr = (char*)_alloca(UIDLen + 2); - if (m_iFileVersion <= 2) - strncpy_s(UIDStr, UIDLen + 2, (char *)pFile, UIDLen); - else - strncpy_s(UIDStr, UIDLen + 2, (char *)pFile, UIDLen + 1); - pFile += UIDLen; - - uint32_t NickLen = RLWord(pFile); pFile += 2; - char *NickStr = (char*)_alloca(NickLen + 2); - if (m_iFileVersion <= 2) - strncpy_s(NickStr, NickLen + 2, (char*)pFile, NickLen); - else - strncpy_s(NickStr, NickLen + 2, (char*)pFile, NickLen + 1); - pFile += NickLen; - - DBCONTACTWRITESETTING dbcws = {}; - dbcws.szModule = "Pattern"; - dbcws.value.type = DBVT_UTF8; - - dbcws.szSetting = "ID"; - dbcws.value.pszVal = UIDStr; - WriteContactSetting(m_hCurrContact, &dbcws); - - dbcws.szSetting = "Nick"; - dbcws.value.pszVal = NickStr; - WriteContactSetting(m_hCurrContact, &dbcws); - - uint32_t iHeaderSize = 0x30 + NickLen + UIDLen; - if (fsz != iSize - iHeaderSize) - fsz = iSize - iHeaderSize; - - m_iMsgHeaderSize = (m_iFileVersion >= 3) ? 0x23 : 0x21; - for (uint32_t i = 0; i < fsz; i += m_iMsgHeaderSize) { - m_events.push_back(i + iHeaderSize); - i += RLWord(&pFile[i + m_iMsgHeaderSize - 2]); - } - - return true; - } - - //////////////////////////////////////////////////////////////////////////////////////// - // Text file format, parsed by regexps - - bool LoadTextFile(const uint8_t *pFile) - { - auto *pPattern = g_pBatch->m_pPattern; - - switch (pPattern->iCodePage) { - case CP_UTF8: - m_buf = mir_utf8decodeW((char*)pFile); - break; - case 1200: - m_buf = mir_wstrdup((wchar_t*)pFile); - break; - default: - m_buf = mir_a2u_cp((char*)pFile, pPattern->iCodePage); - break; - } - - - // smth went wrong or empty file - if (m_buf.IsEmpty()) - return false; - - int iOffset = 0; - if (m_buf[0] == 0xFEFF) - m_buf.Delete(0); - - if (pPattern->iUseHeader) { - int offsets[99]; - int nMatch = pcre16_exec(pPattern->regHeader.pattern, pPattern->regHeader.extra, m_buf, m_buf.GetLength(), iOffset, PCRE_NEWLINE_ANYCRLF, offsets, _countof(offsets)); - if (nMatch <= 0) { - AddMessage(LPGENW("Cannot parse file header, skipping file")); - return false; - } - - const wchar_t **substrings; - if (pcre16_get_substring_list(m_buf, offsets, nMatch, &substrings) >= 0) { - if (pPattern->iUseHeader & 1) { - pPattern->wszIncoming = substrings[pPattern->iHdrIncoming]; - pPattern->wszOutgoing = substrings[pPattern->iHdrOutgoing]; - } - - if (pPattern->iUseHeader & 2) { - DBCONTACTWRITESETTING dbcws = {}; - dbcws.szModule = "Pattern"; - dbcws.value.type = DBVT_WCHAR; - - if (pPattern->iInUID && substrings[pPattern->iHdrInUID]) { - dbcws.szSetting = "ID"; - dbcws.value.pwszVal = (wchar_t *)substrings[pPattern->iHdrInUID]; - WriteContactSetting(m_hCurrContact, &dbcws); - } - - if (pPattern->iInNick && substrings[pPattern->iHdrInNick]) { - dbcws.szSetting = "Nick"; - dbcws.value.pwszVal = (wchar_t *)substrings[pPattern->iHdrInNick]; - WriteContactSetting(m_hCurrContact, &dbcws); - } - } - } - - iOffset = offsets[1]; - } - - while (true) { - int offsets[99]; - int nMatch = pcre16_exec(pPattern->regMessage.pattern, pPattern->regMessage.extra, m_buf, m_buf.GetLength(), iOffset, PCRE_NEWLINE_ANYCRLF, offsets, _countof(offsets)); - if (nMatch <= 0) - break; - - m_events.push_back(offsets[0]); - iOffset = offsets[1]; - } - return true; - } - -public: - CDbxPattern() - {} - - ~CDbxPattern() - { - Close(); - } - - void Close() - { - if (m_pFile != nullptr) - ::UnmapViewOfFile(m_pFile); - - if (m_hMap != nullptr) - ::CloseHandle(m_hMap); - - if (m_hFile != INVALID_HANDLE_VALUE) - ::CloseHandle(m_hFile); - } - - bool Load(const wchar_t *pwszFileName) - { - m_buf.Empty(); - m_events.clear(); - Close(); - - AddMessage(LPGENW("Loading file '%s'..."), pwszFileName); - - m_hFile = ::CreateFileW(pwszFileName, GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, 0); - if (m_hFile == INVALID_HANDLE_VALUE) { - AddMessage(LPGENW("Failed to open file <%s> for import: %d"), pwszFileName, GetLastError()); - return false; - } - - uint32_t cbLen = ::GetFileSize(m_hFile, 0); - m_hMap = ::CreateFileMappingW(m_hFile, nullptr, PAGE_READONLY, 0, 0, L"ImportMapfile"); - if (m_hMap == nullptr) { - AddMessage(LPGENW("Failed to mmap file <%s> for import: %d"), pwszFileName, GetLastError()); - return false; - } - - m_pFile = (const uint8_t*)::MapViewOfFile(m_hMap, FILE_MAP_READ, 0, 0, 0); - if (m_pFile == nullptr) { - AddMessage(LPGENW("Failed to map view of file <%s> for import: %d"), pwszFileName, GetLastError()); - return false; - } - - if (g_pBatch->m_pPattern->iType == 1) // text file - return LoadTextFile(m_pFile); - return LoadBinaryFile(m_pFile, cbLen); - } - - int Open(const wchar_t *profile) - { - CMStringW wszBaseFolder(profile); - auto *pPattern = g_pBatch->m_pPattern; - - // create a mask for loading multiple data files for a folder - uint32_t dwAttr = GetFileAttributesW(profile); - if (dwAttr & FILE_ATTRIBUTE_DIRECTORY) { - wszBaseFolder = profile; - m_folder.AppendFormat(L"%s\\*.%s", profile, pPattern->wszExt.c_str()); - } - else { - int i = wszBaseFolder.ReverseFind('\\'); - if (i != -1) - wszBaseFolder = wszBaseFolder.Left(i); - m_folder = profile; - } - - int hContact = 1; - WIN32_FIND_DATA fd; - HANDLE hFind = FindFirstFile(m_folder, &fd); - if (hFind != INVALID_HANDLE_VALUE) { - do { - // find all subfolders except "." and ".." - if (!mir_wstrcmp(fd.cFileName, L".") || !mir_wstrcmp(fd.cFileName, L"..")) - continue; - - CMStringW wszFullName(wszBaseFolder + L"\\" + fd.cFileName); - m_files.push_back(wszFullName); - - auto *cc = m_cache->AddContactToCache(hContact); - cc->szProto = "Pattern"; - - // we try to restore user id from the file name - if (pPattern->iUseFilename) { - int offsets[100]; - int nMatch = pcre16_exec(pPattern->regFilename.pattern, pPattern->regFilename.extra, wszFullName, wszFullName.GetLength(), 0, 0, offsets, _countof(offsets)); - if (nMatch > 0) { - const wchar_t **substrings; - if (pcre16_get_substring_list(wszFullName, offsets, nMatch, &substrings) >= 0) { - DBCONTACTWRITESETTING dbcws = {}; - dbcws.szModule = cc->szProto; - dbcws.value.type = DBVT_WCHAR; - - if (pPattern->iInUID && substrings[pPattern->iInUID]) { - dbcws.szSetting = "ID"; - dbcws.value.pwszVal = (wchar_t*)substrings[pPattern->iInUID]; - WriteContactSetting(hContact, &dbcws); - } - - if (pPattern->iInNick && substrings[pPattern->iInNick]) { - dbcws.szSetting = "Nick"; - dbcws.value.pwszVal = (wchar_t*)substrings[pPattern->iInNick]; - WriteContactSetting(hContact, &dbcws); - } - - pcre16_free_substring_list(substrings); - } - } - } - hContact++; - } - while (FindNextFile(hFind, &fd)); - - FindClose(hFind); - } - - if (m_files.empty()) - return EGROKPRF_CANTREAD; - - return EGROKPRF_NOERROR; - } - - // patterns file always stores history for the single contact only - STDMETHODIMP_(int) GetBlobSize(MEVENT idx) override - { - if (m_events.size() == 0 || idx < 1 || idx > m_events.size()) - return 0; - - if (g_pBatch->m_pPattern->iType == 1) { - int iStart = m_events[idx-1], iEnd = (idx == m_events.size()) ? m_buf.GetLength() : m_events[idx]; - CMStringW msg = m_buf.Mid(iStart, iEnd - iStart); - return (LONG)mir_strlen(ptrA(mir_utf8encodeW(msg))) + 1; - } - - if (m_pFile == nullptr) - return 0; - - const uint8_t *pMsg = m_pFile + m_events[idx-1]; - return RLWord(&pMsg[m_iMsgHeaderSize - 2]) + 1; - } - - STDMETHODIMP_(int) GetContactCount(void) override - { - return (int)m_files.size(); - } - - STDMETHODIMP_(MCONTACT) FindFirstContact(const char *szProto) override - { - MCONTACT ret = CSuper::FindFirstContact(szProto); - if (ret != 0) - if (!CheckContact(ret)) - return 0; - return ret; - } - - STDMETHODIMP_(MCONTACT) FindNextContact(MCONTACT contactID, const char *szProto) override - { - MCONTACT ret = CSuper::FindNextContact(contactID, szProto); - if (ret != 0) - if (!CheckContact(ret)) - return 0; - return ret; - } - - STDMETHODIMP_(int) GetEventCount(MCONTACT) override - { - return (int)m_events.size(); - } - - STDMETHODIMP_(BOOL) GetContactSettingWorker(MCONTACT hContact, LPCSTR szModule, LPCSTR szSetting, DBVARIANT* dbv, int isStatic) - { - if (szSetting == nullptr || szModule == nullptr) - return 1; - - DBCachedContact *cc = nullptr; - if (hContact) { - cc = m_cache->GetCachedContact(hContact); - if (cc == nullptr) - return 1; - } - - size_t settingNameLen = strlen(szSetting); - size_t moduleNameLen = strlen(szModule); - char* szCachedSettingName = m_cache->GetCachedSetting(szModule, szSetting, moduleNameLen, settingNameLen); - - DBVARIANT *pCachedValue = m_cache->GetCachedValuePtr(hContact, szCachedSettingName, 0); - if (pCachedValue != nullptr) { - if (pCachedValue->type == DBVT_ASCIIZ || 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)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(strlen(pCachedValue->pszVal) + 1); - strcpy(dbv->pszVal, pCachedValue->pszVal); - } - } - else memcpy(dbv, pCachedValue, sizeof(DBVARIANT)); - - return (pCachedValue->type == DBVT_DELETED) ? 1 : 0; - } - - return 1; - } - - STDMETHODIMP_(BOOL) 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 dbcwWork = *dbcws; - if (dbcwWork.value.type == DBVT_WCHAR) { - T2Utf value(dbcwWork.value.pwszVal); - dbcwWork.value.pszVal = NEWSTR_ALLOCA(value); - dbcwWork.value.type = DBVT_UTF8; - dbcwWork.value.cchVal = (uint16_t)strlen(dbcwWork.value.pszVal); - } - - char* cachedSettingName = m_cache->GetCachedSetting(dbcwWork.szModule, dbcwWork.szSetting, mir_strlen(dbcwWork.szModule), mir_strlen(dbcwWork.szSetting)); - DBVARIANT* cachedValue = m_cache->GetCachedValuePtr(hContact, cachedSettingName, 1); - if (cachedValue != nullptr) - m_cache->SetCachedVariant(&dbcwWork.value, cachedValue); - - return 0; - } - - //////////////////////////////////////////////////////////////////////////////////////// - - static int str2int(const wchar_t* str) - { - if (str == nullptr || *str == 0) - return 0; - - return _wtoi(str); - } - - int getBinaryEvent(MEVENT idx, DBEVENTINFO *dbei) - { - if (m_pFile == nullptr) - return 1; - - const uint8_t *pMsg = m_pFile + m_events[idx-1]; - - dbei->eventType = EVENTTYPE_MESSAGE; - dbei->flags = DBEF_READ | DBEF_UTF; - if (pMsg[0x1A] != 0) - dbei->flags |= DBEF_SENT; - dbei->timestamp = RLInteger(&pMsg[0x12]); - dbei->timestamp -= TimeZone_ToLocal(dbei->timestamp) - dbei->timestamp; // deduct time zone offset from timestamp - dbei->cbBlob = RLWord(&pMsg[m_iMsgHeaderSize - 2]); - dbei->pBlob = (uint8_t*)mir_alloc(dbei->cbBlob + 1); - memcpy(dbei->pBlob, pMsg + m_iMsgHeaderSize, dbei->cbBlob); - if (m_iFileVersion != 1) - for (int i = 0; i < dbei->cbBlob; i++) { - dbei->pBlob[i] += i+1; - dbei->pBlob[i] = 255 - dbei->pBlob[i]; - } - - dbei->pBlob[dbei->cbBlob] = 0; - return 0; - } - - int getTextEvent(MEVENT idx, DBEVENTINFO *dbei) - { - auto *pPattern = g_pBatch->m_pPattern; - - int offsets[99]; - int nMatch = pcre16_exec(pPattern->regMessage.pattern, pPattern->regMessage.extra, m_buf, m_buf.GetLength(), m_events[idx-1], PCRE_NEWLINE_ANYCRLF, offsets, _countof(offsets)); - if (nMatch <= 0) - return 1; - - dbei->eventType = EVENTTYPE_MESSAGE; - dbei->flags = DBEF_READ | DBEF_UTF; - - int h1 = offsets[1], h2 = (idx == m_events.size()) ? m_buf.GetLength() : m_events[idx]; - int prn = -1, arn = -1; - if (pPattern->iUsePreMsg) - prn = pPattern->preRN, arn = pPattern->afterRN; - - if (prn != 0) { - int i = 0; - while (m_buf[h1] == '\r' && m_buf[h1 + 1] == '\n' && i < prn) - h1 += 2, i++; - } - - if (arn != 0) { - int i = 0; - while (m_buf[h2 - 2] == '\r' && m_buf[h2 - 1] == '\n' && i < arn) - h2 -= 2, i++; - } - - if (dbei->cbBlob) { - CMStringW wszBody = m_buf.Mid(h1, h2 - h1).Trim(); - if (!wszBody.IsEmpty()) { - ptrA tmp(mir_utf8encodeW(wszBody)); - int copySize = min(dbei->cbBlob - 1, (int)mir_strlen(tmp)); - memcpy(dbei->pBlob, tmp, copySize); - dbei->pBlob[copySize] = 0; - dbei->cbBlob = copySize; - } - else dbei->cbBlob = 0; - } - - const wchar_t **substrings; - if (pcre16_get_substring_list(m_buf, offsets, nMatch, &substrings) >= 0) { - struct tm st = {}; - st.tm_year = str2int(substrings[pPattern->iYear]); - if (st.tm_year > 1900) - st.tm_year -= 1900; - st.tm_mon = str2int(substrings[pPattern->iMonth]) - 1; - st.tm_mday = str2int(substrings[pPattern->iDay]); - st.tm_hour = str2int(substrings[pPattern->iHours]); - st.tm_min = str2int(substrings[pPattern->iMinutes]); - st.tm_sec = (pPattern->iSeconds) ? str2int(substrings[pPattern->iSeconds]) : 0; - dbei->timestamp = mktime(&st); - - if (pPattern->iDirection) - if (pPattern->wszOutgoing == substrings[pPattern->iDirection]) - dbei->flags |= DBEF_SENT; - - - pcre16_free_substring_list(substrings); - } - return 0; - } - - STDMETHODIMP_(BOOL) GetEvent(MEVENT idx, DBEVENTINFO *dbei) override - { - if (dbei == nullptr || m_events.size() == 0 || idx < 1 || idx > m_events.size()) - return 1; - - if (g_pBatch->m_pPattern->iType == 1) - return getTextEvent(idx, dbei); - - return getBinaryEvent(idx, dbei); - } - - STDMETHODIMP_(MEVENT) FindFirstEvent(MCONTACT hContact) override - { - // no system history - if (hContact == 0) - return 0; - - if (!CheckContact(hContact)) - return 0; - - return m_events.size() > 0 ? 1 : 0; - } - - STDMETHODIMP_(MEVENT) FindNextEvent(MCONTACT, MEVENT idx) override - { - if (idx >= m_events.size()) - return 0; - - return idx + 1; - } - - STDMETHODIMP_(MEVENT) FindLastEvent(MCONTACT hContact) override - { - // no system history - if (hContact == 0) - return 0; - - if (!CheckContact(hContact)) - return 0; - - return m_events.size() > 0 ? (MEVENT)m_events.size() : 0; - } - - STDMETHODIMP_(MEVENT) FindPrevEvent(MCONTACT, MEVENT idx) override - { - return (idx >= 1) ? idx-1 : 0; - } - - STDMETHODIMP_(DATABASELINK *) GetDriver(); -}; - -///////////////////////////////////////////////////////////////////////////////////////// -// database link functions - -static int pattern_makeDatabase(const wchar_t*) -{ - return 1; -} - -static int pattern_grokHeader(const wchar_t *profile) -{ - return CDbxPattern().Open(profile); -} - -static MDatabaseCommon* pattern_load(const wchar_t *profile, BOOL) -{ - std::unique_ptr db(new CDbxPattern()); - if (db->Open(profile)) - return nullptr; - - return db.release(); -} - -DATABASELINK g_patternDbLink = -{ - 0, - "pattern", - L"Pattern-based file driver", - pattern_makeDatabase, - pattern_grokHeader, - pattern_load -}; - -STDMETHODIMP_(DATABASELINK *) CDbxPattern::GetDriver() -{ - return &g_patternDbLink; -} +/* + +Import plugin for Miranda NG + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) + +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" + +#include +#include + +void CMPlugin::LoadPatterns() +{ + wchar_t wszPath[MAX_PATH], wszFullPath[MAX_PATH]; + GetModuleFileNameW(m_hInst, wszPath, _countof(wszPath)); + if (auto *p = wcsrchr(wszPath, '\\')) + *p = 0; + + mir_snwprintf(wszFullPath, L"%s\\Import\\*.ini", wszPath); + + WIN32_FIND_DATAW fd; + HANDLE hFind = FindFirstFileW(wszFullPath, &fd); + if (hFind == INVALID_HANDLE_VALUE) + return; + + do { + mir_snwprintf(wszFullPath, L"%s\\Import\\%s", wszPath, fd.cFileName); + LoadPattern(wszFullPath); + } + while (FindNextFileW(hFind, &fd) != 0); +} + +void CMPlugin::LoadPattern(const wchar_t *pwszFileName) +{ + // [General] section + wchar_t buf[1024]; + if (!GetPrivateProfileStringW(L"General", L"Name", L"", buf, _countof(buf), pwszFileName)) + return; + + std::unique_ptr pNew(new CImportPattern()); + pNew->wszName = buf; + pNew->iType = GetPrivateProfileIntW(L"General", L"Type", 1, pwszFileName); + + if (GetPrivateProfileStringW(L"General", L"DefaultExtension", L"", buf, _countof(buf), pwszFileName)) + pNew->wszExt = buf; + + if (pNew->iType == 1) { + if (GetPrivateProfileStringW(L"General", L"Charset", L"", buf, _countof(buf), pwszFileName)) { + if (!wcsicmp(buf, L"ANSI")) + pNew->iCodePage = GetPrivateProfileIntW(L"General", L"Codepage", CP_ACP, pwszFileName); + else if (!wcsicmp(buf, L"UCS2")) + pNew->iCodePage = 1200; + } + else return; + } + + pNew->iUseHeader = GetPrivateProfileIntW(L"General", L"UseHeader", 0, pwszFileName); + pNew->iUsePreMsg = GetPrivateProfileIntW(L"General", L"UsePreMsg", 0, pwszFileName); + pNew->iUseFilename = GetPrivateProfileIntW(L"General", L"UseFileName", 0, pwszFileName); + + // [Message] section + int erroffset; + const char *err; + if (pNew->iType == 1) { + if (GetPrivateProfileStringW(L"Message", L"Pattern", L"", buf, _countof(buf), pwszFileName)) { + if ((pNew->regMessage.pattern = pcre16_compile(buf, PCRE_MULTILINE, &err, &erroffset, nullptr)) == nullptr) + return; + pNew->regMessage.extra = pcre16_study(pNew->regMessage.pattern, 0, &err); + } + else return; + + if (GetPrivateProfileStringW(L"Message", L"In", L"", buf, _countof(buf), pwszFileName)) + pNew->wszIncoming = buf; + if (GetPrivateProfileStringW(L"Message", L"Out", L"", buf, _countof(buf), pwszFileName)) + pNew->wszOutgoing = buf; + + pNew->iDirection = GetPrivateProfileIntW(L"Message", L"Direction", 0, pwszFileName); + pNew->iDay = GetPrivateProfileIntW(L"Message", L"Day", 0, pwszFileName); + pNew->iMonth = GetPrivateProfileIntW(L"Message", L"Month", 0, pwszFileName); + pNew->iYear = GetPrivateProfileIntW(L"Message", L"Year", 0, pwszFileName); + pNew->iHours = GetPrivateProfileIntW(L"Message", L"Hours", 0, pwszFileName); + pNew->iMinutes = GetPrivateProfileIntW(L"Message", L"Minutes", 0, pwszFileName); + pNew->iSeconds = GetPrivateProfileIntW(L"Message", L"Seconds", 0, pwszFileName); + } + + if (pNew->iUseHeader) { + if (GetPrivateProfileStringW(L"Header", L"Pattern", L"", buf, _countof(buf), pwszFileName)) { + if ((pNew->regHeader.pattern = pcre16_compile(buf, PCRE_MULTILINE, &err, &erroffset, nullptr)) == nullptr) + return; + pNew->regHeader.extra = pcre16_study(pNew->regMessage.pattern, 0, &err); + } + else return; + + pNew->iHdrIncoming = GetPrivateProfileIntW(L"Header", L"In", 0, pwszFileName); + pNew->iHdrOutgoing = GetPrivateProfileIntW(L"Header", L"Out", 0, pwszFileName); + pNew->iHdrInNick = GetPrivateProfileIntW(L"Header", L"InNick", 0, pwszFileName); + pNew->iHdrOutNick = GetPrivateProfileIntW(L"Header", L"OutNick", 0, pwszFileName); + pNew->iHdrInUID = GetPrivateProfileIntW(L"Header", L"InUID", 0, pwszFileName); + pNew->iHdrOutUID = GetPrivateProfileIntW(L"Header", L"OutUID", 0, pwszFileName); + } + + if (pNew->iUsePreMsg) { + pNew->preRN = GetPrivateProfileIntW(L"PreMessage", L"PreRN", -1, pwszFileName); + pNew->preSP = GetPrivateProfileIntW(L"PreMessage", L"PreSP", 0, pwszFileName); + pNew->afterRN = GetPrivateProfileIntW(L"PreMessage", L"AfterRN", -1, pwszFileName); + pNew->afterSP = GetPrivateProfileIntW(L"PreMessage", L"AfterSP", 0, pwszFileName); + } + + if (pNew->iUseFilename) { + if (!GetPrivateProfileStringW(L"FileName", L"Pattern", L"", buf, _countof(buf), pwszFileName)) + return; + if ((pNew->regFilename.pattern = pcre16_compile(buf, 0, &err, &erroffset, nullptr)) == nullptr) + return; + pNew->regFilename.extra = pcre16_study(pNew->regFilename.pattern, 0, &err); + + pNew->iInNick = GetPrivateProfileIntW(L"FileName", L"InNick", 0, pwszFileName); + pNew->iInUID = GetPrivateProfileIntW(L"FileName", L"InUID", 0, pwszFileName); + pNew->iOutNick = GetPrivateProfileIntW(L"FileName", L"OutNick", 0, pwszFileName); + pNew->iOutUID = GetPrivateProfileIntW(L"FileName", L"OutUID", 0, pwszFileName); + } + + m_patterns.insert(pNew.release()); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// pattern-based database driver + +class CDbxPattern : public MDatabaseReadonly, public MZeroedObject +{ + typedef MDatabaseReadonly CSuper; + + CMStringW m_buf, m_folder; + MCONTACT m_hCurrContact = INVALID_CONTACT_ID; + HANDLE m_hFile = INVALID_HANDLE_VALUE, m_hMap = 0; + const uint8_t *m_pFile = 0; + int m_iFileVersion = 0, m_iMsgHeaderSize = 0; + + std::vector m_events; + std::vector m_files; + + bool CheckContact(MCONTACT hContact) + { + if (hContact != m_hCurrContact) { + m_hCurrContact = hContact; + if (!Load(m_files[hContact - 1])) + return false; + } + return true; + } + + //////////////////////////////////////////////////////////////////////////////////////// + // QHF file format + + bool LoadBinaryFile(const uint8_t *pFile, uint32_t iSize) + { + if (memicmp(pFile, "QHF", 3)) { + AddMessage(LPGENW("Invalid file header")); + return false; + } + + m_iFileVersion = pFile[3]; + + uint32_t fsz = RLInteger(&pFile[4]); pFile += 0x2C; + uint32_t UIDLen = RLWord(pFile); pFile += 2; + char *UIDStr = (char*)_alloca(UIDLen + 2); + if (m_iFileVersion <= 2) + strncpy_s(UIDStr, UIDLen + 2, (char *)pFile, UIDLen); + else + strncpy_s(UIDStr, UIDLen + 2, (char *)pFile, UIDLen + 1); + pFile += UIDLen; + + uint32_t NickLen = RLWord(pFile); pFile += 2; + char *NickStr = (char*)_alloca(NickLen + 2); + if (m_iFileVersion <= 2) + strncpy_s(NickStr, NickLen + 2, (char*)pFile, NickLen); + else + strncpy_s(NickStr, NickLen + 2, (char*)pFile, NickLen + 1); + pFile += NickLen; + + DBCONTACTWRITESETTING dbcws = {}; + dbcws.szModule = "Pattern"; + dbcws.value.type = DBVT_UTF8; + + dbcws.szSetting = "ID"; + dbcws.value.pszVal = UIDStr; + WriteContactSetting(m_hCurrContact, &dbcws); + + dbcws.szSetting = "Nick"; + dbcws.value.pszVal = NickStr; + WriteContactSetting(m_hCurrContact, &dbcws); + + uint32_t iHeaderSize = 0x30 + NickLen + UIDLen; + if (fsz != iSize - iHeaderSize) + fsz = iSize - iHeaderSize; + + m_iMsgHeaderSize = (m_iFileVersion >= 3) ? 0x23 : 0x21; + for (uint32_t i = 0; i < fsz; i += m_iMsgHeaderSize) { + m_events.push_back(i + iHeaderSize); + i += RLWord(&pFile[i + m_iMsgHeaderSize - 2]); + } + + return true; + } + + //////////////////////////////////////////////////////////////////////////////////////// + // Text file format, parsed by regexps + + bool LoadTextFile(const uint8_t *pFile) + { + auto *pPattern = g_pBatch->m_pPattern; + + switch (pPattern->iCodePage) { + case CP_UTF8: + m_buf = mir_utf8decodeW((char*)pFile); + break; + case 1200: + m_buf = mir_wstrdup((wchar_t*)pFile); + break; + default: + m_buf = mir_a2u_cp((char*)pFile, pPattern->iCodePage); + break; + } + + + // smth went wrong or empty file + if (m_buf.IsEmpty()) + return false; + + int iOffset = 0; + if (m_buf[0] == 0xFEFF) + m_buf.Delete(0); + + if (pPattern->iUseHeader) { + int offsets[99]; + int nMatch = pcre16_exec(pPattern->regHeader.pattern, pPattern->regHeader.extra, m_buf, m_buf.GetLength(), iOffset, PCRE_NEWLINE_ANYCRLF, offsets, _countof(offsets)); + if (nMatch <= 0) { + AddMessage(LPGENW("Cannot parse file header, skipping file")); + return false; + } + + const wchar_t **substrings; + if (pcre16_get_substring_list(m_buf, offsets, nMatch, &substrings) >= 0) { + if (pPattern->iUseHeader & 1) { + pPattern->wszIncoming = substrings[pPattern->iHdrIncoming]; + pPattern->wszOutgoing = substrings[pPattern->iHdrOutgoing]; + } + + if (pPattern->iUseHeader & 2) { + DBCONTACTWRITESETTING dbcws = {}; + dbcws.szModule = "Pattern"; + dbcws.value.type = DBVT_WCHAR; + + if (pPattern->iInUID && substrings[pPattern->iHdrInUID]) { + dbcws.szSetting = "ID"; + dbcws.value.pwszVal = (wchar_t *)substrings[pPattern->iHdrInUID]; + WriteContactSetting(m_hCurrContact, &dbcws); + } + + if (pPattern->iInNick && substrings[pPattern->iHdrInNick]) { + dbcws.szSetting = "Nick"; + dbcws.value.pwszVal = (wchar_t *)substrings[pPattern->iHdrInNick]; + WriteContactSetting(m_hCurrContact, &dbcws); + } + } + } + + iOffset = offsets[1]; + } + + while (true) { + int offsets[99]; + int nMatch = pcre16_exec(pPattern->regMessage.pattern, pPattern->regMessage.extra, m_buf, m_buf.GetLength(), iOffset, PCRE_NEWLINE_ANYCRLF, offsets, _countof(offsets)); + if (nMatch <= 0) + break; + + m_events.push_back(offsets[0]); + iOffset = offsets[1]; + } + return true; + } + +public: + CDbxPattern() + {} + + ~CDbxPattern() + { + Close(); + } + + void Close() + { + if (m_pFile != nullptr) + ::UnmapViewOfFile(m_pFile); + + if (m_hMap != nullptr) + ::CloseHandle(m_hMap); + + if (m_hFile != INVALID_HANDLE_VALUE) + ::CloseHandle(m_hFile); + } + + bool Load(const wchar_t *pwszFileName) + { + m_buf.Empty(); + m_events.clear(); + Close(); + + AddMessage(LPGENW("Loading file '%s'..."), pwszFileName); + + m_hFile = ::CreateFileW(pwszFileName, GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, 0); + if (m_hFile == INVALID_HANDLE_VALUE) { + AddMessage(LPGENW("Failed to open file <%s> for import: %d"), pwszFileName, GetLastError()); + return false; + } + + uint32_t cbLen = ::GetFileSize(m_hFile, 0); + m_hMap = ::CreateFileMappingW(m_hFile, nullptr, PAGE_READONLY, 0, 0, L"ImportMapfile"); + if (m_hMap == nullptr) { + AddMessage(LPGENW("Failed to mmap file <%s> for import: %d"), pwszFileName, GetLastError()); + return false; + } + + m_pFile = (const uint8_t*)::MapViewOfFile(m_hMap, FILE_MAP_READ, 0, 0, 0); + if (m_pFile == nullptr) { + AddMessage(LPGENW("Failed to map view of file <%s> for import: %d"), pwszFileName, GetLastError()); + return false; + } + + if (g_pBatch->m_pPattern->iType == 1) // text file + return LoadTextFile(m_pFile); + return LoadBinaryFile(m_pFile, cbLen); + } + + int Open(const wchar_t *profile) + { + CMStringW wszBaseFolder(profile); + auto *pPattern = g_pBatch->m_pPattern; + + // create a mask for loading multiple data files for a folder + uint32_t dwAttr = GetFileAttributesW(profile); + if (dwAttr & FILE_ATTRIBUTE_DIRECTORY) { + wszBaseFolder = profile; + m_folder.AppendFormat(L"%s\\*.%s", profile, pPattern->wszExt.c_str()); + } + else { + int i = wszBaseFolder.ReverseFind('\\'); + if (i != -1) + wszBaseFolder = wszBaseFolder.Left(i); + m_folder = profile; + } + + int hContact = 1; + WIN32_FIND_DATA fd; + HANDLE hFind = FindFirstFile(m_folder, &fd); + if (hFind != INVALID_HANDLE_VALUE) { + do { + // find all subfolders except "." and ".." + if (!mir_wstrcmp(fd.cFileName, L".") || !mir_wstrcmp(fd.cFileName, L"..")) + continue; + + CMStringW wszFullName(wszBaseFolder + L"\\" + fd.cFileName); + m_files.push_back(wszFullName); + + auto *cc = m_cache->AddContactToCache(hContact); + cc->szProto = "Pattern"; + + // we try to restore user id from the file name + if (pPattern->iUseFilename) { + int offsets[100]; + int nMatch = pcre16_exec(pPattern->regFilename.pattern, pPattern->regFilename.extra, wszFullName, wszFullName.GetLength(), 0, 0, offsets, _countof(offsets)); + if (nMatch > 0) { + const wchar_t **substrings; + if (pcre16_get_substring_list(wszFullName, offsets, nMatch, &substrings) >= 0) { + DBCONTACTWRITESETTING dbcws = {}; + dbcws.szModule = cc->szProto; + dbcws.value.type = DBVT_WCHAR; + + if (pPattern->iInUID && substrings[pPattern->iInUID]) { + dbcws.szSetting = "ID"; + dbcws.value.pwszVal = (wchar_t*)substrings[pPattern->iInUID]; + WriteContactSetting(hContact, &dbcws); + } + + if (pPattern->iInNick && substrings[pPattern->iInNick]) { + dbcws.szSetting = "Nick"; + dbcws.value.pwszVal = (wchar_t*)substrings[pPattern->iInNick]; + WriteContactSetting(hContact, &dbcws); + } + + pcre16_free_substring_list(substrings); + } + } + } + hContact++; + } + while (FindNextFile(hFind, &fd)); + + FindClose(hFind); + } + + if (m_files.empty()) + return EGROKPRF_CANTREAD; + + return EGROKPRF_NOERROR; + } + + // patterns file always stores history for the single contact only + STDMETHODIMP_(int) GetBlobSize(MEVENT idx) override + { + if (m_events.size() == 0 || idx < 1 || idx > m_events.size()) + return 0; + + if (g_pBatch->m_pPattern->iType == 1) { + int iStart = m_events[idx-1], iEnd = (idx == m_events.size()) ? m_buf.GetLength() : m_events[idx]; + CMStringW msg = m_buf.Mid(iStart, iEnd - iStart); + return (LONG)mir_strlen(ptrA(mir_utf8encodeW(msg))) + 1; + } + + if (m_pFile == nullptr) + return 0; + + const uint8_t *pMsg = m_pFile + m_events[idx-1]; + return RLWord(&pMsg[m_iMsgHeaderSize - 2]) + 1; + } + + STDMETHODIMP_(int) GetContactCount(void) override + { + return (int)m_files.size(); + } + + STDMETHODIMP_(MCONTACT) FindFirstContact(const char *szProto) override + { + MCONTACT ret = CSuper::FindFirstContact(szProto); + if (ret != 0) + if (!CheckContact(ret)) + return 0; + return ret; + } + + STDMETHODIMP_(MCONTACT) FindNextContact(MCONTACT contactID, const char *szProto) override + { + MCONTACT ret = CSuper::FindNextContact(contactID, szProto); + if (ret != 0) + if (!CheckContact(ret)) + return 0; + return ret; + } + + STDMETHODIMP_(int) GetEventCount(MCONTACT) override + { + return (int)m_events.size(); + } + + STDMETHODIMP_(BOOL) GetContactSettingWorker(MCONTACT hContact, LPCSTR szModule, LPCSTR szSetting, DBVARIANT* dbv, int isStatic) + { + if (szSetting == nullptr || szModule == nullptr) + return 1; + + DBCachedContact *cc = nullptr; + if (hContact) { + cc = m_cache->GetCachedContact(hContact); + if (cc == nullptr) + return 1; + } + + size_t settingNameLen = strlen(szSetting); + size_t moduleNameLen = strlen(szModule); + char* szCachedSettingName = m_cache->GetCachedSetting(szModule, szSetting, moduleNameLen, settingNameLen); + + DBVARIANT *pCachedValue = m_cache->GetCachedValuePtr(hContact, szCachedSettingName, 0); + if (pCachedValue != nullptr) { + if (pCachedValue->type == DBVT_ASCIIZ || 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)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(strlen(pCachedValue->pszVal) + 1); + strcpy(dbv->pszVal, pCachedValue->pszVal); + } + } + else memcpy(dbv, pCachedValue, sizeof(DBVARIANT)); + + return (pCachedValue->type == DBVT_DELETED) ? 1 : 0; + } + + return 1; + } + + STDMETHODIMP_(BOOL) 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 dbcwWork = *dbcws; + if (dbcwWork.value.type == DBVT_WCHAR) { + T2Utf value(dbcwWork.value.pwszVal); + dbcwWork.value.pszVal = NEWSTR_ALLOCA(value); + dbcwWork.value.type = DBVT_UTF8; + dbcwWork.value.cchVal = (uint16_t)strlen(dbcwWork.value.pszVal); + } + + char* cachedSettingName = m_cache->GetCachedSetting(dbcwWork.szModule, dbcwWork.szSetting, mir_strlen(dbcwWork.szModule), mir_strlen(dbcwWork.szSetting)); + DBVARIANT* cachedValue = m_cache->GetCachedValuePtr(hContact, cachedSettingName, 1); + if (cachedValue != nullptr) + m_cache->SetCachedVariant(&dbcwWork.value, cachedValue); + + return 0; + } + + //////////////////////////////////////////////////////////////////////////////////////// + + static int str2int(const wchar_t* str) + { + if (str == nullptr || *str == 0) + return 0; + + return _wtoi(str); + } + + int getBinaryEvent(MEVENT idx, DBEVENTINFO *dbei) + { + if (m_pFile == nullptr) + return 1; + + const uint8_t *pMsg = m_pFile + m_events[idx-1]; + + dbei->eventType = EVENTTYPE_MESSAGE; + dbei->flags = DBEF_READ | DBEF_UTF; + if (pMsg[0x1A] != 0) + dbei->flags |= DBEF_SENT; + dbei->timestamp = RLInteger(&pMsg[0x12]); + dbei->timestamp -= TimeZone_ToLocal(dbei->timestamp) - dbei->timestamp; // deduct time zone offset from timestamp + dbei->cbBlob = RLWord(&pMsg[m_iMsgHeaderSize - 2]); + dbei->pBlob = (uint8_t*)mir_alloc(dbei->cbBlob + 1); + memcpy(dbei->pBlob, pMsg + m_iMsgHeaderSize, dbei->cbBlob); + if (m_iFileVersion != 1) + for (int i = 0; i < dbei->cbBlob; i++) { + dbei->pBlob[i] += i+1; + dbei->pBlob[i] = 255 - dbei->pBlob[i]; + } + + dbei->pBlob[dbei->cbBlob] = 0; + return 0; + } + + int getTextEvent(MEVENT idx, DBEVENTINFO *dbei) + { + auto *pPattern = g_pBatch->m_pPattern; + + int offsets[99]; + int nMatch = pcre16_exec(pPattern->regMessage.pattern, pPattern->regMessage.extra, m_buf, m_buf.GetLength(), m_events[idx-1], PCRE_NEWLINE_ANYCRLF, offsets, _countof(offsets)); + if (nMatch <= 0) + return 1; + + dbei->eventType = EVENTTYPE_MESSAGE; + dbei->flags = DBEF_READ | DBEF_UTF; + + int h1 = offsets[1], h2 = (idx == m_events.size()) ? m_buf.GetLength() : m_events[idx]; + int prn = -1, arn = -1; + if (pPattern->iUsePreMsg) + prn = pPattern->preRN, arn = pPattern->afterRN; + + if (prn != 0) { + int i = 0; + while (m_buf[h1] == '\r' && m_buf[h1 + 1] == '\n' && i < prn) + h1 += 2, i++; + } + + if (arn != 0) { + int i = 0; + while (m_buf[h2 - 2] == '\r' && m_buf[h2 - 1] == '\n' && i < arn) + h2 -= 2, i++; + } + + if (dbei->cbBlob) { + CMStringW wszBody = m_buf.Mid(h1, h2 - h1).Trim(); + if (!wszBody.IsEmpty()) { + ptrA tmp(mir_utf8encodeW(wszBody)); + int copySize = min(dbei->cbBlob - 1, (int)mir_strlen(tmp)); + memcpy(dbei->pBlob, tmp, copySize); + dbei->pBlob[copySize] = 0; + dbei->cbBlob = copySize; + } + else dbei->cbBlob = 0; + } + + const wchar_t **substrings; + if (pcre16_get_substring_list(m_buf, offsets, nMatch, &substrings) >= 0) { + struct tm st = {}; + st.tm_year = str2int(substrings[pPattern->iYear]); + if (st.tm_year > 1900) + st.tm_year -= 1900; + st.tm_mon = str2int(substrings[pPattern->iMonth]) - 1; + st.tm_mday = str2int(substrings[pPattern->iDay]); + st.tm_hour = str2int(substrings[pPattern->iHours]); + st.tm_min = str2int(substrings[pPattern->iMinutes]); + st.tm_sec = (pPattern->iSeconds) ? str2int(substrings[pPattern->iSeconds]) : 0; + dbei->timestamp = mktime(&st); + + if (pPattern->iDirection) + if (pPattern->wszOutgoing == substrings[pPattern->iDirection]) + dbei->flags |= DBEF_SENT; + + + pcre16_free_substring_list(substrings); + } + return 0; + } + + STDMETHODIMP_(BOOL) GetEvent(MEVENT idx, DBEVENTINFO *dbei) override + { + if (dbei == nullptr || m_events.size() == 0 || idx < 1 || idx > m_events.size()) + return 1; + + if (g_pBatch->m_pPattern->iType == 1) + return getTextEvent(idx, dbei); + + return getBinaryEvent(idx, dbei); + } + + STDMETHODIMP_(MEVENT) FindFirstEvent(MCONTACT hContact) override + { + // no system history + if (hContact == 0) + return 0; + + if (!CheckContact(hContact)) + return 0; + + return m_events.size() > 0 ? 1 : 0; + } + + STDMETHODIMP_(MEVENT) FindNextEvent(MCONTACT, MEVENT idx) override + { + if (idx >= m_events.size()) + return 0; + + return idx + 1; + } + + STDMETHODIMP_(MEVENT) FindLastEvent(MCONTACT hContact) override + { + // no system history + if (hContact == 0) + return 0; + + if (!CheckContact(hContact)) + return 0; + + return m_events.size() > 0 ? (MEVENT)m_events.size() : 0; + } + + STDMETHODIMP_(MEVENT) FindPrevEvent(MCONTACT, MEVENT idx) override + { + return (idx >= 1) ? idx-1 : 0; + } + + STDMETHODIMP_(DATABASELINK *) GetDriver(); +}; + +///////////////////////////////////////////////////////////////////////////////////////// +// database link functions + +static int pattern_makeDatabase(const wchar_t*) +{ + return 1; +} + +static int pattern_grokHeader(const wchar_t *profile) +{ + return CDbxPattern().Open(profile); +} + +static MDatabaseCommon* pattern_load(const wchar_t *profile, BOOL) +{ + std::unique_ptr db(new CDbxPattern()); + if (db->Open(profile)) + return nullptr; + + return db.release(); +} + +DATABASELINK g_patternDbLink = +{ + 0, + "pattern", + L"Pattern-based file driver", + pattern_makeDatabase, + pattern_grokHeader, + pattern_load +}; + +STDMETHODIMP_(DATABASELINK *) CDbxPattern::GetDriver() +{ + return &g_patternDbLink; +} diff --git a/plugins/Import/src/progress.cpp b/plugins/Import/src/progress.cpp index b602d0a655..f9ca110438 100644 --- a/plugins/Import/src/progress.cpp +++ b/plugins/Import/src/progress.cpp @@ -2,7 +2,7 @@ Import plugin for Miranda NG -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/plugins/Import/src/stdafx.cxx b/plugins/Import/src/stdafx.cxx index f64d25234b..ebbde0ade1 100644 --- a/plugins/Import/src/stdafx.cxx +++ b/plugins/Import/src/stdafx.cxx @@ -1,5 +1,5 @@ /* -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/plugins/Import/src/stdafx.h b/plugins/Import/src/stdafx.h index dccb07afc5..b60d8402a5 100644 --- a/plugins/Import/src/stdafx.h +++ b/plugins/Import/src/stdafx.h @@ -2,7 +2,7 @@ Import plugin for Miranda NG -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/plugins/Import/src/textjson.cpp b/plugins/Import/src/textjson.cpp index 22cab70e2b..d419807ac0 100644 --- a/plugins/Import/src/textjson.cpp +++ b/plugins/Import/src/textjson.cpp @@ -1,269 +1,269 @@ -/* - -Import plugin for Miranda NG - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) - -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" - -#include - -static int mc_makeDatabase(const wchar_t*) -{ - return 1; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// JSON text driver, read-only - -static int CompareModules(const char *p1, const char *p2) -{ - return mir_strcmp(p1, p2); -} - -class CDbxJson : public MDatabaseReadonly, public MZeroedObject -{ - JSONNode *m_root = nullptr; - LIST m_events; - LIST m_modules; - -public: - CDbxJson() : - m_events(100), - m_modules(10, CompareModules) - {} - - ~CDbxJson() - { - if (m_root != nullptr) - json_delete(m_root); - - for (auto &it : m_modules) - mir_free(it); - } - - void Load() - { - // json operates with the only contact with pseudo id=1 - m_cache->AddContactToCache(1); - } - - int Open(const wchar_t *profile) - { - HANDLE hFile = CreateFile(profile, GENERIC_READ, 0, 0, OPEN_ALWAYS, 0, 0); - if (hFile == INVALID_HANDLE_VALUE) - return EGROKPRF_CANTREAD; - - DWORD dwSize = GetFileSize(hFile, nullptr), dwRead; - ptrA szFile((char*)mir_alloc(dwSize + 1)); - BOOL r = ReadFile(hFile, szFile, dwSize, &dwRead, nullptr); - CloseHandle(hFile); - if (!r) - return EGROKPRF_CANTREAD; - - szFile[dwSize] = 0; - if ((m_root = json_parse(szFile)) == nullptr) - return EGROKPRF_DAMAGED; - - for (auto &it : m_root->at("history")) - m_events.insert(&it); - - return EGROKPRF_NOERROR; - } - - // mcontacts format always store history for one contact only - STDMETHODIMP_(int) GetContactCount(void) override - { - return 1; - } - - STDMETHODIMP_(int) GetEventCount(MCONTACT) override - { - return m_events.getCount(); - } - - STDMETHODIMP_(BOOL) GetEvent(MEVENT iEvent, DBEVENTINFO *dbei) override - { - JSONNode *node = m_events[iEvent - 1]; - if (node == nullptr) - return 0; - - dbei->eventType = (*node)["type"].as_int(); - - dbei->timestamp = 0; - std::string szTime = (*node)["time"].as_string(); - if (!szTime.empty()) { - char c; - struct tm st = {}; - int res = sscanf(szTime.c_str(), "%4d%c%2d%c%2d %2d:%2d:%2d", &st.tm_year, &c, &st.tm_mon, &c, &st.tm_mday, &st.tm_hour, &st.tm_min, &st.tm_sec); - if (res == 8) { - st.tm_mon--; - st.tm_year -= 1900; - time_t tm = mktime(&st); - if (tm != -1) - dbei->timestamp = tm; - } - } - else { - szTime = (*node)["isotime"].as_string(); - if (!szTime.empty()) { - struct tm st = {}; - int res = sscanf(szTime.c_str(), "%4d-%2d-%2dT%2d:%2d:%2dZ", &st.tm_year, &st.tm_mon, &st.tm_mday, &st.tm_hour, &st.tm_min, &st.tm_sec); - if (res == 6) { - st.tm_mon--; - st.tm_year -= 1900; - time_t tm = _mkgmtime(&st); - if (tm != -1) - dbei->timestamp = tm; - } - } - } - - if (dbei->timestamp == 0) - dbei->timestamp = (*node)["timeStamp"].as_int(); - - dbei->flags = 0; - std::string szFlags = (*node)["flags"].as_string(); - for (auto &c : szFlags) - switch (c) { - case 'm': dbei->flags |= DBEF_SENT; break; - case 'r': dbei->flags |= DBEF_READ; break; - } - - std::string szModule = (*node)["module"].as_string(); - if (!szModule.empty()) { - dbei->szModule = m_modules.find((char*)szModule.c_str()); - if (dbei->szModule == nullptr) { - dbei->szModule = mir_strdup(szModule.c_str()); - m_modules.insert((char*)dbei->szModule); - } - } - - if (dbei->eventType == EVENTTYPE_FILE) { - std::string szFile = (*node)["file"].as_string(); - std::string szDescr = (*node)["descr"].as_string(); - - dbei->flags |= DBEF_UTF; - MBinBuffer buf; - uint32_t tmp = 0; - buf.append(&tmp, sizeof(tmp)); - buf.append(szFile.c_str(), szFile.size()); - if (!szDescr.empty()) { - buf.append(&tmp, 1); - buf.append(szDescr.c_str(), szDescr.size()); - } - buf.append(&tmp, 1); - - dbei->cbBlob = (int)buf.length(); - dbei->pBlob = (uint8_t*)mir_alloc(dbei->cbBlob); - memcpy(dbei->pBlob, buf.data(), buf.length()); - } - else { - std::string szBody = (*node)["body"].as_string(); - if (!szBody.empty()) { - int offset; - switch (dbei->eventType) { - case EVENTTYPE_ADDED: - case EVENTTYPE_FILE: - offset = sizeof(uint32_t); - break; - - case EVENTTYPE_AUTHREQUEST: - offset = sizeof(uint32_t) * 2; - break; - - default: - offset = 0; - } - - dbei->flags |= DBEF_UTF; - dbei->cbBlob = (uint32_t)szBody.size() + offset; - dbei->pBlob = (uint8_t*)mir_calloc(dbei->cbBlob + 1); - memcpy(dbei->pBlob + offset, szBody.c_str(), szBody.size()); - dbei->pBlob[dbei->cbBlob] = 0; - } - } - - return 0; - } - - STDMETHODIMP_(MEVENT) FindFirstEvent(MCONTACT) override - { - return 1; - } - - STDMETHODIMP_(MEVENT) FindNextEvent(MCONTACT, MEVENT iEvent) override - { - if ((int)iEvent >= m_events.getCount()) - return 0; - - return iEvent+1; - } - - STDMETHODIMP_(MEVENT) FindLastEvent(MCONTACT) override - { - int numEvents = m_events.getCount(); - return numEvents ? numEvents-1 : 0; - } - - STDMETHODIMP_(MEVENT) FindPrevEvent(MCONTACT, MEVENT iEvent) override - { - if (iEvent <= 1) - return 0; - - return iEvent-1; - } - - STDMETHODIMP_(DATABASELINK *) GetDriver(); -}; - -static int mc_grokHeader(const wchar_t *profile) -{ - return CDbxJson().Open(profile); -} - -static MDatabaseCommon* mc_load(const wchar_t *profile, BOOL) -{ - std::unique_ptr db(new CDbxJson()); - if (db->Open(profile)) - return nullptr; - - db->Load(); - return db.release(); -} - -static DATABASELINK dblink = -{ - 0, - "mcontacts", - L"mContacts file driver", - mc_makeDatabase, - mc_grokHeader, - mc_load -}; - -STDMETHODIMP_(DATABASELINK *) CDbxJson::GetDriver() -{ - return &g_patternDbLink; -} - -void RegisterJson() -{ - RegisterDatabasePlugin(&dblink); -} +/* + +Import plugin for Miranda NG + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) + +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" + +#include + +static int mc_makeDatabase(const wchar_t*) +{ + return 1; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// JSON text driver, read-only + +static int CompareModules(const char *p1, const char *p2) +{ + return mir_strcmp(p1, p2); +} + +class CDbxJson : public MDatabaseReadonly, public MZeroedObject +{ + JSONNode *m_root = nullptr; + LIST m_events; + LIST m_modules; + +public: + CDbxJson() : + m_events(100), + m_modules(10, CompareModules) + {} + + ~CDbxJson() + { + if (m_root != nullptr) + json_delete(m_root); + + for (auto &it : m_modules) + mir_free(it); + } + + void Load() + { + // json operates with the only contact with pseudo id=1 + m_cache->AddContactToCache(1); + } + + int Open(const wchar_t *profile) + { + HANDLE hFile = CreateFile(profile, GENERIC_READ, 0, 0, OPEN_ALWAYS, 0, 0); + if (hFile == INVALID_HANDLE_VALUE) + return EGROKPRF_CANTREAD; + + DWORD dwSize = GetFileSize(hFile, nullptr), dwRead; + ptrA szFile((char*)mir_alloc(dwSize + 1)); + BOOL r = ReadFile(hFile, szFile, dwSize, &dwRead, nullptr); + CloseHandle(hFile); + if (!r) + return EGROKPRF_CANTREAD; + + szFile[dwSize] = 0; + if ((m_root = json_parse(szFile)) == nullptr) + return EGROKPRF_DAMAGED; + + for (auto &it : m_root->at("history")) + m_events.insert(&it); + + return EGROKPRF_NOERROR; + } + + // mcontacts format always store history for one contact only + STDMETHODIMP_(int) GetContactCount(void) override + { + return 1; + } + + STDMETHODIMP_(int) GetEventCount(MCONTACT) override + { + return m_events.getCount(); + } + + STDMETHODIMP_(BOOL) GetEvent(MEVENT iEvent, DBEVENTINFO *dbei) override + { + JSONNode *node = m_events[iEvent - 1]; + if (node == nullptr) + return 0; + + dbei->eventType = (*node)["type"].as_int(); + + dbei->timestamp = 0; + std::string szTime = (*node)["time"].as_string(); + if (!szTime.empty()) { + char c; + struct tm st = {}; + int res = sscanf(szTime.c_str(), "%4d%c%2d%c%2d %2d:%2d:%2d", &st.tm_year, &c, &st.tm_mon, &c, &st.tm_mday, &st.tm_hour, &st.tm_min, &st.tm_sec); + if (res == 8) { + st.tm_mon--; + st.tm_year -= 1900; + time_t tm = mktime(&st); + if (tm != -1) + dbei->timestamp = tm; + } + } + else { + szTime = (*node)["isotime"].as_string(); + if (!szTime.empty()) { + struct tm st = {}; + int res = sscanf(szTime.c_str(), "%4d-%2d-%2dT%2d:%2d:%2dZ", &st.tm_year, &st.tm_mon, &st.tm_mday, &st.tm_hour, &st.tm_min, &st.tm_sec); + if (res == 6) { + st.tm_mon--; + st.tm_year -= 1900; + time_t tm = _mkgmtime(&st); + if (tm != -1) + dbei->timestamp = tm; + } + } + } + + if (dbei->timestamp == 0) + dbei->timestamp = (*node)["timeStamp"].as_int(); + + dbei->flags = 0; + std::string szFlags = (*node)["flags"].as_string(); + for (auto &c : szFlags) + switch (c) { + case 'm': dbei->flags |= DBEF_SENT; break; + case 'r': dbei->flags |= DBEF_READ; break; + } + + std::string szModule = (*node)["module"].as_string(); + if (!szModule.empty()) { + dbei->szModule = m_modules.find((char*)szModule.c_str()); + if (dbei->szModule == nullptr) { + dbei->szModule = mir_strdup(szModule.c_str()); + m_modules.insert((char*)dbei->szModule); + } + } + + if (dbei->eventType == EVENTTYPE_FILE) { + std::string szFile = (*node)["file"].as_string(); + std::string szDescr = (*node)["descr"].as_string(); + + dbei->flags |= DBEF_UTF; + MBinBuffer buf; + uint32_t tmp = 0; + buf.append(&tmp, sizeof(tmp)); + buf.append(szFile.c_str(), szFile.size()); + if (!szDescr.empty()) { + buf.append(&tmp, 1); + buf.append(szDescr.c_str(), szDescr.size()); + } + buf.append(&tmp, 1); + + dbei->cbBlob = (int)buf.length(); + dbei->pBlob = (uint8_t*)mir_alloc(dbei->cbBlob); + memcpy(dbei->pBlob, buf.data(), buf.length()); + } + else { + std::string szBody = (*node)["body"].as_string(); + if (!szBody.empty()) { + int offset; + switch (dbei->eventType) { + case EVENTTYPE_ADDED: + case EVENTTYPE_FILE: + offset = sizeof(uint32_t); + break; + + case EVENTTYPE_AUTHREQUEST: + offset = sizeof(uint32_t) * 2; + break; + + default: + offset = 0; + } + + dbei->flags |= DBEF_UTF; + dbei->cbBlob = (uint32_t)szBody.size() + offset; + dbei->pBlob = (uint8_t*)mir_calloc(dbei->cbBlob + 1); + memcpy(dbei->pBlob + offset, szBody.c_str(), szBody.size()); + dbei->pBlob[dbei->cbBlob] = 0; + } + } + + return 0; + } + + STDMETHODIMP_(MEVENT) FindFirstEvent(MCONTACT) override + { + return 1; + } + + STDMETHODIMP_(MEVENT) FindNextEvent(MCONTACT, MEVENT iEvent) override + { + if ((int)iEvent >= m_events.getCount()) + return 0; + + return iEvent+1; + } + + STDMETHODIMP_(MEVENT) FindLastEvent(MCONTACT) override + { + int numEvents = m_events.getCount(); + return numEvents ? numEvents-1 : 0; + } + + STDMETHODIMP_(MEVENT) FindPrevEvent(MCONTACT, MEVENT iEvent) override + { + if (iEvent <= 1) + return 0; + + return iEvent-1; + } + + STDMETHODIMP_(DATABASELINK *) GetDriver(); +}; + +static int mc_grokHeader(const wchar_t *profile) +{ + return CDbxJson().Open(profile); +} + +static MDatabaseCommon* mc_load(const wchar_t *profile, BOOL) +{ + std::unique_ptr db(new CDbxJson()); + if (db->Open(profile)) + return nullptr; + + db->Load(); + return db.release(); +} + +static DATABASELINK dblink = +{ + 0, + "mcontacts", + L"mContacts file driver", + mc_makeDatabase, + mc_grokHeader, + mc_load +}; + +STDMETHODIMP_(DATABASELINK *) CDbxJson::GetDriver() +{ + return &g_patternDbLink; +} + +void RegisterJson() +{ + RegisterDatabasePlugin(&dblink); +} diff --git a/plugins/Import/src/ui.cpp b/plugins/Import/src/ui.cpp index 12a84455c7..0a5d6cf4e1 100644 --- a/plugins/Import/src/ui.cpp +++ b/plugins/Import/src/ui.cpp @@ -1,130 +1,130 @@ -/* - -Import plugin for Miranda NG - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) - -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" - -class CContactImportDlg : public CDlgBase -{ - friend INT_PTR ImportContact(WPARAM hContact, LPARAM); - - MCONTACT m_hContact; - int m_flags = 0; - CImportPattern *m_pPattern = 0; - wchar_t m_wszFileName[MAX_PATH]; - - CCtrlButton m_btnOpenFile; - CCtrlCombo m_cmbFileType; - CCtrlEdit edtFileName; - -public: - CContactImportDlg(MCONTACT hContact) : - CDlgBase(g_plugin, IDD_IMPORT_CONTACT), - m_hContact(hContact), - edtFileName(this, IDC_FILENAME), - m_cmbFileType(this, IDC_FILETYPE), - m_btnOpenFile(this, IDC_OPEN_FILE) - { - m_wszFileName[0] = 0; - - m_btnOpenFile.OnClick = Callback(this, &CContactImportDlg::onClick_OpenFile); - } - - bool OnInitDialog() override - { - CMStringW wszTitle(FORMAT, TranslateT("Import history for %s"), Clist_GetContactDisplayName(m_hContact)); - SetWindowTextW(m_hwnd, wszTitle); - - m_cmbFileType.AddString(TranslateT("Miranda NG database/mContacts"), -1); - m_cmbFileType.AddString(TranslateT("JSON file"), -2); - - int iType = 1; - for (auto &it : g_plugin.m_patterns) - m_cmbFileType.AddString(it->wszName, iType++); - - return true; - } - - bool OnApply() override - { - edtFileName.GetText(m_wszFileName, _countof(m_wszFileName)); - if (m_wszFileName[0] == 0) - return false; - - if (IsDlgButtonChecked(m_hwnd, IDC_CHECK_DUPS)) - m_flags = IOPT_CHECKDUPS; - return true; - } - - void onClick_OpenFile(CCtrlButton*) - { - int iCur = m_cmbFileType.GetCurSel(); - if (iCur == -1) - return; - - CMStringW text, cmbText(ptrW(m_cmbFileType.GetText())); - switch(int idx = m_cmbFileType.GetItemData(iCur)) { - case -1: - text.AppendFormat(L"%s (*.dat,*.bak)%c*.dat;*.bak%c", cmbText.c_str(), 0, 0); - m_pPattern = nullptr; - break; - - case -2: - text.AppendFormat(L"%s (*.json)%c*.json%c", cmbText.c_str(), 0, 0); - m_pPattern = nullptr; - break; - - default: - auto &p = g_plugin.m_patterns[idx-1]; - text.AppendFormat(L"%s (*.%s)%c*.%s%c", cmbText.c_str(), p.wszExt.c_str(), 0, p.wszExt.c_str(), 0); - m_pPattern = &p; - break; - } - text.AppendFormat(L"%s (*.*)%c*.*%c%c", TranslateT("All Files"), 0, 0, 0); - - OPENFILENAME ofn = { 0 }; - ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; - ofn.lpstrFilter = text; - ofn.lpstrDefExt = L"dat"; - ofn.Flags = OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_NOCHANGEDIR | OFN_DONTADDTORECENT; - ofn.lpstrFile = m_wszFileName; - ofn.nMaxFile = _countof(m_wszFileName); - if (!GetOpenFileNameW(&ofn)) { - m_wszFileName[0] = 0; - m_pPattern = nullptr; - } - else edtFileName.SetText(m_wszFileName); - } -}; - -INT_PTR ImportContact(WPARAM hContact, LPARAM) -{ - CContactImportDlg dlg(hContact); - if (!dlg.DoModal()) - return 0; - - g_pBatch = new CImportBatch(); - wcsncpy_s(g_pBatch->m_wszFileName, dlg.m_wszFileName, _TRUNCATE); - g_pBatch->m_pPattern = dlg.m_pPattern; - g_pBatch->m_hContact = hContact; - g_pBatch->m_iOptions = IOPT_HISTORY + dlg.m_flags; - return RunWizard(new CProgressPageDlg(), true); -} +/* + +Import plugin for Miranda NG + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) + +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" + +class CContactImportDlg : public CDlgBase +{ + friend INT_PTR ImportContact(WPARAM hContact, LPARAM); + + MCONTACT m_hContact; + int m_flags = 0; + CImportPattern *m_pPattern = 0; + wchar_t m_wszFileName[MAX_PATH]; + + CCtrlButton m_btnOpenFile; + CCtrlCombo m_cmbFileType; + CCtrlEdit edtFileName; + +public: + CContactImportDlg(MCONTACT hContact) : + CDlgBase(g_plugin, IDD_IMPORT_CONTACT), + m_hContact(hContact), + edtFileName(this, IDC_FILENAME), + m_cmbFileType(this, IDC_FILETYPE), + m_btnOpenFile(this, IDC_OPEN_FILE) + { + m_wszFileName[0] = 0; + + m_btnOpenFile.OnClick = Callback(this, &CContactImportDlg::onClick_OpenFile); + } + + bool OnInitDialog() override + { + CMStringW wszTitle(FORMAT, TranslateT("Import history for %s"), Clist_GetContactDisplayName(m_hContact)); + SetWindowTextW(m_hwnd, wszTitle); + + m_cmbFileType.AddString(TranslateT("Miranda NG database/mContacts"), -1); + m_cmbFileType.AddString(TranslateT("JSON file"), -2); + + int iType = 1; + for (auto &it : g_plugin.m_patterns) + m_cmbFileType.AddString(it->wszName, iType++); + + return true; + } + + bool OnApply() override + { + edtFileName.GetText(m_wszFileName, _countof(m_wszFileName)); + if (m_wszFileName[0] == 0) + return false; + + if (IsDlgButtonChecked(m_hwnd, IDC_CHECK_DUPS)) + m_flags = IOPT_CHECKDUPS; + return true; + } + + void onClick_OpenFile(CCtrlButton*) + { + int iCur = m_cmbFileType.GetCurSel(); + if (iCur == -1) + return; + + CMStringW text, cmbText(ptrW(m_cmbFileType.GetText())); + switch(int idx = m_cmbFileType.GetItemData(iCur)) { + case -1: + text.AppendFormat(L"%s (*.dat,*.bak)%c*.dat;*.bak%c", cmbText.c_str(), 0, 0); + m_pPattern = nullptr; + break; + + case -2: + text.AppendFormat(L"%s (*.json)%c*.json%c", cmbText.c_str(), 0, 0); + m_pPattern = nullptr; + break; + + default: + auto &p = g_plugin.m_patterns[idx-1]; + text.AppendFormat(L"%s (*.%s)%c*.%s%c", cmbText.c_str(), p.wszExt.c_str(), 0, p.wszExt.c_str(), 0); + m_pPattern = &p; + break; + } + text.AppendFormat(L"%s (*.*)%c*.*%c%c", TranslateT("All Files"), 0, 0, 0); + + OPENFILENAME ofn = { 0 }; + ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; + ofn.lpstrFilter = text; + ofn.lpstrDefExt = L"dat"; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_NOCHANGEDIR | OFN_DONTADDTORECENT; + ofn.lpstrFile = m_wszFileName; + ofn.nMaxFile = _countof(m_wszFileName); + if (!GetOpenFileNameW(&ofn)) { + m_wszFileName[0] = 0; + m_pPattern = nullptr; + } + else edtFileName.SetText(m_wszFileName); + } +}; + +INT_PTR ImportContact(WPARAM hContact, LPARAM) +{ + CContactImportDlg dlg(hContact); + if (!dlg.DoModal()) + return 0; + + g_pBatch = new CImportBatch(); + wcsncpy_s(g_pBatch->m_wszFileName, dlg.m_wszFileName, _TRUNCATE); + g_pBatch->m_pPattern = dlg.m_pPattern; + g_pBatch->m_hContact = hContact; + g_pBatch->m_iOptions = IOPT_HISTORY + dlg.m_flags; + return RunWizard(new CProgressPageDlg(), true); +} diff --git a/plugins/Import/src/utils.cpp b/plugins/Import/src/utils.cpp index 3c83bf11a9..d869ae2737 100644 --- a/plugins/Import/src/utils.cpp +++ b/plugins/Import/src/utils.cpp @@ -2,7 +2,7 @@ Import plugin for Miranda NG -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/plugins/Import/src/version.h b/plugins/Import/src/version.h index d34c120f7d..f76dfe14a3 100644 --- a/plugins/Import/src/version.h +++ b/plugins/Import/src/version.h @@ -10,4 +10,4 @@ #define __DESCRIPTION "Imports contacts and messages from another Miranda profile or from an external program." #define __AUTHOR "Miranda team" #define __AUTHORWEB "https://miranda-ng.org/p/Import" -#define __COPYRIGHT "© 2012-22 George Hazan" +#define __COPYRIGHT "© 2012-23 George Hazan" diff --git a/plugins/Import/src/wizard.cpp b/plugins/Import/src/wizard.cpp index aab7e802a7..dde120289e 100644 --- a/plugins/Import/src/wizard.cpp +++ b/plugins/Import/src/wizard.cpp @@ -2,7 +2,7 @@ Import plugin for Miranda NG -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License -- cgit v1.2.3