summaryrefslogtreecommitdiff
path: root/plugins/Import
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Import')
-rw-r--r--plugins/Import/src/dbrw/dbcontacts.cpp136
-rw-r--r--plugins/Import/src/dbrw/dbevents.cpp390
-rw-r--r--plugins/Import/src/dbrw/dbintf.cpp174
-rw-r--r--plugins/Import/src/dbrw/dbintf.h318
-rw-r--r--plugins/Import/src/dbrw/dbrw.cpp210
-rw-r--r--plugins/Import/src/dbrw/dbrw.h60
-rw-r--r--plugins/Import/src/dbrw/dbsettings.cpp342
-rw-r--r--plugins/Import/src/dbrw/dbsql.cpp324
-rw-r--r--plugins/Import/src/import.cpp2
-rw-r--r--plugins/Import/src/main.cpp2
-rw-r--r--plugins/Import/src/mcontacts.cpp644
-rw-r--r--plugins/Import/src/miranda.cpp2
-rw-r--r--plugins/Import/src/patterns.cpp1464
-rw-r--r--plugins/Import/src/progress.cpp2
-rw-r--r--plugins/Import/src/stdafx.cxx2
-rw-r--r--plugins/Import/src/stdafx.h2
-rw-r--r--plugins/Import/src/textjson.cpp538
-rw-r--r--plugins/Import/src/ui.cpp260
-rw-r--r--plugins/Import/src/utils.cpp2
-rw-r--r--plugins/Import/src/version.h2
-rw-r--r--plugins/Import/src/wizard.cpp2
21 files changed, 2439 insertions, 2439 deletions
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 <sqlite3.h>
-
-#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 <sqlite3.h>
+
+#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 <memory>
-#include <vector>
-
-#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<uint32_t> m_events;
- std::vector<uint32_t>::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<CDbxMc> 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 <memory>
+#include <vector>
+
+#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<uint32_t> m_events;
+ std::vector<uint32_t>::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<CDbxMc> 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 <memory>
-#include <vector>
-
-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<CImportPattern> 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<uint32_t> m_events;
- std::vector<CMStringW> 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<CDbxPattern> 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 <memory>
+#include <vector>
+
+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<CImportPattern> 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<uint32_t> m_events;
+ std::vector<CMStringW> 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<CDbxPattern> 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 <m_json.h>
-
-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<JSONNode> m_events;
- LIST<char> 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<CDbxJson> 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 <m_json.h>
+
+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<JSONNode> m_events;
+ LIST<char> 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<CDbxJson> 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