summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2024-03-06 20:13:00 +0300
committerGeorge Hazan <george.hazan@gmail.com>2024-03-06 20:13:00 +0300
commite787977a76ef3579d0fdd690530aa5c5ee231aff (patch)
tree78ab53b34b712c6a2e7393881254466d07b07a53
parent63ccf9482d4328cbbcf597c137954211f7bd24c2 (diff)
fixes #4273 (Msg_Export to share JSON export format from Import plugin)
-rw-r--r--plugins/Import/src/stdafx.h2
-rw-r--r--plugins/Import/src/textjson.cpp73
-rw-r--r--plugins/Msg_Export/res/resource.rc2
-rw-r--r--plugins/Msg_Export/src/FileViewer.cpp18
-rw-r--r--plugins/Msg_Export/src/FileViewer.h2
-rw-r--r--plugins/Msg_Export/src/main.cpp122
-rw-r--r--plugins/Msg_Export/src/options.cpp70
-rw-r--r--plugins/Msg_Export/src/resource.h2
-rw-r--r--plugins/Msg_Export/src/stdafx.h18
-rw-r--r--plugins/Msg_Export/src/utils.cpp219
-rw-r--r--plugins/Msg_Export/src/utils.h5
11 files changed, 205 insertions, 328 deletions
diff --git a/plugins/Import/src/stdafx.h b/plugins/Import/src/stdafx.h
index ec15c520db..97571a11ac 100644
--- a/plugins/Import/src/stdafx.h
+++ b/plugins/Import/src/stdafx.h
@@ -28,9 +28,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <commctrl.h> // datetimepicker
#include <ShlObj.h>
+#include <io.h>
#include <malloc.h>
#include <time.h>
+#include <algorithm>
#include <memory>
#include <newpluginapi.h>
diff --git a/plugins/Import/src/textjson.cpp b/plugins/Import/src/textjson.cpp
index 1c03beca4c..feb826ce8c 100644
--- a/plugins/Import/src/textjson.cpp
+++ b/plugins/Import/src/textjson.cpp
@@ -29,6 +29,15 @@ static int json_makeDatabase(const wchar_t*)
return 1;
}
+static void replaceAll(std::string &str, const char *from, const char *to)
+{
+ size_t start_pos = 0;
+ while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
+ str.replace(start_pos, strlen(from), to);
+ start_pos += strlen(to);
+ }
+}
+
/////////////////////////////////////////////////////////////////////////////////////////
// JSON text driver, read-only
@@ -42,8 +51,8 @@ class CDbxJson : public MDatabaseExport, public MZeroedObject
JSONNode *m_root = nullptr;
LIST<JSONNode> m_events;
LIST<char> m_modules;
- FILE *m_out = nullptr;
- bool m_bAppendOnly = false;
+ bool m_bAppend = true;
+ HANDLE m_out = nullptr;
CMStringA m_szId, m_szReplyId, m_szUserId;
public:
@@ -69,7 +78,7 @@ public:
int Open(const wchar_t *profile)
{
- HANDLE hFile = CreateFile(profile, GENERIC_READ, 0, 0, OPEN_ALWAYS, 0, 0);
+ HANDLE hFile = CreateFileW(profile, GENERIC_READ, 0, 0, OPEN_ALWAYS, 0, 0);
if (hFile == INVALID_HANDLE_VALUE)
return EGROKPRF_CANTREAD;
@@ -245,13 +254,17 @@ public:
int Create(const wchar_t *profile)
{
- m_out = _wfopen(profile, L"wt");
- return (m_out == nullptr) ? EGROKPRF_CANTREAD : EGROKPRF_NOERROR;
+ m_out = CreateFileW(profile, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
+ if (m_out == INVALID_HANDLE_VALUE)
+ return EGROKPRF_CANTREAD;
+
+ SetFilePointer(m_out, -4, 0, FILE_END);
+ return EGROKPRF_NOERROR;
}
STDMETHODIMP_(int) BeginExport() override
{
- return 0;
+ return GetFileSize(m_out, 0) != 0;
}
static int sttEnumSettings(const char *szSetting, void *param)
@@ -309,60 +322,70 @@ public:
pHist.set_name("history");
pRoot.push_back(pHist);
- fputs(pRoot.write_formatted().c_str(), m_out);
- fseek(m_out, -4, SEEK_CUR);
+ DWORD dwWritten;
+ auto szOut = pRoot.write_formatted();
+ replaceAll(szOut, "\n", "\r\n");
+ WriteFile(m_out, szOut.c_str(), (DWORD)szOut.size(), &dwWritten, 0);
+
+ m_bAppend = false;
+ SetFilePointer(m_out, -4, 0, FILE_END);
return 0;
}
STDMETHODIMP_(int) ExportEvent(const DB::EventInfo &dbei) override
{
- if (m_bAppendOnly) {
- fseek(m_out, -4, SEEK_END);
- fputs(",", m_out);
+ if (m_bAppend) {
+ SetFilePointer(m_out, -4, 0, FILE_END);
+
+ DWORD dwWritten;
+ WriteFile(m_out, ",", 1, &dwWritten, 0);
}
- JSONNode pRoot2;
- pRoot2.push_back(JSONNode("type", dbei.eventType));
+ JSONNode pRoot;
+ pRoot.push_back(JSONNode("type", dbei.eventType));
char *szProto = Proto_GetBaseAccountName(dbei.hContact);
if (mir_strcmp(dbei.szModule, szProto))
- pRoot2.push_back(JSONNode("module", dbei.szModule));
+ pRoot.push_back(JSONNode("module", dbei.szModule));
- pRoot2.push_back(JSONNode("timestamp", dbei.timestamp));
+ pRoot.push_back(JSONNode("timestamp", dbei.timestamp));
wchar_t szTemp[500];
TimeZone_PrintTimeStamp(UTC_TIME_HANDLE, dbei.timestamp, L"I", szTemp, _countof(szTemp), 0);
- pRoot2.push_back(JSONNode("isotime", T2Utf(szTemp).get()));
+ pRoot.push_back(JSONNode("isotime", T2Utf(szTemp).get()));
std::string flags;
if (dbei.flags & DBEF_SENT)
flags += "m";
if (dbei.flags & DBEF_READ)
flags += "r";
- pRoot2.push_back(JSONNode("flags", flags));
+ pRoot.push_back(JSONNode("flags", flags));
ptrW msg(DbEvent_GetTextW(&dbei));
if (msg)
- pRoot2.push_back(JSONNode("body", T2Utf(msg).get()));
+ pRoot.push_back(JSONNode("body", T2Utf(msg).get()));
if (dbei.szId)
- pRoot2.push_back(JSONNode("server_id", dbei.szId));
+ pRoot.push_back(JSONNode("server_id", dbei.szId));
if (dbei.szUserId)
- pRoot2.push_back(JSONNode("user_id", dbei.szUserId));
+ pRoot.push_back(JSONNode("user_id", dbei.szUserId));
if (dbei.szReplyId)
- pRoot2.push_back(JSONNode("reply_id", dbei.szReplyId));
+ pRoot.push_back(JSONNode("reply_id", dbei.szReplyId));
- fputs(pRoot2.write_formatted().c_str(), m_out);
- fputs("\n]}", m_out);
+ auto szOut = pRoot.write_formatted();
+ replaceAll(szOut, "\n", "\r\n");
- m_bAppendOnly = true;
+ DWORD dwWritten;
+ WriteFile(m_out, szOut.c_str(), (DWORD)szOut.size(), &dwWritten, 0);
+ WriteFile(m_out, "\r\n]}", 4, &dwWritten, 0);
+ m_bAppend = true;
return 0;
}
STDMETHODIMP_(int) EndExport() override
{
if (m_out)
- fclose(m_out);
+ CloseHandle(m_out);
return 0;
}
};
diff --git a/plugins/Msg_Export/res/resource.rc b/plugins/Msg_Export/res/resource.rc
index 2c9a4b412e..262a43280b 100644
--- a/plugins/Msg_Export/res/resource.rc
+++ b/plugins/Msg_Export/res/resource.rc
@@ -81,7 +81,7 @@ BEGIN
CONTROL "Use JSON format for export",IDC_USE_JSON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,150,287,10
CONTROL "Use UTF-8 in new files",IDC_USE_UTF8_IN_NEW_FILES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,163,287,10
CONTROL "Append extra new line",IDC_APPEND_NEWLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,176,287,10
- CONTROL "Use << and >>",IDC_USE_LESS_AND_GREATER_IN_EXPORT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,188,287,10
+ CONTROL "Use << and >>",IDC_USE_ANGLE_BRACKETS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,188,287,10
END
IDD_OPT_CONTACTS DIALOGEX 0, 0, 310, 234
diff --git a/plugins/Msg_Export/src/FileViewer.cpp b/plugins/Msg_Export/src/FileViewer.cpp
index 50bda31613..cb9d162ef9 100644
--- a/plugins/Msg_Export/src/FileViewer.cpp
+++ b/plugins/Msg_Export/src/FileViewer.cpp
@@ -25,9 +25,6 @@ static UINT UM_FIND_CMD = RegisterWindowMessage(FINDMSGSTRING);
#define ID_FV_SYNTAX_HL 0x0030
#define ID_FV_SAVE_AS_RTF 0x0040
-// Specifies if history is opened internaly or externaly
-bool g_bUseIntViewer = true;
-
// External program used to view files
wstring sFileViewerPrg;
@@ -396,17 +393,6 @@ bool bOpenExternaly(MCONTACT hContact)
}
/////////////////////////////////////////////////////////////////////////////////////////
-// Member Function : bGetInternalViewer
-// Type : Global
-// Parameters : None
-// Returns : Returns true if
-
-bool bUseInternalViewer()
-{
- return g_bUseIntViewer;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
// Member Function : bUseInternalViewer
// Type : Global
// Parameters : bNew - ?
@@ -414,8 +400,8 @@ bool bUseInternalViewer()
bool bUseInternalViewer(bool bNew)
{
- g_bUseIntViewer = bNew;
- if (g_bUseIntViewer && !hRichEditDll) {
+ g_plugin.bUseIntViewer = bNew;
+ if (g_plugin.bUseIntViewer && !hRichEditDll) {
hRichEditDll = LoadLibraryA("Msftedit.dll");
if (!hRichEditDll) {
LogLastError(L"Failed to load Rich Edit (Msftedit.dll)");
diff --git a/plugins/Msg_Export/src/FileViewer.h b/plugins/Msg_Export/src/FileViewer.h
index 400938080e..13379b8753 100644
--- a/plugins/Msg_Export/src/FileViewer.h
+++ b/plugins/Msg_Export/src/FileViewer.h
@@ -26,8 +26,6 @@ bool bShowFileViewer(MCONTACT hContact);
bool bUseInternalViewer(bool bNew);
-extern bool g_bUseIntViewer;
-
extern wstring sFileViewerPrg;
#endif
diff --git a/plugins/Msg_Export/src/main.cpp b/plugins/Msg_Export/src/main.cpp
index 76daadba0f..7f78b1eeb9 100644
--- a/plugins/Msg_Export/src/main.cpp
+++ b/plugins/Msg_Export/src/main.cpp
@@ -22,9 +22,7 @@ CMPlugin g_plugin;
MWindowList hInternalWindowList = nullptr;
-/////////////////////////////////////////////////////
-// Remember to update the Version in the resource !!!
-/////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
PLUGININFOEX pluginInfoEx = {
sizeof(PLUGININFOEX),
@@ -40,29 +38,24 @@ PLUGININFOEX pluginInfoEx = {
};
CMPlugin::CMPlugin() :
- PLUGIN<CMPlugin>(MODULENAME, pluginInfoEx)
+ PLUGIN<CMPlugin>(MODULENAME, pluginInfoEx),
+ bUseJson(MODULENAME, "UseJson", false),
+ bUseIntViewer(MODULENAME, "UseInternalViewer", true),
+ bAppendNewLine(MODULENAME, "AppendNewLine", true),
+ bReplaceHistory(MODULENAME, "ReplaceHistory", false),
+ bUseAngleBrackets(MODULENAME, "UseLessAndGreaterInExport", false),
+ bUseUtf8InNewFiles(MODULENAME, "UseUtf8InNewFiles", true)
{}
-/////////////////////////////////////////////////////////////////////
-// Member Function : ShowExportHistory
-// Type : Global
-// Parameters : wParam - (MCONTACT)hContact
-// lParam - ?
-// Returns : static int
-// Description : Called when user selects my menu item "Open Exported History"
-//
-// References : -
-// Remarks : -
-// Created : 020422, 22 April 2002
-// Developer : KN
-/////////////////////////////////////////////////////////////////////
-
-static INT_PTR ShowExportHistory(WPARAM wParam, LPARAM)
+/////////////////////////////////////////////////////////////////////////////////////////
+// Services
+
+static INT_PTR ShowExportHistory(WPARAM hContact, LPARAM)
{
- if (g_bUseIntViewer)
- bShowFileViewer(wParam);
+ if (g_plugin.bUseIntViewer)
+ bShowFileViewer(hContact);
else
- bOpenExternaly(wParam);
+ bOpenExternaly(hContact);
return 0;
}
@@ -74,43 +67,28 @@ static INT_PTR ExportContactHistory(WPARAM hContact, LPARAM)
return 0;
}
-/////////////////////////////////////////////////////////////////////
-// Member Function : nSystemShutdown
-// Type : Global
-// Parameters : wparam - 0
-// lparam - 0
-// Returns : int
-// Description :
-//
-// References : -
-// Remarks : -
-// Created : 020428, 28 April 2002
-// Developer : KN
-/////////////////////////////////////////////////////////////////////
-
-int nSystemShutdown(WPARAM /*wparam*/, LPARAM /*lparam*/)
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static int nSystemShutdown(WPARAM, LPARAM)
{
WindowList_Broadcast(hInternalWindowList, WM_CLOSE, 0, 0);
return 0;
}
-/////////////////////////////////////////////////////////////////////
-// Member Function : MainInit
-// Type : Global
-// Parameters : wparam - ?
-// lparam - ?
-// Returns : int
-// Description : Called when system modules has been loaded
-//
-// References : -
-// Remarks : -
-// Created : 020422, 22 April 2002
-// Developer : KN
-/////////////////////////////////////////////////////////////////////
-
-int MainInit(WPARAM /*wparam*/, LPARAM /*lparam*/)
+static int OnModuleLoaded(WPARAM, LPARAM)
+{
+ if (g_pDriver = GetDatabasePlugin("JSON"))
+ g_bUseJson = g_plugin.bUseJson;
+ else
+ g_bUseJson = false;
+
+ return 0;
+}
+
+int MainInit(WPARAM, LPARAM)
{
bReadMirandaDirAndPath();
+ OnModuleLoaded(0, 0);
UpdateFileToColWidth();
CMenuItem mi(&g_plugin);
@@ -121,7 +99,7 @@ int MainInit(WPARAM /*wparam*/, LPARAM /*lparam*/)
mi.pszService = MS_EXPORT_HISTORY;
Menu_AddContactMenuItem(&mi);
- if (!g_bReplaceHistory) {
+ if (!g_plugin.bReplaceHistory) {
SET_UID(mi, 0x701c543, 0xd078, 0x41dd, 0x95, 0xe3, 0x96, 0x49, 0x8a, 0x72, 0xc7, 0x50);
mi.hIcolibItem = g_plugin.getIconHandle(IDI_MAIN);
mi.position = 1000090100;
@@ -130,22 +108,14 @@ int MainInit(WPARAM /*wparam*/, LPARAM /*lparam*/)
Menu_AddContactMenuItem(&mi);
}
+ HookEvent(ME_SYSTEM_MODULELOAD, OnModuleLoaded);
+ HookEvent(ME_SYSTEM_MODULEUNLOAD, OnModuleLoaded);
HookEvent(ME_SYSTEM_SHUTDOWN, nSystemShutdown);
return 0;
}
-/////////////////////////////////////////////////////////////////////
-// Member Function : Load
-// Type : Global
-// Parameters : link - ?
-// Returns : int
-// Description :
-//
-// References : -
-// Remarks : -
-// Created : 020422, 22 April 2002
-// Developer : KN
-/////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+// Plugin entry point
static IconItem iconList[] =
{
@@ -172,19 +142,12 @@ int CMPlugin::Load()
g_sTimeFormat = _DBGetStringW(0, MODULENAME, "TimeFormat", L"d s");
sFileViewerPrg = _DBGetStringW(0, MODULENAME, "FileViewerPrg", L"");
- g_bUseIntViewer = getBool("UseInternalViewer", true);
-
- g_bUseJson = getBool("UseJson", false);
- g_bAppendNewLine = getBool("AppendNewLine", true);
- g_bReplaceHistory = getBool("ReplaceHistory", false);
- g_bUseUtf8InNewFiles = getBool("UseUtf8InNewFiles", true);
- g_bUseLessAndGreaterInExport = getBool("UseLessAndGreaterInExport", false);
g_enRenameAction = (ENDialogAction)getByte("RenameAction", eDAPromptUser);
g_enDeleteAction = (ENDialogAction)getByte("DeleteAction", eDAPromptUser);
HANDLE hServiceFunc = nullptr;
- if (g_bReplaceHistory)
+ if (g_plugin.bReplaceHistory)
hServiceFunc = CreateServiceFunction(MS_HISTORY_SHOWCONTACTHISTORY, ShowExportHistory); //this need new code
if (!hServiceFunc)
@@ -196,19 +159,6 @@ int CMPlugin::Load()
return 0;
}
-/////////////////////////////////////////////////////////////////////
-// Member Function : Unload
-// Type : Global
-// Parameters : none
-// Returns :
-// Description :
-//
-// References : -
-// Remarks : -
-// Created : 020422, 22 April 2002
-// Developer : KN
-/////////////////////////////////////////////////////////////////////
-
int CMPlugin::Unload()
{
WindowList_Destroy(hInternalWindowList);
diff --git a/plugins/Msg_Export/src/options.cpp b/plugins/Msg_Export/src/options.cpp
index 31f4e5a6fc..1426854feb 100644
--- a/plugins/Msg_Export/src/options.cpp
+++ b/plugins/Msg_Export/src/options.cpp
@@ -169,10 +169,20 @@ void __cdecl exportContactsMessages(struct ExportDialogData *data)
// Open/create file for writing
wstring sFilePath = F.first;
- HANDLE hFile = openCreateFile(sFilePath);
- if (hFile == INVALID_HANDLE_VALUE) {
- DisplayErrorDialog(LPGENW("Failed to open or create file:\n"), sFilePath, nullptr);
- continue;
+ MDatabaseExport *pJson = nullptr;
+ HANDLE hFile;
+
+ if (g_bUseJson) {
+ pJson = g_pDriver->Export(sFilePath.c_str());
+ pJson->BeginExport();
+ hFile = pJson;
+ }
+ else {
+ hFile = openCreateFile(sFilePath);
+ if (hFile == INVALID_HANDLE_VALUE) {
+ DisplayErrorDialog(LPGENW("Failed to open or create file:\n"), sFilePath, nullptr);
+ continue;
+ }
}
// At first write we need to have this false (to write file header, etc.), for each next write to same file use true
@@ -189,7 +199,11 @@ void __cdecl exportContactsMessages(struct ExportDialogData *data)
}
// Close the file
- CloseHandle(hFile);
+ if (pJson) {
+ pJson->EndExport();
+ delete pJson;
+ }
+ else CloseHandle(hFile);
SendMessage(hProg, PBM_SETPOS, ++nCur, 0);
RedrawWindow(hDlg, nullptr, nullptr, RDW_ALLCHILDREN | RDW_UPDATENOW);
@@ -204,18 +218,36 @@ void __cdecl exportContactsMessages(struct ExportDialogData *data)
class CBasicOptDlg : public CDlgBase
{
CCtrlButton btnBrowseDir, btnBrowseFile;
+ CCtrlCheck chkJson, chkUseUtf8, chkAppendNewLine, chkIntViewer, chkAngleBrackets, chkReplaceHistory;
CCtrlCombo cmbExportDir, cmbDefaultFile, cmbTimeFormat, cmbFileViewer;
+ bool bOrigReplaceHistory;
+
public:
CBasicOptDlg() :
CDlgBase(g_plugin, IDD_OPT_MSGEXPORT),
btnBrowseDir(this, IDC_EXPORT_DIR_BROWSE),
btnBrowseFile(this, IDC_FILE_VIEWER_BROWSE),
+ chkJson(this, IDC_USE_JSON),
+ chkUseUtf8(this, IDC_USE_UTF8_IN_NEW_FILES),
+ chkIntViewer(this, IDC_USE_INTERNAL_VIEWER),
+ chkAppendNewLine(this, IDC_APPEND_NEWLINE),
+ chkAngleBrackets(this, IDC_USE_ANGLE_BRACKETS),
+ chkReplaceHistory(this, IDC_REPLACE_MIRANDA_HISTORY),
cmbExportDir(this, IDC_EXPORT_DIR),
cmbTimeFormat(this, IDC_EXPORT_TIMEFORMAT),
cmbFileViewer(this, IDC_FILE_VIEWER),
cmbDefaultFile(this, IDC_DEFAULT_FILE)
{
+ CreateLink(chkJson, g_plugin.bUseJson);
+ CreateLink(chkUseUtf8, g_plugin.bUseUtf8InNewFiles);
+ CreateLink(chkIntViewer, g_plugin.bUseIntViewer);
+ CreateLink(chkAppendNewLine, g_plugin.bAppendNewLine);
+ CreateLink(chkAngleBrackets, g_plugin.bUseAngleBrackets);
+ CreateLink(chkReplaceHistory, g_plugin.bReplaceHistory);
+
+ bOrigReplaceHistory = g_plugin.bReplaceHistory;
+
btnBrowseDir.OnClick = Callback(this, &CBasicOptDlg::onClick_BrowseDir);
btnBrowseFile.OnClick = Callback(this, &CBasicOptDlg::onClick_BrowseFile);
}
@@ -264,12 +296,7 @@ public:
cmbFileViewer.AddString(L"C:\\WinNT\\Notepad.exe");
cmbFileViewer.AddString(L"C:\\Program Files\\Notepad++\\notepad++.exe");
- CheckDlgButton(m_hwnd, IDC_USE_JSON, g_bUseJson ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_USE_INTERNAL_VIEWER, g_bUseIntViewer ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_REPLACE_MIRANDA_HISTORY, g_bReplaceHistory ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_APPEND_NEWLINE, g_bAppendNewLine ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_USE_UTF8_IN_NEW_FILES, g_bUseUtf8InNewFiles ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(m_hwnd, IDC_USE_LESS_AND_GREATER_IN_EXPORT, g_bUseLessAndGreaterInExport ? BST_CHECKED : BST_UNCHECKED);
+ chkJson.Enable(g_pDriver != 0);
return true;
}
@@ -303,27 +330,12 @@ public:
sFileViewerPrg = szTemp;
g_plugin.setWString("FileViewerPrg", sFileViewerPrg.c_str());
- bUseInternalViewer(IsDlgButtonChecked(m_hwnd, IDC_USE_INTERNAL_VIEWER) == BST_CHECKED);
- g_plugin.setByte("UseInternalViewer", g_bUseIntViewer);
-
- bool bNewRp = IsDlgButtonChecked(m_hwnd, IDC_REPLACE_MIRANDA_HISTORY) == BST_CHECKED;
- if (g_bReplaceHistory != bNewRp) {
- g_bReplaceHistory = bNewRp;
+ if (bOrigReplaceHistory != g_plugin.bReplaceHistory)
MessageBox(m_hwnd, TranslateT("You need to restart Miranda to change the history function"), MSG_BOX_TITEL, MB_OK);
- }
- g_plugin.setByte("ReplaceHistory", g_bReplaceHistory);
-
- g_bUseJson = IsDlgButtonChecked(m_hwnd, IDC_USE_JSON) == BST_CHECKED;
- g_plugin.setByte("UseJson", g_bUseJson);
-
- g_bAppendNewLine = IsDlgButtonChecked(m_hwnd, IDC_APPEND_NEWLINE) == BST_CHECKED;
- g_plugin.setByte("AppendNewLine", g_bAppendNewLine);
- g_bUseUtf8InNewFiles = IsDlgButtonChecked(m_hwnd, IDC_USE_UTF8_IN_NEW_FILES) == BST_CHECKED;
- g_plugin.setByte("UseUtf8InNewFiles", g_bUseUtf8InNewFiles);
+ if (chkJson.Enabled())
+ g_bUseJson = g_plugin.bUseJson;
- g_bUseLessAndGreaterInExport = IsDlgButtonChecked(m_hwnd, IDC_USE_LESS_AND_GREATER_IN_EXPORT) == BST_CHECKED;
- g_plugin.setByte("UseLessAndGreaterInExport", g_bUseLessAndGreaterInExport);
return true;
}
diff --git a/plugins/Msg_Export/src/resource.h b/plugins/Msg_Export/src/resource.h
index d42cfb4645..194585b410 100644
--- a/plugins/Msg_Export/src/resource.h
+++ b/plugins/Msg_Export/src/resource.h
@@ -29,7 +29,7 @@
#define IDC_FILE_VIEWER_BROWSE 1063
#define IDC_FILE_VIEWER 1064
#define IDC_APPEND_NEWLINE 1065
-#define IDC_USE_LESS_AND_GREATER_IN_EXPORT 1066
+#define IDC_USE_ANGLE_BRACKETS 1066
#define IDC_FC_PROMPT 1067
#define IDC_FC_RENAME 1068
#define IDC_FC_NOTHING 1069
diff --git a/plugins/Msg_Export/src/stdafx.h b/plugins/Msg_Export/src/stdafx.h
index 8c22887482..a914349564 100644
--- a/plugins/Msg_Export/src/stdafx.h
+++ b/plugins/Msg_Export/src/stdafx.h
@@ -32,22 +32,22 @@ using namespace std;
#include <map>
#include <newpluginapi.h>
-#include <m_database.h>
-#include <m_metacontacts.h>
#include <m_chat_int.h>
#include <m_clist.h>
#include <m_contacts.h>
+#include <m_db_int.h>
+#include <m_gui.h>
+#include <m_history.h>
+#include <m_icolib.h>
+#include <m_json.h>
#include <m_langpack.h>
+#include <m_metacontacts.h>
#include <m_netlib.h>
#include <m_options.h>
-#include <m_icolib.h>
-#include <m_history.h>
-#include <m_userinfo.h>
#include <m_protosvc.h>
-#include <m_timezones.h>
#include <m_skin.h>
-#include <m_gui.h>
-#include <m_json.h>
+#include <m_timezones.h>
+#include <m_userinfo.h>
#include "utils.h"
#include "options.h"
@@ -66,6 +66,8 @@ struct CMPlugin : public PLUGIN<CMPlugin>
{
CMPlugin();
+ CMOption<bool> bUseJson, bAppendNewLine, bReplaceHistory, bUseIntViewer, bUseAngleBrackets, bUseUtf8InNewFiles;
+
int Load() override;
int Unload() override;
};
diff --git a/plugins/Msg_Export/src/utils.cpp b/plugins/Msg_Export/src/utils.cpp
index c30c32a62b..8fa20770cc 100644
--- a/plugins/Msg_Export/src/utils.cpp
+++ b/plugins/Msg_Export/src/utils.cpp
@@ -49,22 +49,16 @@ map<wstring, string::size_type, less<wstring> > clFileTo1ColWidth;
// default line width
int nMaxLineWidth = 80;
-// Allow this plugin to replace the history function of miranda !!
-bool g_bReplaceHistory;
-
// This enum define the actions which MsgExport must take when a File is renamed
ENDialogAction g_enRenameAction;
// This enum define the actions which MsgExport must take when a user is delete
ENDialogAction g_enDeleteAction;
-// If true MsgExport will use << and >> instead of the nick in the exported format
-bool g_bUseLessAndGreaterInExport;
-
-bool g_bAppendNewLine;
-bool g_bUseUtf8InNewFiles;
bool g_bUseJson;
+DATABASELINK *g_pDriver = nullptr;
+
const char szUtf8ByteOrderHeader[] = "\xEF\xBB\xBF";
bool bIsUtf8Header(uint8_t * pucByteOrder)
{
@@ -228,21 +222,6 @@ static bool bWriteTextToFile(HANDLE hFile, const wchar_t *pszSrc, bool bUtf8File
return bWriteToFile(hFile, T2Utf(pszSrc), -1);
}
-
-static bool bWriteTextToFile(HANDLE hFile, const char *pszSrc, bool bUtf8File, int nLen = -1)
-{
- if (!bUtf8File)
- return bWriteToFile(hFile, pszSrc, nLen);
-
- if (nLen != -1) {
- char *tmp = (char*)alloca(nLen + 1);
- mir_strncpy(tmp, pszSrc, nLen + 1);
- pszSrc = tmp;
- }
-
- return bWriteToFile(hFile, ptrA(mir_utf8encode(pszSrc)), -1);
-}
-
/////////////////////////////////////////////////////////////////////
// Member Function : bWriteNewLine
// Type : Global
@@ -627,6 +606,7 @@ static bool ExportDBEventInfo(MCONTACT hContact, HANDLE hFile, const wstring &sF
wstring sLocalUser;
wstring sRemoteUser;
string::size_type nFirstColumnWidth;
+ auto *pJson = (MDatabaseExport *)hFile;
const char *szProto = Proto_GetBaseAccountName(hContact);
if (szProto == nullptr) {
@@ -634,7 +614,7 @@ static bool ExportDBEventInfo(MCONTACT hContact, HANDLE hFile, const wstring &sF
return false;
}
- if (g_bUseLessAndGreaterInExport) {
+ if (g_plugin.bUseAngleBrackets) {
sLocalUser = L"<<";
sRemoteUser = L">>";
nFirstColumnWidth = 4;
@@ -656,14 +636,9 @@ static bool ExportDBEventInfo(MCONTACT hContact, HANDLE hFile, const wstring &sF
bool bWriteUTF8Format = false;
if (bAppendOnly) {
- bWriteUTF8Format = g_bUseUtf8InNewFiles;
-
- if (g_bUseJson) {
- SetFilePointer(hFile, -3, nullptr, FILE_END);
- bWriteToFile(hFile, ",", 1);
- }
+ bWriteUTF8Format = g_plugin.bUseUtf8InNewFiles;
}
- else {
+ else if (!g_bUseJson) {
DWORD dwHighSize = 0;
DWORD dwLowSize = GetFileSize(hFile, &dwHighSize);
if (dwLowSize == INVALID_FILE_SIZE || dwLowSize != 0 || dwHighSize != 0) {
@@ -672,142 +647,54 @@ static bool ExportDBEventInfo(MCONTACT hContact, HANDLE hFile, const wstring &sF
if (ReadFile(hFile, ucByteOrder, 3, &dwDataRead, nullptr))
bWriteUTF8Format = bIsUtf8Header(ucByteOrder);
- DWORD dwPtr = SetFilePointer(hFile, g_bUseJson ? -3 : 0, nullptr, FILE_END);
+ DWORD dwPtr = SetFilePointer(hFile, 0, nullptr, FILE_END);
if (dwPtr == INVALID_SET_FILE_POINTER)
return false;
- if (g_bUseJson)
- bWriteToFile(hFile, ",", 1);
- }
- else {
- if (g_bUseJson) {
- JSONNode pRoot, pInfo, pHist(JSON_ARRAY);
- pInfo.set_name("info");
- pInfo.push_back(JSONNode("user", T2Utf(sRemoteUser.c_str()).get()));
- pInfo.push_back(JSONNode("proto", szProto));
-
- ptrW contactId(Contact::GetInfo(CNF_UNIQUEID, hContact, szProto));
- if (contactId != NULL)
- pInfo.push_back(JSONNode("uin", T2Utf(contactId).get()));
-
- szTemp[0] = (wchar_t)db_get_b(hContact, szProto, "Gender", 0);
- if (szTemp[0]) {
- szTemp[1] = 0;
- pInfo.push_back(JSONNode("gender", T2Utf(szTemp).get()));
- }
+ bWriteUTF8Format = g_plugin.bUseUtf8InNewFiles;
+ if (bWriteUTF8Format)
+ if (!bWriteToFile(hFile, szUtf8ByteOrderHeader, sizeof(szUtf8ByteOrderHeader) - 1))
+ return false;
- int age = db_get_w(hContact, szProto, "Age", 0);
- if (age != 0)
- pInfo.push_back(JSONNode("age", age));
+ CMStringW output = L"------------------------------------------------\r\n";
+ output.AppendFormat(L"%s\r\n", TranslateT(" History for"));
- for (auto &it : pSettings) {
- wstring szValue = _DBGetStringW(hContact, szProto, it, L"");
- if (!szValue.empty())
- pInfo.push_back(JSONNode(it, T2Utf(szValue.c_str()).get()));
- }
- pRoot.push_back(pInfo);
+ // This is written this way because I expect this will become a string the user may set
+ // in the options dialog.
+ output.AppendFormat(L"%-10s: %s\r\n", TranslateT("User"), sRemoteUser.c_str());
+ output.AppendFormat(L"%-10s: %S\r\n", TranslateT("Account"), szProto);
- pHist.set_name("history");
- pRoot.push_back(pHist);
+ ptrW id(Contact::GetInfo(CNF_UNIQUEID, hContact, szProto));
+ if (id != NULL)
+ output.AppendFormat(L"%-10s: %s\r\n", TranslateT("User ID"), id.get());
- std::string output = pRoot.write_formatted();
- if (!bWriteTextToFile(hFile, output.c_str(), false, (int)output.size()))
- return false;
-
- SetFilePointer(hFile, -3, nullptr, FILE_CURRENT);
+ szTemp[0] = (wchar_t)db_get_b(hContact, szProto, "Gender", 0);
+ if (szTemp[0]) {
+ szTemp[1] = 0;
+ output.AppendFormat(L"%-10s: %s\r\n", TranslateT("Gender"), szTemp);
}
- else {
- bWriteUTF8Format = g_bUseUtf8InNewFiles;
- if (bWriteUTF8Format)
- if (!bWriteToFile(hFile, szUtf8ByteOrderHeader, sizeof(szUtf8ByteOrderHeader) - 1))
- return false;
-
- CMStringW output = L"------------------------------------------------\r\n";
- output.AppendFormat(L"%s\r\n", TranslateT(" History for"));
-
- // This is written this way because I expect this will become a string the user may set
- // in the options dialog.
- output.AppendFormat(L"%-10s: %s\r\n", TranslateT("User"), sRemoteUser.c_str());
- output.AppendFormat(L"%-10s: %S\r\n", TranslateT("Account"), szProto);
-
- ptrW id(Contact::GetInfo(CNF_UNIQUEID, hContact, szProto));
- if (id != NULL)
- output.AppendFormat(L"%-10s: %s\r\n", TranslateT("User ID"), id.get());
-
- szTemp[0] = (wchar_t)db_get_b(hContact, szProto, "Gender", 0);
- if (szTemp[0]) {
- szTemp[1] = 0;
- output.AppendFormat(L"%-10s: %s\r\n", TranslateT("Gender"), szTemp);
- }
- int age = db_get_w(hContact, szProto, "Age", 0);
- if (age != 0)
- output.AppendFormat(L"%-10s: %d\r\n", TranslateT("Age"), age);
+ int age = db_get_w(hContact, szProto, "Age", 0);
+ if (age != 0)
+ output.AppendFormat(L"%-10s: %d\r\n", TranslateT("Age"), age);
- for (auto &it : pSettings) {
- wstring szValue = _DBGetStringW(hContact, szProto, it, L"");
- if (!szValue.empty()) {
- mir_snwprintf(szTemp, L"%-10s: %s\r\n", TranslateW(_A2T(it)), szValue.c_str());
- output += szTemp;
- }
+ for (auto &it : pSettings) {
+ wstring szValue = _DBGetStringW(hContact, szProto, it, L"");
+ if (!szValue.empty()) {
+ mir_snwprintf(szTemp, L"%-10s: %s\r\n", TranslateW(_A2T(it)), szValue.c_str());
+ output += szTemp;
}
+ }
- output += L"------------------------------------------------\r\n";
+ output += L"------------------------------------------------\r\n";
- if (!bWriteTextToFile(hFile, output, bWriteUTF8Format, output.GetLength()))
- return false;
- }
+ if (!bWriteTextToFile(hFile, output, bWriteUTF8Format, output.GetLength()))
+ return false;
}
}
if (g_bUseJson) {
- JSONNode pRoot;
- pRoot.push_back(JSONNode("type", dbei.eventType));
- if (mir_strcmp(dbei.szModule, szProto))
- pRoot.push_back(JSONNode("module", dbei.szModule));
-
- if (dbei.szUserId && !(dbei.flags & DBEF_SENT))
- pRoot.push_back(JSONNode("member", T2Utf(sRemoteUser.c_str()).get()));
-
- TimeZone_PrintTimeStamp(UTC_TIME_HANDLE, dbei.timestamp, L"I", szTemp, _countof(szTemp), 0);
- pRoot.push_back(JSONNode("isotime", T2Utf(szTemp).get()));
-
- std::string flags;
- if (dbei.flags & DBEF_SENT)
- flags += "m";
- if (dbei.flags & DBEF_READ)
- flags += "r";
- if (dbei.flags & DBEF_BOOKMARK)
- flags += "b";
-
- pRoot.push_back(JSONNode("flags", flags));
-
- if (dbei.eventType == EVENTTYPE_FILE) {
- DB::FILE_BLOB blob(dbei);
-
- pRoot << WCHAR_PARAM("file", blob.getName());
- if (mir_wstrlen(blob.getDescr()))
- pRoot << WCHAR_PARAM("descr", blob.getDescr());
- if (blob.isOffline()) {
- pRoot << INT_PARAM("fileSize", blob.getSize()) << INT_PARAM("transferred", blob.getTransferred());
- if (mir_wstrlen(blob.getLocalName()))
- pRoot << WCHAR_PARAM("localFile", blob.getLocalName());
- if (mir_strlen(blob.getUrl()))
- pRoot << CHAR_PARAM("url", blob.getUrl());
- }
- }
- else {
- ptrW msg(DbEvent_GetTextW(&dbei));
- if (msg)
- pRoot.push_back(JSONNode("body", T2Utf(msg).get()));
- }
-
- std::string output = pRoot.write_formatted();
- output += "\n]}";
-
- if (!bWriteTextToFile(hFile, output.c_str(), false, (int)output.size()))
- return false;
-
+ pJson->ExportEvent(dbei);
return true;
}
@@ -937,7 +824,7 @@ static bool ExportDBEventInfo(MCONTACT hContact, HANDLE hFile, const wstring &sF
bWriteTextToFile(hFile, szTemp, bWriteUTF8Format, n);
}
- bWriteToFile(hFile, g_bAppendNewLine ? "\r\n\r\n" : "\r\n");
+ bWriteToFile(hFile, g_plugin.bAppendNewLine ? "\r\n\r\n" : "\r\n");
UpdateFileViews(sFilePath.c_str());
return true;
}
@@ -987,17 +874,37 @@ int nExportEvent(WPARAM hContact, LPARAM hDbEvent)
// Open/create file for writing
wstring sFilePath = GetFilePathFromUser(hContact);
- HANDLE hFile = openCreateFile(sFilePath);
- if (hFile == INVALID_HANDLE_VALUE) {
- DisplayErrorDialog(LPGENW("Failed to open or create file:\n"), sFilePath, nullptr);
- return 0;
+ MDatabaseExport *pJson = nullptr;
+ HANDLE hFile;
+
+ if (g_bUseJson) {
+ pJson = g_pDriver->Export(sFilePath.c_str());
+ if (pJson == nullptr) {
+ DisplayErrorDialog(LPGENW("Failed to open or create file:\n"), sFilePath, nullptr);
+ return 0;
+ }
+
+ if (!pJson->BeginExport())
+ pJson->ExportContact(hContact);
+ hFile = pJson;
+ }
+ else {
+ hFile = openCreateFile(sFilePath);
+ if (hFile == INVALID_HANDLE_VALUE) {
+ DisplayErrorDialog(LPGENW("Failed to open or create file:\n"), sFilePath, nullptr);
+ return 0;
+ }
}
// Write the event
bExportEvent(hContact, hDbEvent, hFile, sFilePath, false);
// Close the file
- CloseHandle(hFile);
+ if (pJson) {
+ pJson->EndExport();
+ delete pJson;
+ }
+ else CloseHandle(hFile);
return 0;
}
diff --git a/plugins/Msg_Export/src/utils.h b/plugins/Msg_Export/src/utils.h
index 8e50aeff9a..b5b650e2f3 100644
--- a/plugins/Msg_Export/src/utils.h
+++ b/plugins/Msg_Export/src/utils.h
@@ -36,12 +36,9 @@ extern wstring g_sDefaultFile;
extern wstring g_sTimeFormat;
extern map<wstring, string::size_type, less<wstring> > clFileTo1ColWidth;
-extern bool g_bAppendNewLine;
extern bool g_bUseJson;
-extern bool g_bUseUtf8InNewFiles;
-extern bool g_bUseLessAndGreaterInExport;
-extern bool g_bReplaceHistory;
+extern DATABASELINK *g_pDriver;
void LogLastError(const wchar_t *pszError);
void DisplayErrorDialog(const wchar_t *pszError, wstring &sFilePath, DBEVENTINFO *dbei);