diff options
author | Szymon Tokarz <wsx22@o2.pl> | 2013-05-27 22:29:01 +0000 |
---|---|---|
committer | Szymon Tokarz <wsx22@o2.pl> | 2013-05-27 22:29:01 +0000 |
commit | c628a13d98fde8d2555cc6fa8628e0b575021bd4 (patch) | |
tree | f25e89f902c0ac82c8f138badbca7f29d331ba18 /plugins/MirFox/src | |
parent | 2f2175b11692b8561fd1018161a62685910d08b0 (diff) |
MirFox plugin for Miranda NG added
Version 0.5.0.0
Compatible Firefox addon is now available at:
https://addons.mozilla.org/pl/firefox/addon/mirfox/versions/0.5.0.0
or http://wsx22.xpdev-hosted.com/
git-svn-id: http://svn.miranda-ng.org/main/trunk@4826 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/MirFox/src')
26 files changed, 3752 insertions, 0 deletions
diff --git a/plugins/MirFox/src/MirandaInterface.cpp b/plugins/MirFox/src/MirandaInterface.cpp new file mode 100644 index 0000000000..d25ac93a34 --- /dev/null +++ b/plugins/MirFox/src/MirandaInterface.cpp @@ -0,0 +1,177 @@ +#include "common.h"
+#include "version.h"
+#include "mirandaInterface.h"
+
+
+
+
+
+//Miranda - handle from DllMain
+HINSTANCE hInst;
+
+//Miranda - Langpack
+int hLangpack;
+
+//Miranda - HANDLE to hooked protocols ACK
+HANDLE hProtoAck;
+
+//popup classes handles
+HANDLE hPopupNotify;
+HANDLE hPopupError;
+
+
+
+
+//main add-on's object
+CMirfoxMiranda mirfoxMiranda;
+
+
+
+PLUGININFOEX pluginInfo={
+ sizeof(PLUGININFOEX),
+ __PLUGIN_NAME,
+ PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
+ __DESCRIPTION,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ UNICODE_AWARE,
+#ifdef _X64
+ { 0xcb5d6b27, 0xb8e0, 0x484c, { 0x87, 0xb0, 0x4d, 0x46, 0x91, 0xa9, 0x4d, 0xee } }
+#else
+ { 0xe99a09b2, 0xe05b, 0x4633, { 0xaa, 0x3a, 0x5c, 0x83, 0xef, 0x1c, 0xba, 0xb6 } }
+#endif
+};
+
+
+extern "C" BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
+
+ hInst = hinstDLL;
+ return TRUE;
+}
+
+
+int lowVersionUserAnswer = -1;
+
+extern "C" __declspec (dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) {
+
+ if(mirfoxMiranda.onMirandaPluginInfoExCheck(mirandaVersion)){
+ return &pluginInfo;
+ } else {
+ if (lowVersionUserAnswer == -1){
+ lowVersionUserAnswer = MessageBox(NULL
+ //, mfTranslate(TEXT("mirfox.too.old.miranda"), TEXT("You use old Miranda version, whitch MirFox was not tested. Do You want to load MirFox plugin ?"))
+ //@langpack: [mirfox.too.old.miranda] Używasz starszej wersji Mirandy, dla której plugin MirFox nie został przetestowany. Czy chcesz uruchomić ten plugin ?
+ , (LPCWSTR)TEXT("You use old Miranda version, whitch MirFox was not tested. Do You want to load MirFox plugin ?") //TODO - translation crash here
+ , (LPCWSTR)TEXT("MirFox")
+ , MB_YESNO | MB_ICONWARNING );
+ }
+ if (lowVersionUserAnswer == IDYES){
+ return &pluginInfo;
+ } else {
+ return NULL;
+ }
+ }
+
+}
+
+
+/*
+ * hook on ME_SYSTEM_MODULESLOADED at Load()
+ */
+static int onModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+
+ //init popup classes
+ POPUPCLASS puc = {0};
+ puc.cbSize = sizeof(puc);
+ puc.flags = PCF_TCHAR;
+
+ puc.pszName = "MirFox_Notify";
+ puc.ptszDescription = MirandaUtils::getInstance()->mfTranslate(LPGENT("mirfox.popup.notify.description"), TEXT("MirFox/Notification"));
+ puc.colorBack = RGB(173, 206, 247); //light blue
+ puc.colorText = GetSysColor(COLOR_WINDOWTEXT);
+ puc.iSeconds = 3;
+ puc.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON_PN));
+ hPopupNotify = Popup_RegisterClass(&puc);
+
+ puc.pszName = "MirFox_Error";
+ puc.ptszDescription = MirandaUtils::getInstance()->mfTranslate(LPGENT("mirfox.popup.error.description"), TEXT("MirFox/Error"));
+ puc.colorBack = RGB(255, 128, 128); //light red
+ puc.colorText = GetSysColor(COLOR_WINDOWTEXT);
+ puc.iSeconds = 20;
+ puc.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON_PE));
+ hPopupError = Popup_RegisterClass(&puc);
+
+ return 0;
+}
+
+static int OnShutdown(WPARAM wParam, LPARAM lParam)
+{
+
+ Popup_UnregisterClass(hPopupError);
+ Popup_UnregisterClass(hPopupNotify);
+
+ return 0;
+}
+
+
+extern "C" int __declspec(dllexport) Load(void){
+
+ HookEvent(ME_SYSTEM_MODULESLOADED, onModulesLoaded);
+ HookEvent(ME_SYSTEM_SHUTDOWN, OnShutdown);
+
+ hProtoAck = HookEvent(ME_PROTO_ACK, MirandaUtils::onProtoAck);
+
+
+
+ //Ensure that the common control DLL is loaded. needed to use ICC_LISTVIEW_CLASSES control in options TODO move to InitOptions();?
+ INITCOMMONCONTROLSEX icex = {0};
+ icex.dwSize = sizeof(icex);
+ icex.dwICC = ICC_LISTVIEW_CLASSES;
+ InitCommonControlsEx(&icex);
+
+ mirfoxMiranda.getMirfoxData().Plugin_Terminated = false;
+ mirfoxMiranda.getMirfoxData().setPluginState(MFENUM_PLUGIN_STATE_INIT);
+ mirfoxMiranda.onMirandaInterfaceLoad();
+ /**MirandaOptions.cpp**/InitOptions();
+
+ if (mirfoxMiranda.getMirfoxData().getPluginState() != MFENUM_PLUGIN_STATE_ERROR){
+ mirfoxMiranda.getMirfoxData().setPluginState(MFENUM_PLUGIN_STATE_WORK);
+ } /*else {
+ mirfoxMiranda.onMirandaInterfaceUnload();
+ DeinitOptions();
+ } */ //TODO
+
+ return 0;
+}
+
+
+extern "C" __declspec (dllexport) int Unload(void) {
+
+ MFLogger::getInstance()->log(L"Unload: start");
+
+
+ //wait for csmThread, msgQueueThread and userActionThread's end
+ mirfoxMiranda.getMirfoxData().Plugin_Terminated = true;
+ UnhookEvent(hProtoAck);
+ int counter = 0;
+ const int UNLOAD_WAIT_TIME = 50; //[ms]
+ const int MAX_UNLOAD_WAIT_COUNTER = 10; //10 * 50ms = 0,5s
+ while (mirfoxMiranda.getMirfoxData().workerThreadsCount > 0 ){
+ MFLogger::getInstance()->log_p(L"Unload: workerThreadsCount=%d > 0, waiting. counter=%d", mirfoxMiranda.getMirfoxData().workerThreadsCount, counter);
+ SleepEx(UNLOAD_WAIT_TIME, TRUE);
+ counter++;
+ }
+ MFLogger::getInstance()->log_p(L"Unload: workerThreadsCount=%d. counter=%d", mirfoxMiranda.getMirfoxData().workerThreadsCount, counter);
+
+
+ MFLogger::getInstance()->log(L"Unload: last log");
+
+ mirfoxMiranda.onMirandaInterfaceUnload();
+ DeinitOptions();
+
+ return 0;
+}
+
diff --git a/plugins/MirFox/src/MirandaInterface.h b/plugins/MirFox/src/MirandaInterface.h new file mode 100644 index 0000000000..71ff271530 --- /dev/null +++ b/plugins/MirFox/src/MirandaInterface.h @@ -0,0 +1,11 @@ +#ifndef _MIRANDAINTERFACE_INC
+#define _MIRANDAINTERFACE_INC
+
+
+#include "resource.h"
+
+#include "MirfoxMiranda.h"
+
+#include "MirandaOptions.h"
+
+#endif //ifndef _MIRANDAINTERFACE_INC
diff --git a/plugins/MirFox/src/MirandaOptions.cpp b/plugins/MirFox/src/MirandaOptions.cpp new file mode 100644 index 0000000000..ec95c8657b --- /dev/null +++ b/plugins/MirFox/src/MirandaOptions.cpp @@ -0,0 +1,814 @@ +#include "common.h"
+#include "MirandaOptions.h"
+
+
+extern CMirfoxMiranda mirfoxMiranda;
+extern HINSTANCE hInst;
+
+
+/*
+ * callback function for tab 1 options page
+ */
+INT_PTR CALLBACK DlgProcOpts_Tab1(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
+
+ switch ( msg ) {
+ case WM_INITDIALOG:
+ {
+ //executed once, during each tab initialization during each miranda options open
+
+ mirfoxMiranda.getMirfoxData().setTab1OptionsState(MFENUM_OPTIONS_INIT);
+
+
+ MirandaUtils* mu = MirandaUtils::getInstance();
+
+ mu->mfTranslateControl(hwndDlg, IDC1_LABEL1,
+ LPGENT("mirfox.options.tab1.sendtocontacts"), TEXT("Send to contact action")
+ );
+ mu->mfTranslateControl(hwndDlg, IDC1_LABEL2,
+ LPGENT("mirfox.options.tab1.left"), TEXT("on left mouse button click")
+ );
+ //IDC1_COMBO1
+ SendDlgItemMessage(hwndDlg, IDC1_COMBO1, CB_ADDSTRING, 0, (LPARAM)mu->mfTranslate(LPGENT("mirfox.options.onlysend"), TEXT("just send message")));
+ SendDlgItemMessage(hwndDlg, IDC1_COMBO1, CB_ADDSTRING, 0, (LPARAM)mu->mfTranslate(LPGENT("mirfox.options.sendandshow"), TEXT("send message and open message window")));
+ SendDlgItemMessage(hwndDlg, IDC1_COMBO1, CB_ADDSTRING, 0, (LPARAM)mu->mfTranslate(LPGENT("mirfox.options.onlyshow"), TEXT("show message window with pasted message")));
+ SendDlgItemMessage(hwndDlg, IDC1_COMBO1, CB_SETCURSEL, (int)mirfoxMiranda.getMirfoxData().leftClickSendMode - 1, 0);
+
+
+ mu->mfTranslateControl(hwndDlg, IDC1_LABEL3,
+ LPGENT("mirfox.options.tab1.right"), TEXT("on right mouse button click")
+ );
+ //IDC1_COMBO2
+ SendDlgItemMessage(hwndDlg, IDC1_COMBO2, CB_ADDSTRING, 0, (LPARAM)mu->mfTranslate(LPGENT("mirfox.options.onlysend"), TEXT("just send message")));
+ SendDlgItemMessage(hwndDlg, IDC1_COMBO2, CB_ADDSTRING, 0, (LPARAM)mu->mfTranslate(LPGENT("mirfox.options.sendandshow"), TEXT("send message and open message window")));
+ SendDlgItemMessage(hwndDlg, IDC1_COMBO2, CB_ADDSTRING, 0, (LPARAM)mu->mfTranslate(LPGENT("mirfox.options.onlyshow"), TEXT("show message window with pasted message")));
+ SendDlgItemMessage(hwndDlg, IDC1_COMBO2, CB_SETCURSEL, (int)mirfoxMiranda.getMirfoxData().rightClickSendMode - 1, 0);
+
+
+ mu->mfTranslateControl(hwndDlg, IDC1_LABEL4,
+ LPGENT("mirfox.options.tab1.middle"), TEXT("on middle mouse button click\n(note: use middle mouse button to send multiple messages from Firefox)")
+ );
+ //IDC1_COMBO3
+ SendDlgItemMessage(hwndDlg, IDC1_COMBO3, CB_ADDSTRING, 0, (LPARAM)mu->mfTranslate(LPGENT("mirfox.options.onlysend"), TEXT("just send message")));
+ //disabled due to Firefox bug. opening other window while firefox menu is still open -> firefox crash
+ //SendDlgItemMessage(hwndDlg, IDC1_COMBO3, CB_ADDSTRING, 0, (LPARAM)mu->mfTranslate(LPGENT("mirfox.options.sendandshow"), TEXT("send message and open message window")));
+ //SendDlgItemMessage(hwndDlg, IDC1_COMBO3, CB_ADDSTRING, 0, (LPARAM)mu->mfTranslate(LPGENT("mirfox.options.onlyshow"), TEXT("show message window with pasted message")));
+ SendDlgItemMessage(hwndDlg, IDC1_COMBO3, CB_SETCURSEL, (int)mirfoxMiranda.getMirfoxData().middleClickSendMode - 1, 0);
+
+
+
+ mu->mfTranslateControl(hwndDlg, IDC1_CHECK1,
+ LPGENT("mirfox.options.tab1.profiles"), TEXT("Show Miranda menu only in this firefox profiles (comma delimeted)")
+ );
+
+
+
+ //other options initialization
+ SetDlgItemText(hwndDlg, IDC1_EDIT1, mirfoxMiranda.getMirfoxData().getClientsProfilesFilterStringPtr()->c_str());
+
+ if (mirfoxMiranda.getMirfoxData().getClientsProfilesFilterCheckbox()){
+ CheckDlgButton(hwndDlg, IDC1_CHECK1, BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC1_EDIT1), TRUE);
+ } else {
+ CheckDlgButton(hwndDlg, IDC1_CHECK1, BST_UNCHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC1_EDIT1), FALSE);
+ }
+ //other options initialization - end
+
+ mirfoxMiranda.getMirfoxData().setTab1OptionsState(MFENUM_OPTIONS_WORK);
+ return FALSE;
+
+ }
+ case WM_COMMAND:
+ {
+ if (mirfoxMiranda.getMirfoxData().getTab1OptionsState() != MFENUM_OPTIONS_WORK){
+ break; //options not inited yet
+ }
+
+ //if user changed some options controls, send info to miranda to activate ok button
+ if (
+ (
+ ((HIWORD(wParam) == EN_CHANGE) && (HWND)lParam == GetFocus()) //edit control AND control from message has focus now
+ ||
+ ((HIWORD(wParam) == BN_CLICKED) && (HWND)lParam == GetFocus()) //button or checkbox clicked AND control from message has focus now
+ ||
+ (HIWORD(wParam) == CBN_DROPDOWN) //COMBOBOX clicked
+ )
+ &&
+ (
+ LOWORD(wParam) != IDC1_BUTTON_INVALIDATE //invalidate button click doesn't activate [Apply] button.
+ )
+ )
+ {
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+
+
+ if (LOWORD(wParam) == IDC1_CHECK1){
+ if (IsDlgButtonChecked(hwndDlg, IDC1_CHECK1) == BST_CHECKED){
+ EnableWindow(GetDlgItem(hwndDlg, IDC1_EDIT1), TRUE);
+ } else {
+ EnableWindow(GetDlgItem(hwndDlg, IDC1_EDIT1), FALSE);
+ }
+ }
+
+
+ if (LOWORD(wParam) == IDC1_BUTTON_INVALIDATE && HIWORD(wParam) == BN_CLICKED){
+ //TODO invalidate button clicked - refresh MSM's (now this button has visable=false at .rc file)
+ break;
+ }
+
+ break;
+ }
+ case WM_NOTIFY:
+ {
+
+ //executed on each move to another options tab or after [OK]
+
+ if (mirfoxMiranda.getMirfoxData().getTab1OptionsState() != MFENUM_OPTIONS_WORK){
+ break; //options not inited yet
+ }
+
+
+ if (((LPNMHDR)lParam)->idFrom == 0 &&
+ ((LPNMHDR)lParam)->code == PSN_APPLY
+ ){
+ //SaveOptions from tab1 mirfoxData to miranda database
+
+
+ mirfoxMiranda.getMirfoxData().leftClickSendMode = (MFENUM_SEND_MESSAGE_MODE)( 1 + (WORD)SendDlgItemMessage(hwndDlg, IDC1_COMBO1, CB_GETCURSEL, 0, 0));
+ db_set_b(0, PLUGIN_DB_ID, "leftClickSendMode", (int)mirfoxMiranda.getMirfoxData().leftClickSendMode);
+
+ mirfoxMiranda.getMirfoxData().rightClickSendMode = (MFENUM_SEND_MESSAGE_MODE)( 1 + (WORD)SendDlgItemMessage(hwndDlg, IDC1_COMBO2, CB_GETCURSEL, 0, 0));
+ db_set_b(0, PLUGIN_DB_ID, "rightClickSendMode", (int)mirfoxMiranda.getMirfoxData().rightClickSendMode);
+
+ mirfoxMiranda.getMirfoxData().middleClickSendMode = (MFENUM_SEND_MESSAGE_MODE)( 1 + (WORD)SendDlgItemMessage(hwndDlg, IDC1_COMBO3, CB_GETCURSEL, 0, 0));
+ db_set_b(0, PLUGIN_DB_ID, "middleClickSendMode", (int)mirfoxMiranda.getMirfoxData().middleClickSendMode);
+
+
+
+ if (IsDlgButtonChecked(hwndDlg, IDC1_CHECK1) == BST_CHECKED){
+ mirfoxMiranda.getMirfoxData().setClientsProfilesFilterCheckbox(true);
+ db_set_b(0, PLUGIN_DB_ID, "clientsProfilesFilterCheckbox", 1);
+ } else {
+ mirfoxMiranda.getMirfoxData().setClientsProfilesFilterCheckbox(false);
+ db_set_b(0, PLUGIN_DB_ID, "clientsProfilesFilterCheckbox", 2);
+ }
+
+
+ int opt2Len = SendDlgItemMessage(hwndDlg, IDC1_EDIT1, WM_GETTEXTLENGTH, 0, 0);
+ wchar_t * opt2Buffer = new WCHAR[opt2Len+1];
+ UINT opt2NumCharCopy = GetDlgItemText(hwndDlg, IDC1_EDIT1, opt2Buffer, opt2Len+1);
+ mirfoxMiranda.getMirfoxData().getClientsProfilesFilterStringPtr()->assign(opt2Buffer);
+ delete opt2Buffer;
+ mirfoxMiranda.getMirfoxData().normalizeClientsProfilesFilterString(SMUCONST_CSM_RECORD_VISABLETO_SIZEC_DEF);
+ SetDlgItemText(hwndDlg, IDC1_EDIT1, mirfoxMiranda.getMirfoxData().getClientsProfilesFilterStringPtr()->c_str());
+
+ MFLogger* logger = MFLogger::getInstance();
+ logger->log_p(L"Options. Save clientsProfilesFilterString: [%s]", mirfoxMiranda.getMirfoxData().getClientsProfilesFilterStringPtr()->c_str());
+ db_set_ts(0, PLUGIN_DB_ID, "clientsProfilesFilterString", mirfoxMiranda.getMirfoxData().getClientsProfilesFilterStringPtr()->c_str());
+
+ //TODO fire actualization visableTo field at CSM record
+
+ }//end of PSN_APPLY
+
+ break;
+
+ }
+ case WM_DESTROY:
+
+ break;
+
+ }
+
+ return 0;
+}
+
+
+
+
+//--------------------------------------TAB 2------------------------------------------------------------------
+
+
+
+static void setListContactIcons(HWND hwndList){
+
+
+ //trick
+ //http://forums.miranda-im.org/showthread.php?t=11800
+ //give IDC2_CONTACTS_LIST control time needed to rebuild internal data list
+ SendMessage(hwndList, WM_TIMER, TIMERID_REBUILDAFTER, 0); //TIMERID_REBUILDAFTER def at m_clistint.h
+
+ //get contacts data from mirfoxData
+ boost::ptr_list<MirandaContact> * mirandaContactsPtr = mirfoxMiranda.getMirfoxData().getMirandaContacts();
+ boost::ptr_list<MirandaContact>::iterator mirandaContactsIter;
+ for (mirandaContactsIter = mirandaContactsPtr->begin(); mirandaContactsIter != mirandaContactsPtr->end(); mirandaContactsIter++){
+
+ HANDLE hContact = mirandaContactsIter->contactHandle;
+ HANDLE hItem = (HANDLE)SendMessage(hwndList, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if(hItem) {
+ //if icon on 0th extracolumn is not set
+ if(SendMessage(hwndList, CLM_GETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(0,0)) == 0xFF){
+ //check contact state on/off
+ if (MFENUM_MIRANDACONTACT_STATE_ON == mirandaContactsIter->contactState){
+ //if on - set icon 1 on 0th extracolumn
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(0,1));
+ } else {
+ //if off (default) - set icon 0 on 0th extracolumn
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(0,0));
+ }
+ }
+ } else {
+ //no contact at options list, probably deleted,
+ //TODO refresh mirfoxData.contacts ??
+ }
+
+ }
+
+ //TODO new contacts on list support - add to mirfoxData
+
+
+}
+
+
+
+#define SIZEOF(X) (sizeof(X)/sizeof(X[0]))
+
+static void setListGroupIcons(HWND hwndList, HANDLE hFirstItem, HANDLE hParentItem, int *groupChildCount){
+
+ int iconOn[1]={1};
+ int childCount[1]={0};
+ int i;
+ int iImage;
+ HANDLE hItem;
+ HANDLE hChildItem;
+
+ int typeOfFirst = SendMessage(hwndList, CLM_GETITEMTYPE, (WPARAM)hFirstItem, 0);
+
+ //check groups
+ if(typeOfFirst == CLCIT_GROUP){
+ hItem = hFirstItem;
+ } else {
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTGROUP,(LPARAM)hFirstItem);
+ }
+
+ while(hItem) {
+ hChildItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hItem);
+ if(hChildItem) {
+ setListGroupIcons(hwndList, hChildItem, hItem, childCount); //recursion
+ }
+ for( i=0; i < SIZEOF(iconOn); i++){
+ if(iconOn[i] && SendMessage(hwndList, CLM_GETEXTRAIMAGE, (WPARAM)hItem,i) == 0){
+ iconOn[i] = 0;
+ }
+ }
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTGROUP, (LPARAM)hItem);
+ }
+
+ //check contacts
+ if(typeOfFirst == CLCIT_CONTACT){
+ hItem = hFirstItem;
+ } else {
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTCONTACT, (LPARAM)hFirstItem);
+ }
+
+ while(hItem) {
+ for ( i=0; i < SIZEOF(iconOn); i++) {
+ iImage = SendMessage(hwndList, CLM_GETEXTRAIMAGE, (WPARAM)hItem, i);
+ if(iconOn[i] && iImage==0){
+ iconOn[i]=0;
+ }
+ if(iImage!=0xFF){
+ childCount[i]++;
+ }
+ }
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTCONTACT, (LPARAM)hItem);
+ }
+
+ //set icons
+ for( i=0; i < SIZEOF(iconOn); i++) {
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hParentItem, MAKELPARAM(i,childCount[i]?(iconOn[i]?i+1:0):0xFF));
+ if(groupChildCount){
+ groupChildCount[i]+=childCount[i];
+ }
+ }
+
+}
+
+static void setAllChildIcons(HWND hwndList, HANDLE hFirstItem, int iColumn, int iImage)
+{
+
+ HANDLE hItem;
+ HANDLE hChildItem;
+
+ int typeOfFirst = SendMessage(hwndList, CLM_GETITEMTYPE, (WPARAM)hFirstItem, 0);
+
+ //check groups
+ if(typeOfFirst==CLCIT_GROUP){
+ hItem = hFirstItem;
+ } else {
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTGROUP, (LPARAM)hFirstItem);
+ }
+
+ while(hItem) {
+ hChildItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hItem);
+ if(hChildItem){
+ setAllChildIcons(hwndList, hChildItem, iColumn, iImage); //recursion
+ }
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTGROUP, (LPARAM)hItem);
+ }
+
+
+ //check contacts
+ if(typeOfFirst==CLCIT_CONTACT){
+ hItem = hFirstItem;
+ } else {
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTCONTACT, (LPARAM)hFirstItem);
+ }
+
+ while(hItem) {
+ int iOldIcon = SendMessage(hwndList, CLM_GETEXTRAIMAGE, (WPARAM)hItem, iColumn);
+ if(iOldIcon!=0xFF && iOldIcon!=iImage){
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(iColumn,iImage));
+ }
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTCONTACT, (LPARAM)hItem);
+ }
+
+}
+
+
+
+/**
+ * set colors, margins, indents, styles etc of list
+ */
+static void resetListOptions(HWND hwndList){
+
+ //background image = null
+ SendMessage(hwndList, CLM_SETBKBITMAP, 0, (LPARAM)(HBITMAP)NULL);
+
+ //background color //TODO - colours
+ SendMessage(hwndList, CLM_SETBKCOLOR, GetSysColor(COLOR_WINDOW), 0);
+
+ //?
+ SendMessage(hwndList, CLM_SETGREYOUTFLAGS, 0, 0);
+
+ //left margin
+ SendMessage(hwndList, CLM_SETLEFTMARGIN, 2, 0);
+
+ //indent
+ SendMessage(hwndList, CLM_SETINDENT, 10, 0);
+
+ //font color //TODO - colours
+ int i;
+ for(i=0; i<=FONTID_MAX; i++){ // FONTID_MAX - miranda const
+ SendMessage(hwndList, CLM_SETTEXTCOLOR, i, GetSysColor(COLOR_WINDOWTEXT));
+ }
+
+ //?
+ SetWindowLong(hwndList, GWL_STYLE, GetWindowLong(hwndList,GWL_STYLE)|CLS_SHOWHIDDEN);
+
+}
+
+
+
+HICON icoHandle_ICON_OFF;
+HICON icoHandle_ICON_FF;
+
+/*
+ * funkcja callback obsługująca stronę z opcjami tab 2
+ */
+INT_PTR CALLBACK DlgProcOpts_Tab2(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
+
+ static HANDLE hItemAll;
+
+ switch ( msg ) {
+ case WM_INITDIALOG:
+ {
+
+ mirfoxMiranda.getMirfoxData().setTab2OptionsState(MFENUM_OPTIONS_INIT);
+
+
+ MirandaUtils::getInstance()->mfTranslateControl(hwndDlg, IDC2_LABEL1,
+ LPGENT("mirfox.options.tab2.contacts"), TEXT("Show this contacts in 'Send ... to' option in Firefox")
+ );
+
+
+ //load icons
+ HIMAGELIST hIml;
+ int smCx = GetSystemMetrics(SM_CXSMICON);
+ int smCy = GetSystemMetrics(SM_CYSMICON);
+ hIml = ImageList_Create(smCx,smCy,((LOBYTE(LOWORD(GetVersion()))>=5 && LOWORD(GetVersion())!=5) ? ILC_COLOR32 : ILC_COLOR16) | ILC_MASK, 4, 4);
+
+ //load icons (direct)
+ icoHandle_ICON_OFF = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON_OFF));
+ icoHandle_ICON_FF = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON_FF));
+
+ //TODO load icons (icolib) - no need to use DestroyIcon
+ //HICON icoHandle_ICON_OFF = (HICON)CallService(MS_SKIN2_GETICONBYHANDLE, 0, (LPARAM)mirfoxData.icoHandle_ICON_OFF);
+ //HICON icoHandle_ICON_FF = (HICON)CallService(MS_SKIN2_GETICONBYHANDLE, 0, (LPARAM)mirfoxData.icoHandle_ICON_FF);
+
+ //add icons to ImageList list
+ ImageList_AddIcon(hIml, icoHandle_ICON_OFF);
+ ImageList_AddIcon(hIml, icoHandle_ICON_FF);
+ SendDlgItemMessage(hwndDlg, IDC2_CONTACTS_LIST, CLM_SETEXTRAIMAGELIST, 0, (LPARAM)hIml); //m_clc.h
+
+
+ //list params init
+ resetListOptions(GetDlgItem(hwndDlg, IDC2_CONTACTS_LIST));
+ SendDlgItemMessage(hwndDlg, IDC2_CONTACTS_LIST, CLM_SETEXTRACOLUMNS, 1, 0);
+
+ //add 'All contacts' list record
+ {
+ CLCINFOITEM cii = {0};
+ cii.cbSize = sizeof(cii);
+ cii.flags = CLCIIF_GROUPFONT;
+ cii.pszText = MirandaUtils::getInstance()->mfTranslate(LPGENT("mirfox.options.tab2.allcontacts"), TEXT("** All contacts **"));
+ hItemAll = (HANDLE)SendDlgItemMessage(hwndDlg, IDC2_CONTACTS_LIST, CLM_ADDINFOITEM, 0, (LPARAM)&cii);
+ }
+
+ //set contacts and groups icons
+ setListContactIcons(GetDlgItem(hwndDlg, IDC2_CONTACTS_LIST));
+ setListGroupIcons(GetDlgItem(hwndDlg, IDC2_CONTACTS_LIST), (HANDLE)SendDlgItemMessage(hwndDlg, IDC2_CONTACTS_LIST, CLM_GETNEXTITEM, CLGN_ROOT, 0), hItemAll, NULL);
+
+
+ mirfoxMiranda.getMirfoxData().setTab2OptionsState(MFENUM_OPTIONS_WORK);
+ return FALSE;
+
+ }
+ case WM_SETFOCUS:
+
+ SetFocus(GetDlgItem(hwndDlg, IDC2_CONTACTS_LIST));
+ break;
+
+ case WM_NOTIFY:
+
+ if (mirfoxMiranda.getMirfoxData().getTab2OptionsState() != MFENUM_OPTIONS_WORK){
+ break; //options not inited yet
+ }
+
+ switch(((LPNMHDR)lParam)->idFrom) {
+ case IDC2_CONTACTS_LIST:
+
+ switch (((LPNMHDR)lParam)->code){
+
+ case CLN_NEWCONTACT:
+ case CLN_LISTREBUILT:
+ setListContactIcons(GetDlgItem(hwndDlg, IDC2_CONTACTS_LIST));
+ //fall through
+ case CLN_CONTACTMOVED:
+ setListGroupIcons(GetDlgItem(hwndDlg, IDC2_CONTACTS_LIST), (HANDLE)SendDlgItemMessage(hwndDlg, IDC2_CONTACTS_LIST, CLM_GETNEXTITEM, CLGN_ROOT, 0), hItemAll, NULL);
+ break;
+ case CLN_OPTIONSCHANGED:
+ resetListOptions(GetDlgItem(hwndDlg, IDC2_CONTACTS_LIST));
+ break;
+ case NM_CLICK:
+ {
+
+ NMCLISTCONTROL *nm=(NMCLISTCONTROL*)lParam;
+
+ // Make sure we have an extra column
+ if (nm->iColumn == -1){
+ break;
+ }
+
+ // Find clicked item
+ DWORD hitFlags;
+ HANDLE hItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC2_CONTACTS_LIST, CLM_HITTEST, (WPARAM)&hitFlags, MAKELPARAM(nm->pt.x, nm->pt.y));
+
+ // Nothing was clicked
+ if (hItem == NULL){
+ break;
+ }
+ // It was not a visbility icon
+ if (!(hitFlags & CLCHT_ONITEMEXTRA)){
+ break;
+ }
+
+ // Get image in clicked column (0=off, 1=on)
+ int iImage = SendDlgItemMessage(hwndDlg, IDC2_CONTACTS_LIST, CLM_GETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(nm->iColumn, 0));
+ if (iImage == 0){
+ iImage=nm->iColumn + 1;
+ } else {
+ if (iImage == 1){
+ iImage = 0;
+ }
+ }
+
+ // Get item type (contact, group, etc...)
+ int itemType = SendDlgItemMessage(hwndDlg, IDC2_CONTACTS_LIST, CLM_GETITEMTYPE, (WPARAM)hItem, 0);
+
+ // Update list
+ if (itemType == CLCIT_CONTACT) { // A contact
+ SendDlgItemMessage(hwndDlg, IDC2_CONTACTS_LIST, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(nm->iColumn, iImage));
+ } else if (itemType == CLCIT_INFO) { // All Contacts
+ setAllChildIcons(GetDlgItem(hwndDlg, IDC2_CONTACTS_LIST), hItem, nm->iColumn, iImage);
+ } else if (itemType == CLCIT_GROUP) { // A group
+ hItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC2_CONTACTS_LIST, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hItem);
+ if (hItem) {
+ setAllChildIcons(GetDlgItem(hwndDlg, IDC2_CONTACTS_LIST), hItem, nm->iColumn, iImage);
+ }
+ }
+
+ // Update the all/none icons
+ setListGroupIcons(GetDlgItem(hwndDlg, IDC2_CONTACTS_LIST), (HANDLE)SendDlgItemMessage(hwndDlg, IDC2_CONTACTS_LIST, CLM_GETNEXTITEM, CLGN_ROOT, 0), hItemAll, NULL);
+
+ // Activate Apply button
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+
+ break;
+ }//end case NM_CLICK
+
+ }//end switch
+
+ break;
+
+ case 0:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+
+ for (HANDLE hContact = db_find_first(); hContact; hContact = db_find_next(hContact)){
+
+ HANDLE hItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC2_CONTACTS_LIST, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if(hItem) {
+
+ int iImage = SendDlgItemMessage(hwndDlg, IDC2_CONTACTS_LIST, CLM_GETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(0,0));
+ MFENUM_MIRANDACONTACT_STATE contactState;
+
+ if (iImage == 0xFF){ //TODO impossible??
+ } else {
+ if (iImage == 1){
+ contactState = MFENUM_MIRANDACONTACT_STATE_ON;
+ } else {
+ contactState = MFENUM_MIRANDACONTACT_STATE_OFF;
+ }
+ }
+
+ //save to mirfoxData
+ int result = mirfoxMiranda.getMirfoxData().updateMirandaContactState(hContact, contactState);
+ if (result != 0){
+ //todo errors handling
+ }
+
+ //save to db 1 - on, 2 - off
+ if (contactState == MFENUM_MIRANDACONTACT_STATE_OFF){
+ db_set_b(hContact, PLUGIN_DB_ID, "state", 2);
+ } else {
+ db_set_b(hContact, PLUGIN_DB_ID, "state", 1);
+ }
+
+
+ }//TODO else { ... (and at others if(hItem))
+ //TODO contacts witch are not ay mirfoxData but on list
+ //( check hash concat(all id) on mirfoxData and on list, if doesn't match - refresh mirfoxData
+ //same for protocols
+ //for now it schould be ok
+
+ }
+
+ //TODO contacts at MirfoxData but not on list now
+
+ return TRUE;
+ }
+ }
+ break;
+ }
+
+ break;
+
+ case WM_DESTROY:
+ {
+ HIMAGELIST hIml=(HIMAGELIST)SendDlgItemMessage(hwndDlg, IDC2_CONTACTS_LIST, CLM_GETEXTRAIMAGELIST, 0, 0); //m_clc.h
+ ImageList_Destroy(hIml);
+
+ // use DestroyIcon only witchout icolib
+ DestroyIcon(icoHandle_ICON_OFF);
+ icoHandle_ICON_OFF = NULL;
+ DestroyIcon(icoHandle_ICON_FF);
+ icoHandle_ICON_FF = NULL;
+
+ break;
+
+ }
+ }//end switch
+
+ return 0;
+}
+
+
+
+
+
+/*
+ * callback function for tab 3 options page
+ */
+INT_PTR CALLBACK DlgProcOpts_Tab3(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
+
+ switch ( msg ) {
+ case WM_INITDIALOG:
+ {
+ //executed once during init of each tab, on each enter to miranda options
+
+ mirfoxMiranda.getMirfoxData().setTab3OptionsState(MFENUM_OPTIONS_INIT);
+
+
+ MirandaUtils::getInstance()->mfTranslateControl(hwndDlg, IDC3_LABEL1,
+ LPGENT("mirfox.options.tab3.accounts"), TEXT("Show this accounts in 'Set status message' option in Firefox")
+ );
+
+
+ //protocol list initialization
+ HWND hAccountsList = GetDlgItem(hwndDlg, IDC3_PROTOCOLS_LIST);
+
+ ListView_SetExtendedListViewStyleEx(hAccountsList, LVS_EX_FULLROWSELECT|LVS_EX_CHECKBOXES, LVS_EX_FULLROWSELECT|LVS_EX_CHECKBOXES);
+
+ LVCOLUMN lvCol = {0};
+ lvCol.mask = LVCF_WIDTH|LVCF_TEXT;
+ lvCol.pszText=TEXT("Protocol");
+ lvCol.cx = 260; //column width
+ ListView_InsertColumn(hAccountsList, 0, &lvCol);
+
+ LVITEM lvItem = {0};
+ lvItem.mask=LVIF_TEXT|LVIF_PARAM;
+ lvItem.iItem=0;
+ lvItem.iSubItem=0;
+
+ //get accounts data from mirfoxData
+ boost::ptr_list<MirandaAccount> * mirandaAccountsPtr = mirfoxMiranda.getMirfoxData().getMirandaAccounts();
+ boost::ptr_list<MirandaAccount>::iterator mirandaAccountsIter;
+ for (mirandaAccountsIter = mirandaAccountsPtr->begin(); mirandaAccountsIter != mirandaAccountsPtr->end(); mirandaAccountsIter++){
+
+ lvItem.pszText = mirandaAccountsIter->tszAccountName;
+ //http://www.experts-exchange.com/Programming/Languages/CPP/Q_20175412.html - must duplicate string
+ lvItem.lParam = (LPARAM)_strdup(mirandaAccountsIter->szModuleName);
+ ListView_InsertItem(hAccountsList,&lvItem);//winapi function
+
+ MFENUM_MIRANDAACCOUNT_STATE accountState = mirandaAccountsIter->accountState;
+ if (accountState == MFENUM_MIRANDAACCOUNT_STATE_ON){
+ ListView_SetCheckState(hAccountsList, lvItem.iItem, 1 );
+ } else {
+ ListView_SetCheckState(hAccountsList, lvItem.iItem, 0 );
+ }
+
+ lvItem.iItem++;
+ }
+ //protocol list initialization - end
+
+ mirfoxMiranda.getMirfoxData().setTab3OptionsState(MFENUM_OPTIONS_WORK);
+ return FALSE;
+
+ }
+ case WM_COMMAND:
+ {
+ if (mirfoxMiranda.getMirfoxData().getTab3OptionsState() != MFENUM_OPTIONS_WORK){
+ break; //options not inited yet
+ }
+
+ break;
+ }
+ case WM_NOTIFY:
+ {
+
+ //executed on each change tab at options or after [OK]
+
+ if (mirfoxMiranda.getMirfoxData().getTab3OptionsState() != MFENUM_OPTIONS_WORK){
+ break; //options not inited yet
+ }
+
+
+ if (((NMHDR*)lParam)->idFrom == IDC3_PROTOCOLS_LIST) {
+ if (((NMHDR*)lParam)->code== LVN_ITEMCHANGED) {
+ NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam;
+ if (/*IsWindowVisible(GetDlgItem(hwndDlg,IDC_PROTOCOLLIST)) && */ ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK)) {
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ }
+ }
+
+ if (((LPNMHDR)lParam)->idFrom == 0 &&
+ ((LPNMHDR)lParam)->code == PSN_APPLY
+ ){
+ //SaveOptions from tab3 mirfoxData to miranda database
+
+ int i;
+ HWND hList = GetDlgItem(hwndDlg, IDC3_PROTOCOLS_LIST);
+ LVITEM lvItem = {0};
+ lvItem.mask = LVIF_PARAM;
+ for (i=0; i<ListView_GetItemCount(hList); i++) {
+
+ lvItem.iItem = i;
+ lvItem.iSubItem = 0;
+ ListView_GetItem(hList, &lvItem);
+
+ char * accountId ((char *)lvItem.lParam);
+ BYTE accountStateB = (BYTE)ListView_GetCheckState(hList, lvItem.iItem);
+
+ MFENUM_MIRANDAACCOUNT_STATE accountState;
+ if (accountStateB == 0){
+ accountState = MFENUM_MIRANDAACCOUNT_STATE_OFF;
+ } else if (accountStateB == 1){
+ accountState = MFENUM_MIRANDAACCOUNT_STATE_ON;
+ } else {
+ //todo errors handling
+ accountState = MFENUM_MIRANDAACCOUNT_STATE_ON;
+ }
+
+ //save to mirfoxData
+ int result = mirfoxMiranda.getMirfoxData().updateMirandaAccountState(accountId, accountState);
+ if (result != 0){
+ //todo errors handling
+ }
+
+ //save to db 1 - on, 2 - off
+ std::string mirandaAccountDBKey("ACCOUNTSTATE_");
+ mirandaAccountDBKey += accountId;
+ if (accountState == MFENUM_MIRANDAACCOUNT_STATE_OFF){
+ db_set_b(0, PLUGIN_DB_ID, mirandaAccountDBKey.c_str(), 2);
+ } else {
+ db_set_b(0, PLUGIN_DB_ID, mirandaAccountDBKey.c_str(), 1);
+ }
+
+
+ } //end for
+
+ }
+
+ break;
+
+ }
+ case WM_DESTROY:
+
+ break;
+
+ }
+
+ return 0;
+
+}
+
+
+
+
+
+
+
+
+
+
+/**
+ *
+ * called from: options.cpp.InitOptions()
+ */
+int OptInit(WPARAM wParam, LPARAM lParam) {
+
+ OPTIONSDIALOGPAGE odp = { 0 };
+
+ //options init
+ odp.cbSize = sizeof(odp);
+ odp.position = -790000000;
+ odp.hInstance = hInst;
+ odp.ptszTitle = LPGENT(PLUGIN_OPTIONS_NAME);
+ odp.ptszGroup = LPGENT("Services");
+
+ odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR;
+
+ //1 - options
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT1);
+ odp.ptszTab = MirandaUtils::getInstance()->mfTranslate(LPGENT("mirfox.options.tab1"), TEXT("Options"));
+ odp.pfnDlgProc = DlgProcOpts_Tab1;
+ Options_AddPage(wParam, &odp);
+
+ //2 - contacts
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT2);
+ odp.ptszTab = MirandaUtils::getInstance()->mfTranslate(LPGENT("mirfox.options.tab2"), TEXT("Contacts"));
+ odp.pfnDlgProc = DlgProcOpts_Tab2;
+ Options_AddPage(wParam, &odp);
+
+ //3 - accounts
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT3);
+ odp.ptszTab = MirandaUtils::getInstance()->mfTranslate(LPGENT("mirfox.options.tab3"), TEXT("Accounts"));
+ odp.pfnDlgProc = DlgProcOpts_Tab3;
+ Options_AddPage(wParam, &odp);
+
+ return 0;
+}
+
+
+
+HANDLE hEventOptInit;
+
+/**
+ *
+ * called from: MirfoxMiranda.cpp.Load(PLUGINLINK *link)
+ */
+void InitOptions() {
+ hEventOptInit = HookEvent(ME_OPT_INITIALISE, OptInit);
+}
+
+/**
+ *
+ * called from: MirfoxMiranda.cpp.Unload()
+ */
+void DeinitOptions() {
+ UnhookEvent(hEventOptInit);
+}
diff --git a/plugins/MirFox/src/MirandaOptions.h b/plugins/MirFox/src/MirandaOptions.h new file mode 100644 index 0000000000..8b68c25a53 --- /dev/null +++ b/plugins/MirFox/src/MirandaOptions.h @@ -0,0 +1,10 @@ +#ifndef _MIRANDA_OPTIONS_INC
+#define _MIRANDA_OPTIONS_INC
+
+#include "MirandaInterface.h"
+
+void InitOptions();
+
+void DeinitOptions();
+
+#endif //#ifndef _MIRANDA_OPTIONS_INC
diff --git a/plugins/MirFox/src/MirandaUtils.cpp b/plugins/MirFox/src/MirandaUtils.cpp new file mode 100644 index 0000000000..28ba5c4294 --- /dev/null +++ b/plugins/MirFox/src/MirandaUtils.cpp @@ -0,0 +1,705 @@ +#include "common.h"
+#include "MirandaUtils.h"
+
+
+/*static*/ MirandaUtils * MirandaUtils::m_pOnlyOneInstance;
+
+// private constructor
+MirandaUtils::MirandaUtils()
+ : logger(MFLogger::getInstance())
+{
+
+ netlibHandle = NULL;
+ InitializeCriticalSection(&ackMapCs);
+
+}
+
+
+/* static */ void
+MirandaUtils::netlibLog(const wchar_t* szText){
+ MirandaUtils::getInstance()->netlibLog_int(szText);
+}
+
+void
+MirandaUtils::netlibLog_int(const wchar_t* szText){
+ if (netlibHandle) {
+ CallService(MS_NETLIB_LOGW, (WPARAM)netlibHandle, (LPARAM)szText);
+ }
+#ifdef _DEBUG
+ OutputDebugString(szText);
+#endif //_DEBUG
+}
+
+void
+MirandaUtils::netlibRegister(){
+
+ // Register netlib user for logging function
+ NETLIBUSER nlu = { 0 };
+ nlu.cbSize = sizeof(nlu);
+ nlu.flags = NUF_TCHAR | NUF_NOOPTIONS;
+ nlu.szSettingsModule = PLUGIN_DB_ID;
+ nlu.ptszDescriptiveName = mfTranslate(LPGENT("mirfox.netlib.name"), TEXT("MirFox log"));
+
+ netlibHandle = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
+
+}
+
+void
+MirandaUtils::netlibUnregister(){
+
+ Netlib_CloseHandle(netlibHandle);
+ netlibHandle = NULL;
+
+}
+
+
+std::wstring&
+MirandaUtils::getProfileName()
+{
+ if (profileName.size()>0){
+ //profileName is now inited
+ return profileName;
+ }
+
+ wchar_t mirandaProfileNameW[128] = {0};
+ CallService(MS_DB_GETPROFILENAMEW, SIZEOF(mirandaProfileNameW), (WPARAM)mirandaProfileNameW);
+ profileName.append(mirandaProfileNameW);
+
+ return profileName;
+}
+
+
+std::wstring&
+MirandaUtils::getDisplayName()
+{
+ if (displayName.size()>0){
+ //displayName is now inited
+ return displayName;
+ }
+
+ displayName.append(L"Miranda NG v.");
+ char mirandaVersion[128];
+ CallService(MS_SYSTEM_GETVERSIONTEXT, (WPARAM)SIZEOF(mirandaVersion), (LPARAM)mirandaVersion);
+ displayName.append(_A2T(mirandaVersion));
+ displayName.append(L" (");
+ displayName.append(getProfileName());
+ displayName.append(L")");
+
+ return displayName;
+
+}
+
+
+/*
+ * mfTranslate
+ * It is my old solution of problem with not unique strings that must be translate by miranda.
+ * Function takes unique code (string id) and default translation (english)
+ * if no translation for code is found it returns default string.
+ * mfTranslate works on plugins layer and can't be used with core translated strings
+ * Tell me if this not standard solution cause problems in NG langpacks environment.
+ */
+TCHAR*
+MirandaUtils::mfTranslate(const TCHAR* msgCode, TCHAR* msgDefault)
+{
+ TCHAR* msgTranslated = TranslateTS(msgCode);
+ if (_tcscmp(msgCode, msgTranslated) == 0){
+ //no translation in miranda langpack
+ return msgDefault;
+ } else {
+ return msgTranslated;
+ }
+}
+
+
+void
+MirandaUtils::mfTranslateControl(HWND parentWindowHwnd, long controlId, const TCHAR* msgCode, TCHAR* msgDefault)
+{
+ HWND controlHwnd = GetDlgItem(parentWindowHwnd, controlId);
+ if (controlHwnd != NULL){
+ int currentTextLength = GetWindowTextLength(controlHwnd) + 1;
+ TCHAR* currentTextPtr = new TCHAR[currentTextLength];
+ GetWindowText(controlHwnd, currentTextPtr, currentTextLength);
+ SetWindowText(controlHwnd, mfTranslate(msgCode, msgDefault));
+ delete [] currentTextPtr;
+ }
+}
+
+
+
+
+/*static*/ void
+MirandaUtils::userActionThread(void* threadArg)
+{
+ Thread_Push(0);
+ ActionThreadArgStruct* actionThreadArgPtr = (ActionThreadArgStruct*)threadArg;
+
+ if (actionThreadArgPtr->mirfoxDataPtr == NULL){
+ MFLogger::getInstance()->log(L"MirandaUtils::userActionThread: ERROR mirfoxDataPtr == NULL");
+ return;
+ }
+
+ if (actionThreadArgPtr->mirfoxDataPtr->Plugin_Terminated){
+ MFLogger::getInstance()->log(L"MirandaUtils::userActionThread: Plugin_Terminated return");
+ return;
+ }
+
+ actionThreadArgPtr->mirfoxDataPtr->workerThreadsCount++;
+
+ if (actionThreadArgPtr->menuItemType == 'C'){
+ actionThreadArgPtr->instancePtr->sendMessageToContact(actionThreadArgPtr);
+ } else if (actionThreadArgPtr->menuItemType == 'A'){
+ actionThreadArgPtr->instancePtr->setStatusOnAccount(actionThreadArgPtr);
+ delete actionThreadArgPtr->accountSzModuleName;
+ } else {
+ MFLogger::getInstance()->log(TEXT("MirandaUtils::userActionThread: ERROR: unknown actionThreadArgPtr->menuItemType"));
+ }
+
+ delete actionThreadArgPtr->userActionSelection;
+ actionThreadArgPtr->mirfoxDataPtr->workerThreadsCount--;
+ delete threadArg;
+
+ Thread_Pop();
+ return;
+
+}
+
+
+
+void
+MirandaUtils::sendMessageToContact(ActionThreadArgStruct* args)
+{
+
+ logger->log(L"MirandaUtils::sendMessageToContact: start");
+
+ if (args->targetHandle == NULL){
+ logger->log(L"MirandaUtils::sendMessageToContact: ERROR targetHandle == NULL");
+ return;
+ }
+
+ if (args->userButton == 'R'){ //'R'ight mouse button
+ this->sendMessage(args, args->mirfoxDataPtr->rightClickSendMode);
+ } else if (args->userButton == 'M'){ //'M'iddle mouse button
+ this->sendMessage(args, args->mirfoxDataPtr->middleClickSendMode);
+ } else { //'L'eft mouse button
+ this->sendMessage(args, args->mirfoxDataPtr->leftClickSendMode);
+ }
+
+}
+
+
+void
+MirandaUtils::sendMessage(ActionThreadArgStruct* args, MFENUM_SEND_MESSAGE_MODE mode)
+{
+
+ logger->log_p(L"MirandaUtils::sendMessage: mode = [%d] to = [" SCNuPTR L"] msg = [%s]", mode, args->targetHandle, args->userActionSelection );
+
+ if (mode == MFENUM_SMM_ONLY_SEND || mode == MFENUM_SMM_SEND_AND_SHOW_MW){
+
+ //TODO - metacontacts support - C:\MIRANDA\SOURCES\PLUGINS\popup_trunk\src\popup_wnd2.cpp : 1083
+ // //check for MetaContact and get szProto from subcontact
+ // if(strcmp(targetHandleSzProto, gszMetaProto)==0) {
+ // HANDLE hSubContact = (HANDLE)CallService(MS_MC_GETDEFAULTCONTACT, (WPARAM)hContact, 0);
+ // if(!hSubContact) return FALSE;
+ // targetHandleSzProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hSubContact, 0);
+ // }
+
+ char* targetHandleSzProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)args->targetHandle, 0); //targetHandleSzProto doesnt need mir_free or delete
+ if (targetHandleSzProto == NULL){
+ logger->log(L"MirandaUtils::sendMessageToContact: ERROR targetHandleSzProto == NULL");
+ return;
+ }
+
+ int mirandaSendModeFlag = getMirandaSendModeFlag(targetHandleSzProto);
+
+ char* msgBuffer = NULL;
+ std::size_t bufSize = 0;
+
+ if (mirandaSendModeFlag == PREF_UTF){
+
+ msgBuffer = mir_utf8encodeW(args->userActionSelection);
+ bufSize = strlen(msgBuffer) + 1;
+
+ } else if (mirandaSendModeFlag == PREF_UNICODE){
+
+ msgBuffer = mir_t2a(args->userActionSelection);
+ bufSize = strlen(msgBuffer) + 1;
+ size_t bufSizeT = (wcslen(args->userActionSelection) + 1) * sizeof(wchar_t);
+ msgBuffer = (char*)mir_realloc(msgBuffer, bufSizeT + bufSize);
+ memcpy((wchar_t*)&msgBuffer[bufSize], args->userActionSelection, bufSizeT);
+ bufSize += bufSizeT;
+
+ }
+
+ logger->log_p(L"SMTC: mirandaSendModeFlag = [%d] bufSize = [%d]", mirandaSendModeFlag, bufSize);
+ HANDLE hProcess = sendMessageMiranda(args->targetHandle, mirandaSendModeFlag, msgBuffer);
+ logger->log_p(L"SMTC: hProcess = [" SCNuPTR L"]", hProcess);
+
+ MIRFOXACKDATA* myMfAck = NULL;
+
+ if (hProcess != NULL){
+ //if hProcess of sending process is null there will not be any ack
+
+ EnterCriticalSection(&ackMapCs);
+ ackMap[hProcess] = (MIRFOXACKDATA*)NULL;
+ LeaveCriticalSection(&ackMapCs);
+
+ int counter = 0;
+ const int ACK_WAIT_TIME = 250; //[ms]
+ const int MAX_ACK_WAIT_COUNTER = 40; //40 * 250ms = 10s
+
+ do {
+ SleepEx(ACK_WAIT_TIME, TRUE);
+ counter++;
+ EnterCriticalSection(&ackMapCs);
+ myMfAck = ackMap[hProcess];
+ LeaveCriticalSection(&ackMapCs);
+ if(Miranda_Terminated() || args->mirfoxDataPtr->Plugin_Terminated){
+ logger->log_p(L"SMTC: ACK break by Plugin_Terminated (=%d) or Miranda_Terminated()", args->mirfoxDataPtr->Plugin_Terminated);
+ break;
+ }
+ } while (myMfAck == NULL && counter <= MAX_ACK_WAIT_COUNTER); //TODO or Plugin_Terminated or Miranda_Terminated()
+
+ logger->log_p(L"SMTC: ACK found counter = [%d] myMfAck = [" SCNuPTR L"]", counter, myMfAck);
+
+ }
+
+
+ MirandaContact* mirandaContact = args->mirfoxDataPtr->getMirandaContactPtrByHandle(args->targetHandle);
+ const wchar_t* contactNameW = NULL;
+ TCHAR* tszAccountName = NULL;
+ if (mirandaContact){
+ contactNameW = mirandaContact->contactNameW.c_str();
+ MirandaAccount* mirandaAccount = mirandaContact->mirandaAccountPtr;
+ if (mirandaAccount){
+ tszAccountName = mirandaAccount->tszAccountName;
+ }
+ }
+
+ if(myMfAck != NULL && myMfAck->result == ACKRESULT_SUCCESS){
+
+ addMessageToDB(args->targetHandle, mirandaSendModeFlag, msgBuffer, bufSize, targetHandleSzProto);
+
+ if (mode == MFENUM_SMM_ONLY_SEND){
+
+ //show notyfication popup (only in SMM_ONLY_SEND mode)
+ wchar_t* buffer = new wchar_t[1024 * sizeof(wchar_t)];
+ if (contactNameW != NULL && tszAccountName != NULL){
+ mir_sntprintf(buffer, 1024, mfTranslate(LPGENT("mirfox.message.sent"), TEXT("Message sent to %s (%s)")), contactNameW, tszAccountName);
+ } else {
+ buffer = mir_wstrdup(mfTranslate(LPGENT("mirfox.message.sent.unknown"), TEXT("Message sent")));
+ }
+
+ if(ServiceExists(MS_POPUP_ADDPOPUPCLASS)) {
+ ShowClassPopupT("MirFox_Notify", mfTranslate(LPGENT("mirfox.popup.notify.title"), TEXT("MirFox")), buffer);
+ } else {
+ PUShowMessageT(buffer, SM_NOTIFY);
+ }
+
+ delete buffer;
+
+ } else if (mode == MFENUM_SMM_SEND_AND_SHOW_MW){
+
+ //notify hook to open window
+ if (args->mirfoxDataPtr != NULL && args->mirfoxDataPtr->hhook_EventOpenMW != NULL){
+
+ OnHookOpenMvStruct* onHookOpenMv = new(OnHookOpenMvStruct);
+ onHookOpenMv->targetHandle = args->targetHandle;
+ onHookOpenMv->msgBuffer = NULL;
+ NotifyEventHooks(args->mirfoxDataPtr->hhook_EventOpenMW, (WPARAM)onHookOpenMv, (LPARAM)NULL);
+
+ } else {
+
+ logger->log(L"SMTC: ERROR1 args->mirfoxDataPtr == NULL || args->mirfoxDataPtr->hhook_EventOpenMW == NULL");
+
+ }
+
+ }
+
+ } else {
+
+ //error - show error popup
+ wchar_t* buffer = new wchar_t[1024 * sizeof(wchar_t)];
+ if (myMfAck != NULL){
+ logger->log_p(L"SMTC: ERROR - Can not send message - result = [%d] ", myMfAck->result);
+ if (myMfAck->errorDesc != NULL){
+ if (contactNameW != NULL && tszAccountName != NULL){
+ mir_sntprintf(buffer, 1024, mfTranslate(LPGENT("mirfox.message.badack.errordesc"), TEXT("Can not send message to %s (%s) - %S")), contactNameW, tszAccountName, myMfAck->errorDesc);
+ } else {
+ mir_sntprintf(buffer, 1024, mfTranslate(LPGENT("mirfox.message.badack.errordesc.unknown"), TEXT("Can not send message - %S")), myMfAck->errorDesc);
+ }
+ } else {
+ if (contactNameW != NULL && tszAccountName != NULL){
+ mir_sntprintf(buffer, 1024, mfTranslate(LPGENT("mirfox.message.badack"), TEXT("Can not send message to %s (%s)")), contactNameW, tszAccountName);
+ } else {
+ buffer = mir_wstrdup(mfTranslate(LPGENT("mirfox.message.badack.unknown"), TEXT("Can not send message - %S")));
+ }
+ }
+
+ } else {
+ logger->log(L"SMTC: ERROR - Can not send message 2");
+ if (contactNameW != NULL && tszAccountName != NULL){
+ mir_sntprintf(buffer, 1024, mfTranslate(LPGENT("mirfox.message.noack"), TEXT("Can not send message to %s (%s)")), contactNameW, tszAccountName);
+ } else {
+ buffer = mir_wstrdup(mfTranslate(LPGENT("mirfox.message.noack.unknown"), TEXT("Can not send message")));
+ }
+ }
+
+ if(ServiceExists(MS_POPUP_ADDPOPUPCLASS)) {
+ ShowClassPopupT("MirFox_Error", mfTranslate(LPGENT("mirfox.popup.error.title"), TEXT("MirFox error")), buffer);
+ } else {
+ PUShowMessageT(buffer, SM_WARNING);
+ }
+
+ delete buffer;
+
+ }
+
+ if (myMfAck != NULL){ //when we found ack, not when we exceed MAX_ACK_WAIT_COUNTER
+ if (myMfAck->errorDesc != NULL) delete myMfAck->errorDesc;
+ delete myMfAck->szModule;
+ delete myMfAck;
+ }
+ EnterCriticalSection(&ackMapCs);
+ ackMap.erase(hProcess);
+ LeaveCriticalSection(&ackMapCs);
+
+ mir_free(msgBuffer);
+
+ } else if (mode == MFENUM_SMM_ONLY_SHOW_MW){
+
+ //notify hook to open window
+ if (args->mirfoxDataPtr != NULL && args->mirfoxDataPtr->hhook_EventOpenMW != NULL){
+
+ OnHookOpenMvStruct* onHookOpenMv = new(OnHookOpenMvStruct);
+ onHookOpenMv->targetHandle = args->targetHandle;
+ //adding newline to message in Message Window, only in this mode
+ std::wstring* msgBuffer = new std::wstring(); //deleted at on_hook_OpenMW
+ msgBuffer->append(args->userActionSelection);
+ msgBuffer->append(L"\r\n");
+ onHookOpenMv->msgBuffer = msgBuffer;
+ NotifyEventHooks(args->mirfoxDataPtr->hhook_EventOpenMW, (WPARAM)onHookOpenMv, (LPARAM)NULL);
+
+ } else {
+ logger->log(L"SMTC: ERROR1 args->mirfoxDataPtr == NULL || args->mirfoxDataPtr->hhook_EventOpenMW == NULL");
+ }
+
+ }
+
+}
+
+
+int
+MirandaUtils::getMirandaSendModeFlag(char* targetHandleSzProto)
+{
+ if (CallProtoService(targetHandleSzProto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_IMSENDUTF){
+ return PREF_UTF;
+ } else {
+ return PREF_UNICODE;
+ }
+
+}
+
+
+HANDLE
+MirandaUtils::sendMessageMiranda(HANDLE hContact, int mirandaSendModeFlag, char* msgBuffer)
+{
+ return (HANDLE)CallContactService(hContact, PSS_MESSAGE, (WPARAM)mirandaSendModeFlag, (LPARAM)msgBuffer);
+}
+
+
+void
+MirandaUtils::addMessageToDB(HANDLE hContact, int mirandaSendModeFlag, char* msgBuffer, std::size_t bufSize, char* targetHandleSzProto)
+{
+ DBEVENTINFO dbei = {0};
+ dbei.cbSize = sizeof(dbei);
+ dbei.eventType = EVENTTYPE_MESSAGE;
+ dbei.flags = DBEF_SENT | ((mirandaSendModeFlag&PREF_UTF)==PREF_UTF ? DBEF_UTF : 0);
+ dbei.szModule = targetHandleSzProto;
+ dbei.timestamp = (DWORD)time(NULL);
+ dbei.cbBlob = (DWORD)bufSize;
+ dbei.pBlob = (PBYTE)msgBuffer;
+ CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei);
+}
+
+
+//http://www.shloemi.com/2012/09/solved-setforegroundwindow-win32-api-not-always-works/
+/*static*/ void
+MirandaUtils::ForceForegroundWindow(HWND hWnd)
+{
+ DWORD foreThread = GetWindowThreadProcessId(GetForegroundWindow(), NULL);
+ DWORD appThread = GetCurrentThreadId();
+
+ if (foreThread != appThread) {
+ AttachThreadInput(foreThread, appThread, true);
+ BringWindowToTop(hWnd);
+ ShowWindow(hWnd, SW_SHOW);
+ AttachThreadInput(foreThread, appThread, false);
+ } else {
+ BringWindowToTop(hWnd);
+ ShowWindow(hWnd, SW_SHOW);
+ }
+}
+
+
+/*static*/ int
+MirandaUtils::on_hook_OpenMW(WPARAM wParam, LPARAM lParam)
+{
+
+ OnHookOpenMvStruct* param = (OnHookOpenMvStruct*)wParam;
+
+ if (param->msgBuffer != NULL){
+
+ //open window and paste text
+ if (ServiceExists(MS_MSG_SENDMESSAGEW)){
+
+ char* msgBuffer = (char*)mir_wstrdup(param->msgBuffer->c_str());
+ CallServiceSync(MS_MSG_SENDMESSAGEW, (WPARAM)param->targetHandle, (LPARAM)msgBuffer);
+ mir_free(msgBuffer);
+
+ } else {
+
+ char* msgBuffer = mir_u2a(param->msgBuffer->c_str());
+ CallServiceSync(MS_MSG_SENDMESSAGE, (WPARAM)param->targetHandle, (LPARAM)msgBuffer);
+ mir_free(msgBuffer);
+
+ }
+
+ delete param->msgBuffer;
+
+ } else {
+
+ //only open window
+ CallServiceSync(MS_MSG_SENDMESSAGE, (WPARAM)param->targetHandle, LPARAM(NULL));
+
+ }
+
+ // show and focus window
+ if (db_get_b(0, PLUGIN_DB_ID, "doNotFocusWhenOpenMW", 0) == 1){
+ delete param;
+ return 0;
+ }
+
+ MessageWindowData mwd;
+ mwd.cbSize = sizeof(MessageWindowData);
+ mwd.hContact = param->targetHandle;
+ mwd.uFlags = MSG_WINDOW_UFLAG_MSG_BOTH;
+
+ MessageWindowInputData mwid;
+ mwid.cbSize = sizeof(MessageWindowInputData);
+ mwid.hContact = param->targetHandle;
+ mwid.uFlags = MSG_WINDOW_UFLAG_MSG_BOTH;
+
+ delete param;
+
+ if (!CallService(MS_MSG_GETWINDOWDATA, (WPARAM)&mwid, (LPARAM)&mwd) && mwd.hwndWindow){
+ HWND parent;
+ HWND hWnd = mwd.hwndWindow;
+ while((parent = GetParent(hWnd)) != 0) hWnd = parent; // ensure we have the top level window (need parent window for scriver & tabsrmm)
+ ForceForegroundWindow(hWnd);
+ }
+
+ return 0;
+}
+
+
+
+
+
+void
+MirandaUtils::setStatusOnAccount(ActionThreadArgStruct* args)
+{
+
+ logger->log(L"MirandaUtils::setStatusOnAccount: start");
+ int status = CallProtoService(args->accountSzModuleName, PS_GETSTATUS, 0, 0);
+ logger->log_p(L"SSOA: on account: [%S] targetHandle = [" SCNuPTR L"] at status = [%d]", args->accountSzModuleName, args->targetHandle, status);
+
+ int result = -1;
+
+ if (!(CallProtoService(args->accountSzModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_INDIVMODEMSG)){
+ result = CallProtoService(args->accountSzModuleName, PS_SETAWAYMSGW, (WPARAM)status, (LPARAM)args->userActionSelection);
+ if (result == CALLSERVICE_NOTFOUND){
+ char *szMsg = mir_u2a(args->userActionSelection);
+ result = CallProtoService(args->accountSzModuleName, PS_SETAWAYMSG, (WPARAM)status, (LPARAM)szMsg);
+ mir_free(szMsg);
+ }
+ }
+
+ MirandaAccount* mirandaAccount = args->mirfoxDataPtr->getMirandaAccountPtrBySzModuleName(args->accountSzModuleName);
+ TCHAR* tszAccountName = NULL;
+ if (mirandaAccount){
+ tszAccountName = mirandaAccount->tszAccountName;
+ }
+
+ wchar_t* buffer = new wchar_t[1024 * sizeof(wchar_t)];
+ if(result == 0){
+
+ if (tszAccountName != NULL){
+ logger->log_p(L"SSOA: Status message set on [%s]", tszAccountName);
+ mir_sntprintf(buffer, 1024, mfTranslate(LPGENT("mirfox.statusmsg.set"), TEXT("Status message set on %s")), tszAccountName);
+ } else {
+ logger->log(L"SSOA: Status message set");
+ buffer = mir_wstrdup(mfTranslate(LPGENT("mirfox.statusmsg.set.unknown"), TEXT("Status message set")));
+ }
+
+ if(ServiceExists(MS_POPUP_ADDPOPUPCLASS)) {
+ ShowClassPopupT("MirFox_Notify", mfTranslate(LPGENT("mirfox.popup.notify.title"), TEXT("MirFox")), buffer);
+ } else {
+ PUShowMessageT(buffer, SM_NOTIFY);
+ }
+
+ } else {
+
+ if (tszAccountName != NULL){
+ logger->log_p(L"SSOA: ERROR - Can not set status message 2 on [%s] - result = [%d] ", tszAccountName, result);
+ mir_sntprintf(buffer, 1024, mfTranslate(LPGENT("mirfox.statusmsg.error"), TEXT("Can not set status message on %s")), tszAccountName);
+ } else {
+ logger->log_p(L"SSOA: ERROR - Can not set status message 2 - result = [%d] ", result);
+ buffer = mir_wstrdup(mfTranslate(LPGENT("mirfox.statusmsg.error.unknown"), TEXT("Can not set status message")));
+ }
+
+ if(ServiceExists(MS_POPUP_ADDPOPUPCLASS)) {
+ ShowClassPopupT("MirFox_Error", mfTranslate(LPGENT("mirfox.popup.error.title"), TEXT("MirFox error")), buffer);
+ } else {
+ PUShowMessageT(buffer, SM_WARNING);
+ }
+
+ }
+ delete buffer;
+
+}
+
+
+
+
+int
+MirandaUtils::onProtoAck(WPARAM wParam, LPARAM lParam)
+{
+ MirandaUtils* mirandaUtils = MirandaUtils::getInstance();
+ mirandaUtils->onProtoAckOnInstance((ACKDATA*)lParam);
+ return 0;
+}
+
+
+void
+MirandaUtils::onProtoAckOnInstance(ACKDATA* ack)
+{
+
+ if (ack == NULL || ack->type != ACKTYPE_MESSAGE){
+ //we are waiting for ACKTYPE_MESSAGE ack's
+ return;
+ }
+
+ EnterCriticalSection(&ackMapCs);
+ ackMapIt = ackMap.find(ack->hProcess);
+ if (ackMapIt != ackMap.end()){
+ //we waited for this ack, save copy (only needed data) to our map. Oryginal ack object is unstable, it is probably controled not in our thread
+ logger->log_p(L"!!! ACK received acl: hContact = [" SCNuPTR L"] result = [%d] szModule = [%S] lParam = [%S]", ack->hProcess, ack->result, ack->szModule, (ack->lParam != NULL && *((char*)ack->lParam) != '\0') ? (char*)ack->lParam : "null");
+ MIRFOXACKDATA* myMfAck = new(MIRFOXACKDATA);
+ myMfAck->result = ack->result;
+ myMfAck->hContact = ack->hContact;
+ size_t len1 = strlen(ack->szModule) + 1;
+ char* myMfSzModulePtr = new char[len1];
+ strcpy_s(myMfSzModulePtr, len1, ack->szModule);
+ myMfAck->szModule = myMfSzModulePtr;
+ if (ack->lParam != NULL && *((char*)ack->lParam) != '\0'){
+ size_t len2 = strlen((char*)ack->lParam) + 1;
+ char* myMfSzLparamPtr = new char[len2];
+ strcpy_s(myMfSzLparamPtr, len2, (char*)ack->lParam);
+ myMfAck->errorDesc = myMfSzLparamPtr;
+ } else {
+ myMfAck->errorDesc = NULL;
+ }
+
+ ackMap[ack->hProcess] = myMfAck;
+ }
+ LeaveCriticalSection(&ackMapCs);
+
+}
+
+
+
+
+
+
+
+
+#define OLD_PLUGIN_DB_ID "MirfoxMiranda"
+/**
+ * function changes db module name from "MirfoxMiranda" (used before 0.3.0.0) to "Mirfox"
+ */
+void
+MirandaUtils::translateOldDBNames() {
+
+
+ //settings "clientsProfilesFilterCheckbox", "clientsProfilesFilterString"
+ int opt1KeyValue = db_get_b(0, OLD_PLUGIN_DB_ID, "clientsProfilesFilterCheckbox", 0);
+ if (opt1KeyValue != 0){
+
+ db_set_b(0, PLUGIN_DB_ID, "clientsProfilesFilterCheckbox", opt1KeyValue);
+ db_unset(0, OLD_PLUGIN_DB_ID, "clientsProfilesFilterCheckbox");
+ logger->log(L"TranslateOldDBNames: 'clientsProfilesFilterCheckbox' db entry found and moved");
+
+ } else {
+
+ logger->log(L"TranslateOldDBNames: no old settings found. returning.");
+ return;
+
+ }
+
+
+ DBVARIANT opt2Dbv = {0};
+ INT_PTR opt2Result = db_get_s(0, OLD_PLUGIN_DB_ID, "clientsProfilesFilterString", &opt2Dbv, DBVT_TCHAR);
+ if (opt2Result == 0){ //success
+
+ std::wstring clientsProfilesFilterString = opt2Dbv.pwszVal;
+ db_set_ts(0, PLUGIN_DB_ID, "clientsProfilesFilterString", clientsProfilesFilterString.c_str());
+ db_unset(0, OLD_PLUGIN_DB_ID, "clientsProfilesFilterString");
+ logger->log(L"TranslateOldDBNames: 'clientsProfilesFilterString' db entry found and moved");
+
+ }
+ db_free(&opt2Dbv);
+
+
+
+
+ //account's settings "ACCOUNTSTATE_"
+ int accountsTmpCount = 0;
+ PROTOACCOUNT **accountsTmp;
+ CallService(MS_PROTO_ENUMACCOUNTS, (WPARAM)&accountsTmpCount, (LPARAM)&accountsTmp);
+ for(int i=0; i<accountsTmpCount; i++) {
+
+ logger->log_p(L"TranslateOldDBNames: found ACCOUNT: [%s] protocol: [%S]", accountsTmp[i]->tszAccountName, accountsTmp[i]->szProtoName);
+
+ std::string mirandaAccountDBKey("ACCOUNTSTATE_");
+ mirandaAccountDBKey += accountsTmp[i]->szModuleName;
+ int keyValue = db_get_b(0, OLD_PLUGIN_DB_ID, mirandaAccountDBKey.c_str(), 0);
+ if (keyValue != 0){
+ db_set_b(0, PLUGIN_DB_ID, mirandaAccountDBKey.c_str(), keyValue);
+ db_unset(0, OLD_PLUGIN_DB_ID, mirandaAccountDBKey.c_str());
+ logger->log(L"TranslateOldDBNames: ACCOUNT db entry found and moved");
+ }
+
+ }
+
+
+ //contacts "state"
+ for (HANDLE hContact = db_find_first(); hContact; hContact = db_find_next(hContact)){
+
+ logger->log_p(L"TranslateOldDBNames: found CONTACT: [" SCNuPTR L"]", hContact);
+
+ int keyValue = db_get_b(hContact, OLD_PLUGIN_DB_ID, "state", 0);
+ if (keyValue != 0){
+ db_set_b(hContact, PLUGIN_DB_ID, "state", keyValue);
+ db_unset(hContact, OLD_PLUGIN_DB_ID, "state");
+ logger->log(L"TranslateOldDBNames: CONTACT db entry found and moved");
+ }
+
+ }
+
+
+
+ //delete db module
+ CallService(MS_DB_MODULE_DELETE, 0, (LPARAM)OLD_PLUGIN_DB_ID);
+
+}
+
diff --git a/plugins/MirFox/src/MirandaUtils.h b/plugins/MirFox/src/MirandaUtils.h new file mode 100644 index 0000000000..673a4495eb --- /dev/null +++ b/plugins/MirFox/src/MirandaUtils.h @@ -0,0 +1,125 @@ +#ifndef _MIRANDAUTILS_INC
+#define _MIRANDAUTILS_INC
+
+#include "MirfoxData.h"
+
+
+
+class MirandaUtils;
+
+
+struct ActionThreadArgStruct {
+ wchar_t* userActionSelection;
+ HANDLE targetHandle;
+ char* accountSzModuleName;
+ char userActionType;
+ char menuItemType;
+ char userButton;
+ MirandaUtils* instancePtr;
+ MirfoxData* mirfoxDataPtr;
+};
+
+
+
+
+class MirandaUtils
+{
+
+public:
+
+ static MirandaUtils *
+ getInstance()
+ {
+ if (m_pOnlyOneInstance == NULL) {
+ if (m_pOnlyOneInstance == NULL) {
+ m_pOnlyOneInstance = new MirandaUtils();
+ }
+ }
+ return m_pOnlyOneInstance;
+ }
+
+
+ void netlibRegister(void);
+ void netlibUnregister(void);
+ void netlibLog_int(const wchar_t* szText);
+ static void netlibLog(const wchar_t* szText);
+
+
+ std::wstring& getProfileName();
+
+ std::wstring& getDisplayName();
+
+ //description at MirandaUtils.cpp
+ TCHAR* mfTranslate(const TCHAR* msgCode, TCHAR* msgDefault);
+
+ void mfTranslateControl(HWND parentWindowHwnd, long controlId, const TCHAR* msgCode, TCHAR* msgDefault);
+
+ static void userActionThread(void* threadArg);
+
+ static int onProtoAck(WPARAM wParam, LPARAM lParam);
+
+ void translateOldDBNames();
+
+ struct OnHookOpenMvStruct {
+ HANDLE targetHandle;
+ std::wstring* msgBuffer;
+ };
+
+ static int on_hook_OpenMW(WPARAM wParam, LPARAM lParam);
+
+
+private:
+
+
+ static MirandaUtils * m_pOnlyOneInstance;
+
+ // private constructor
+ MirandaUtils();
+
+
+
+
+ void sendMessageToContact(ActionThreadArgStruct* args);
+
+ void sendMessage(ActionThreadArgStruct* args, MFENUM_SEND_MESSAGE_MODE mode);
+
+ int getMirandaSendModeFlag(char* targetHandleSzProto);
+
+ HANDLE sendMessageMiranda(HANDLE hContact, int mirandaSendModeFlag, char* msgBuffer);
+
+ void addMessageToDB(HANDLE hContact, int mirandaSendModeFlag, char* msgBuffer, std::size_t bufSize, char* targetHandleSzProto);
+
+ void setStatusOnAccount(ActionThreadArgStruct* args);
+
+ void onProtoAckOnInstance(ACKDATA* ack);
+
+ static void ForceForegroundWindow(HWND hWnd);
+
+
+ HANDLE netlibHandle;
+
+ std::wstring profileName;
+ std::wstring displayName;
+
+
+
+ typedef struct {
+ const char* szModule;
+ HANDLE hContact;
+ int result;
+ const char* errorDesc;
+ } MIRFOXACKDATA;
+
+ std::map<HANDLE, MIRFOXACKDATA*> ackMap;
+ std::map<HANDLE, MIRFOXACKDATA*>::iterator ackMapIt;
+ CRITICAL_SECTION ackMapCs;
+
+
+ MFLogger* logger;
+
+
+};
+
+
+
+#endif //#IFNDEF _MIRANDAUTILS_INC
diff --git a/plugins/MirFox/src/MirfoxData.cpp b/plugins/MirFox/src/MirfoxData.cpp new file mode 100644 index 0000000000..bef57abf04 --- /dev/null +++ b/plugins/MirFox/src/MirfoxData.cpp @@ -0,0 +1,607 @@ +#include "common.h"
+#include "MirfoxData.h"
+
+
+
+
+
+/*
+ * MirfoxData
+ * class functions implementation
+ */
+
+
+MirfoxData::MirfoxData(void)
+{
+ pluginState = MFENUM_PLUGIN_STATE_NEW;
+ tab1OptionsState = MFENUM_OPTIONS_NEW;
+ tab2OptionsState = MFENUM_OPTIONS_NEW;
+
+ Plugin_Terminated = false;
+ workerThreadsCount = 0;
+
+ clientsProfilesFilterCheckbox = false;
+
+ leftClickSendMode = MFENUM_SMM_ONLY_SEND;
+ rightClickSendMode = MFENUM_SMM_ONLY_SHOW_MW;
+ middleClickSendMode = MFENUM_SMM_ONLY_SEND;
+
+ processCsmId = 0;
+}
+
+MirfoxData::~MirfoxData(void)
+{
+}
+
+
+//Contacts
+
+void MirfoxData::addMirandaContact(MirandaContact* mirandaContactL){
+ mirandaContacts.push_back(mirandaContactL);
+}
+
+boost::ptr_list<MirandaContact>* MirfoxData::getMirandaContacts(){
+ return &mirandaContacts;
+}
+
+void MirfoxData::clearMirandaContacts(){
+ mirandaContacts.clear(); //all pointers are deleted by boost
+}
+
+int
+MirfoxData::updateMirandaContactState(HANDLE contactHandle, MFENUM_MIRANDACONTACT_STATE & contactState)
+{
+
+ boost::ptr_list<MirandaContact>* mirandaContactsPtr = getMirandaContacts();
+ boost::ptr_list<MirandaContact>::iterator mirandaContactsIter;
+ for (mirandaContactsIter = mirandaContactsPtr->begin(); mirandaContactsIter != mirandaContactsPtr->end(); mirandaContactsIter++){
+ if (mirandaContactsIter->contactHandle == contactHandle ){
+ mirandaContactsIter->contactState = contactState;
+ return 0;
+ }
+ }
+ return 1; //mirandaContact not found
+
+}
+
+MirandaContact*
+MirfoxData::getMirandaContactPtrByHandle(HANDLE contactHandle){
+
+ MFLogger* logger = MFLogger::getInstance();
+
+ if (contactHandle == NULL){
+ logger->log(L"getMirandaContactPtrByHandle: return NULL for HANDLE: [NULL]");
+ return NULL;
+ }
+
+ boost::ptr_list<MirandaContact>* mirandaContactsPtr = getMirandaContacts();
+ boost::ptr_list<MirandaContact>::iterator mirandaContactsIter;
+ for (mirandaContactsIter = mirandaContactsPtr->begin(); mirandaContactsIter != mirandaContactsPtr->end(); mirandaContactsIter++){
+ if (mirandaContactsIter->contactHandle == contactHandle ){
+ logger->log_p(L"getMirandaContactPtrByHandle: found MirandaContact for HANDLE: [" SCNuPTR L"]", contactHandle);
+ return mirandaContactsIter->getObjectPtr();
+ }
+ }
+
+ logger->log_p(L"getMirandaContactPtrByHandle: return NULL for HANDLE: [" SCNuPTR L"]", contactHandle);
+ return NULL; //mirandaContact not found
+
+}
+
+
+
+//Accounts
+
+void MirfoxData::addMirandaAccount(MirandaAccount* mirandaAccountL){
+ mirandaAccounts.push_back(mirandaAccountL);
+}
+
+boost::ptr_list<MirandaAccount>* MirfoxData::getMirandaAccounts(){
+ return &mirandaAccounts;
+}
+
+void MirfoxData::clearMirandaAccounts(){
+ mirandaAccounts.clear(); //all pointers are deleted by boost
+}
+
+int
+MirfoxData::updateMirandaAccountState(char* szModuleName, MFENUM_MIRANDAACCOUNT_STATE& accountState)
+{
+
+ boost::ptr_list<MirandaAccount>* mirandaAccountsPtr = getMirandaAccounts();
+ boost::ptr_list<MirandaAccount>::iterator mirandaAccountsIter;
+ for (mirandaAccountsIter = mirandaAccountsPtr->begin(); mirandaAccountsIter != mirandaAccountsPtr->end(); mirandaAccountsIter++){
+ if (strcmp(mirandaAccountsIter->szModuleName, szModuleName) == 0 ){
+ mirandaAccountsIter->accountState = accountState;
+ return 0;
+ }
+ }
+
+ return 1; //mirandaAccount not found
+}
+
+//you MUST delete returned char* (if it is not NULL)
+char*
+MirfoxData::getAccountSzModuleNameById(uint64_t id)
+{
+
+ MFLogger* logger = MFLogger::getInstance();
+
+ boost::ptr_list<MirandaAccount>* mirandaAccountsPtr = getMirandaAccounts();
+ boost::ptr_list<MirandaAccount>::iterator mirandaAccountsIter;
+ for (mirandaAccountsIter = mirandaAccountsPtr->begin(); mirandaAccountsIter != mirandaAccountsPtr->end(); mirandaAccountsIter++){
+ if (mirandaAccountsIter->id == id){
+
+ size_t len = strlen(mirandaAccountsIter->szModuleName) + 1;
+ char* returnPtr = new char[len];
+ strcpy_s(returnPtr, len, mirandaAccountsIter->szModuleName);
+ logger->log_p(L"getAccountSzModuleNameById: return: [%S] for id = [%I64u]", returnPtr, id);
+ return returnPtr;
+
+ }
+ }
+
+ logger->log_p(L"getAccountSzModuleNameById: return NULL for id = [%I64u]", id);
+ return NULL; //mirandaAccount not found
+}
+
+
+
+MirandaAccount*
+MirfoxData::getMirandaAccountPtrBySzModuleName(char* szModuleName)
+{
+
+ MFLogger* logger = MFLogger::getInstance();
+
+ if (szModuleName == NULL){
+ logger->log(L"getMirandaAccountPtrBySzModuleName: return NULL for szModuleName: [NULL]");
+ return NULL;
+ }
+
+ boost::ptr_list<MirandaAccount>* mirandaAccountsPtr = getMirandaAccounts();
+ boost::ptr_list<MirandaAccount>::iterator mirandaAccountsIter;
+ for (mirandaAccountsIter = mirandaAccountsPtr->begin(); mirandaAccountsIter != mirandaAccountsPtr->end(); mirandaAccountsIter++){
+ if (mirandaAccountsIter->szModuleName != NULL && strcmp(mirandaAccountsIter->szModuleName, szModuleName) == 0){
+ logger->log_p(L"getMirandaAccountPtrBySzModuleName: found MirandaAccount for szModuleName: [%S]", szModuleName);
+ return mirandaAccountsIter->getObjectPtr();
+ }
+ }
+
+ logger->log_p(L"getMirandaAccountPtrBySzModuleName: return NULL for szModuleName: [%S]", szModuleName);
+ return NULL; //mirandaAccount not found
+
+}
+
+
+
+//options
+
+//get ptr to clientsProfilesFilterWString std::string
+std::wstring * MirfoxData::getClientsProfilesFilterStringPtr() {
+ return & clientsProfilesFilterString;
+}
+
+void MirfoxData::normalizeClientsProfilesFilterString(std::size_t maxCSize){
+
+ boost::replace_all(clientsProfilesFilterString, L" ", L",");
+ boost::replace_all(clientsProfilesFilterString, L";", L",");
+ boost::replace_all(clientsProfilesFilterString, L"|", L",");
+ while (clientsProfilesFilterString.find(L",,") != std::wstring::npos) {
+ boost::replace_all(clientsProfilesFilterString, L",,", L",");
+ }
+
+ if (clientsProfilesFilterString.size() + 1 > maxCSize){
+ clientsProfilesFilterString.resize(maxCSize);
+ }
+
+}
+
+
+
+void
+MirfoxData::initializeMirfoxData()
+{
+
+ initializeMirandaAccounts(); //must be before initializeMirandaContacts
+ initializeMirandaContacts();
+ initializeOptions();
+
+}
+
+
+
+
+
+/*static*/ bool
+MirfoxData::shouldProtoBeActiveByName(std::string protoName)
+{
+ if (
+ boost::iequals("ExchangeRates", protoName)
+ || boost::iequals("mTV", protoName)
+ || boost::iequals("Quotes", protoName)
+ || boost::iequals("Weather", protoName)
+ || boost::iequals("GmailMNotifier", protoName)
+ || boost::iequals("RSSNews", protoName)
+ || boost::iequals("PING", protoName)
+ || boost::iequals("WorldTime", protoName)
+ || boost::iequals("NIM_Contact", protoName)
+ || boost::iequals("POP3", protoName)
+ || boost::iequals("webview", protoName)
+ || boost::iequals("YAMN", protoName)
+ || boost::iequals("lotusnotify", protoName)
+ || boost::iequals("webinfo", protoName)
+ || boost::iequals("infofromweb", protoName)
+ ){
+ return false;
+ }
+
+ return true;
+}
+
+//return 1 if on, 2 if off
+int
+MirfoxData::getAccountDefaultState(MirandaAccount* account)
+{
+ if (account == NULL){
+ return 2;
+ }
+
+ if (shouldProtoBeActiveByName(account->szProtoName)){
+ return 1;
+ } else {
+ return 2;
+ }
+}
+
+//return 1 if on, 2 if off
+int
+MirfoxData::getContactDefaultState(MirandaContact* contact)
+{
+
+ MFLogger* logger = MFLogger::getInstance();
+
+ if (contact == NULL){
+ return 2;
+ }
+
+ if (contact->mirandaAccountPtr == NULL){
+ return 2;
+ }
+
+ if (contact->mirandaAccountPtr->szProtoName == NULL){
+ return 2;
+ }
+
+ if (!shouldProtoBeActiveByName(contact->mirandaAccountPtr->szProtoName)){
+ return 2;
+ }
+
+ if (db_get_b(contact->contactHandle, "CList", "Hidden", 0) == 1 ||
+ db_get_b(contact->contactHandle, "CList", "NotOnList", 0) == 1 ){
+ return 2;
+ }
+
+ return 1;
+
+}
+
+
+void
+MirfoxData::initializeMirandaAccounts()
+{
+
+ clearMirandaAccounts();
+
+ int accountsCount = 0;
+ PROTOACCOUNT **accounts;
+
+ //get accounts from Miranda by CallService MS_PROTO_ENUMACCOUNTS
+ CallService(MS_PROTO_ENUMACCOUNTS, (WPARAM)&accountsCount, (LPARAM)&accounts);
+
+ uint64_t protocolId = 1;
+
+ for(int i=0; i<accountsCount; i++) {
+
+ //checking account
+ if(accounts[i]->bIsEnabled == 0){
+ continue;
+ }
+ if(accounts[i]->bDynDisabled != 0){
+ continue;
+ }
+
+ //add to list
+ MirandaAccount* mirandaAccountItemPtr = new MirandaAccount(
+ protocolId,
+ accounts[i]->szModuleName,
+ accounts[i]->tszAccountName,
+ accounts[i]->szProtoName,
+ accounts[i]->iOrder
+ );
+
+ MFLogger* logger = MFLogger::getInstance();
+ logger->log_p(L"initializeMirandaAccounts: tszAccountName: [%s] protocol: [%S]", accounts[i]->tszAccountName, accounts[i]->szProtoName );
+
+ protocolId++;
+
+ std::string mirandaAccountDBKey("ACCOUNTSTATE_");
+ mirandaAccountDBKey += accounts[i]->szModuleName;
+
+ int keyValue = db_get_b(0, PLUGIN_DB_ID, mirandaAccountDBKey.c_str(), 0);
+ if (keyValue == 1 || keyValue == 2){
+ //setting exist
+ if (keyValue == 1){
+ mirandaAccountItemPtr->accountState = MFENUM_MIRANDAACCOUNT_STATE_ON; //1
+ } else {
+ mirandaAccountItemPtr->accountState = MFENUM_MIRANDAACCOUNT_STATE_OFF; //2
+ }
+ } else {
+ //setting does not exist, or is invalid -> save default setting (1 - ON)
+ if (MirfoxData::getAccountDefaultState(mirandaAccountItemPtr) == 1){ //on = 1
+ mirandaAccountItemPtr->accountState = MFENUM_MIRANDAACCOUNT_STATE_ON; //1
+ db_set_b(0, PLUGIN_DB_ID, mirandaAccountDBKey.c_str(), 1);
+ } else { //off = 2
+ mirandaAccountItemPtr->accountState = MFENUM_MIRANDAACCOUNT_STATE_OFF; //2
+ db_set_b(0, PLUGIN_DB_ID, mirandaAccountDBKey.c_str(), 2);
+ }
+ }
+
+ addMirandaAccount(mirandaAccountItemPtr);
+
+ }
+
+ //TODO - sort by mirandaAccount.displayOrder
+
+}
+
+void MirfoxData::initializeMirandaContacts()
+{
+
+ MFLogger* logger = MFLogger::getInstance();
+
+ //clean data
+ clearMirandaContacts();
+
+
+ //get contects from miranda
+ for (HANDLE hContact = db_find_first(); hContact; hContact = db_find_next(hContact)){
+ //add to list
+ MirandaContact* mirandaContactItemPtr = new MirandaContact(
+ hContact //handle to contact in miranda
+ );
+ addMirandaContact(mirandaContactItemPtr);
+ }
+
+
+ boost::ptr_list<MirandaContact>* mirandaContactsPtr = getMirandaContacts();
+ boost::ptr_list<MirandaContact>::iterator mirandaContactsIter;
+
+
+ //determine contact's account
+ for (mirandaContactsIter = mirandaContactsPtr->begin(); mirandaContactsIter != mirandaContactsPtr->end(); mirandaContactsIter++){
+
+ logger->log_p(L"initializeMirandaContacts: try to get account for hContact = [" SCNuPTR L"]", mirandaContactsIter->contactHandle);
+ char* szModuleName = (char*)CallService(MS_PROTO_GETCONTACTBASEACCOUNT, (WPARAM)(mirandaContactsIter->contactHandle), 0);
+ if (szModuleName == NULL){
+ continue; //mirandaContactsIter->mirandaAccountPtr will be NULL
+ }
+ mirandaContactsIter->mirandaAccountPtr = getMirandaAccountPtrBySzModuleName(szModuleName);
+
+ }
+
+
+ //determine contact's name
+ for (mirandaContactsIter = mirandaContactsPtr->begin(); mirandaContactsIter != mirandaContactsPtr->end(); mirandaContactsIter++){
+
+ logger->log_p(L"initializeMirandaContacts: try to get name for hContact = [" SCNuPTR L"]", mirandaContactsIter->contactHandle);
+
+ if (mirandaContactsIter->mirandaAccountPtr != NULL){
+
+ if ( strcmp(mirandaContactsIter->mirandaAccountPtr->szProtoName, "Twitter") == 0){
+ //hack for Twitter protocol
+
+ DBVARIANT dbv;
+ if (!db_get_s(mirandaContactsIter->contactHandle, mirandaContactsIter->mirandaAccountPtr->szModuleName, "Username", &dbv, DBVT_WCHAR)) {
+ mirandaContactsIter->contactNameW = std::wstring(dbv.pwszVal);
+ db_free(&dbv);
+ }
+
+ } else {
+ //standard miranda way for another protocols
+
+ mirandaContactsIter->contactNameW =
+ (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)mirandaContactsIter->contactHandle, GCDNF_TCHAR);
+ //get contact's display name from clist
+
+ }
+
+ }
+
+ if (mirandaContactsIter->contactNameW.size() == 0){
+ //last chance (if some hack didn't work or mirandaContactsIter->mirandaAccountPtr is NULL)
+ mirandaContactsIter->contactNameW =
+ (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)mirandaContactsIter->contactHandle, GCDNF_TCHAR);
+ //get contact's display name from clist
+ }
+
+ logger->log_p(L"initializeMirandaContacts: got name for hContact = [" SCNuPTR L"] is: [%s]", mirandaContactsIter->contactHandle,
+ &(mirandaContactsIter->contactNameW)==NULL ? L"<null>" : mirandaContactsIter->contactNameW.c_str());
+
+ }
+
+
+ //determine contact's state
+ for (mirandaContactsIter = mirandaContactsPtr->begin(); mirandaContactsIter != mirandaContactsPtr->end(); mirandaContactsIter++){
+
+ logger->log_p(L"initializeMirandaContacts: try to get state for hContact = [" SCNuPTR L"]", mirandaContactsIter->contactHandle);
+
+ int keyValue = db_get_b(mirandaContactsIter->contactHandle, PLUGIN_DB_ID, "state", 0);
+ if (keyValue == 1 || keyValue == 2){
+ //setting exist
+ if (keyValue == 1){
+ mirandaContactsIter->contactState = MFENUM_MIRANDACONTACT_STATE_ON; //1
+ } else {
+ mirandaContactsIter->contactState = MFENUM_MIRANDACONTACT_STATE_OFF; //2
+ }
+ } else {
+ //setting does not exist, or is invalid -> save default setting (1 - ON)
+ if (MirfoxData::getContactDefaultState(mirandaContactsIter->getObjectPtr()) == 1){ //on = 1
+ mirandaContactsIter->contactState = MFENUM_MIRANDACONTACT_STATE_ON; //1
+ db_set_b(mirandaContactsIter->contactHandle, PLUGIN_DB_ID, "state", 1);
+ } else { //off = 2
+ mirandaContactsIter->contactState = MFENUM_MIRANDACONTACT_STATE_OFF; //2
+ db_set_b(mirandaContactsIter->contactHandle, PLUGIN_DB_ID, "state", 2);
+ }
+ }
+
+ }
+
+
+
+}
+
+
+
+
+
+void MirfoxData::initializeOptions()
+{
+
+ //clientsProfilesFilterCheckbox
+ int opt1KeyValue = db_get_b(0, PLUGIN_DB_ID, "clientsProfilesFilterCheckbox", 0);
+ if (opt1KeyValue == 1 || opt1KeyValue == 2){
+ //setting exist
+ if (opt1KeyValue == 1){
+ setClientsProfilesFilterCheckbox(true); //1
+ } else {
+ setClientsProfilesFilterCheckbox(false); //2
+ }
+ } else {
+ //setting does not exist, or is invalid -> save default setting (2 - false)
+ setClientsProfilesFilterCheckbox(false); //2
+ db_set_b(0, PLUGIN_DB_ID, "clientsProfilesFilterCheckbox", 2);
+ }
+
+
+ //clientsProfilesFilterString
+ DBVARIANT opt2Dbv = {0};
+ INT_PTR opt2Result = db_get_s(0, PLUGIN_DB_ID, "clientsProfilesFilterString", &opt2Dbv, DBVT_TCHAR);
+ if (opt2Result == 0){ //success
+ //option exists in DB, get value
+ (* getClientsProfilesFilterStringPtr()) = opt2Dbv.pwszVal;
+ } else {
+ //option not exists in DB, set default value
+ (* getClientsProfilesFilterStringPtr()) = L"";
+ db_set_ts(0, PLUGIN_DB_ID, "clientsProfilesFilterString", getClientsProfilesFilterStringPtr()->c_str());
+ }
+ db_free(&opt2Dbv);
+
+
+
+ int opt3KeyValue = db_get_b(0, PLUGIN_DB_ID, "leftClickSendMode", 0);
+ if (opt3KeyValue == MFENUM_SMM_ONLY_SEND || opt3KeyValue == MFENUM_SMM_SEND_AND_SHOW_MW || opt3KeyValue == MFENUM_SMM_ONLY_SHOW_MW){
+ //setting exist
+ leftClickSendMode = (MFENUM_SEND_MESSAGE_MODE)opt3KeyValue;
+ } else {
+ //setting does not exist, or is invalid -> save default setting (MFENUM_SMM_ONLY_SEND)
+ leftClickSendMode = MFENUM_SMM_ONLY_SEND;
+ db_set_b(0, PLUGIN_DB_ID, "leftClickSendMode", MFENUM_SMM_ONLY_SEND);
+ }
+
+ int opt4KeyValue = db_get_b(0, PLUGIN_DB_ID, "rightClickSendMode", 0);
+ if (opt4KeyValue == MFENUM_SMM_ONLY_SEND || opt4KeyValue == MFENUM_SMM_SEND_AND_SHOW_MW || opt4KeyValue == MFENUM_SMM_ONLY_SHOW_MW){
+ //setting exist
+ rightClickSendMode = (MFENUM_SEND_MESSAGE_MODE)opt4KeyValue;
+ } else {
+ //setting does not exist, or is invalid -> save default setting (MFENUM_SMM_SEND_AND_SHOW_MW)
+ rightClickSendMode = MFENUM_SMM_SEND_AND_SHOW_MW;
+ db_set_b(0, PLUGIN_DB_ID, "rightClickSendMode", MFENUM_SMM_SEND_AND_SHOW_MW);
+ }
+
+ int opt5KeyValue = db_get_b(0, PLUGIN_DB_ID, "middleClickSendMode", 0);
+ if (opt5KeyValue == MFENUM_SMM_ONLY_SEND || opt5KeyValue == MFENUM_SMM_SEND_AND_SHOW_MW || opt5KeyValue == MFENUM_SMM_ONLY_SHOW_MW){
+ //setting exist
+ middleClickSendMode = (MFENUM_SEND_MESSAGE_MODE)opt5KeyValue;
+ } else {
+ //setting does not exist, or is invalid -> save default setting (must be MFENUM_SMM_ONLY_SEND due to Firefox bug and crash)
+ middleClickSendMode = MFENUM_SMM_ONLY_SEND;
+ db_set_b(0, PLUGIN_DB_ID, "middleClickSendMode", MFENUM_SMM_ONLY_SEND);
+ }
+
+
+
+}
+
+
+
+void MirfoxData::releaseMirfoxData()
+{
+
+ clearMirandaContacts();
+ clearMirandaAccounts();
+
+}
+
+
+
+
+
+
+
+
+
+/*
+ * MirandaAccount
+ * class functions implementation
+ */
+
+MirandaAccount::MirandaAccount(uint64_t idL, char* szModuleNameL, TCHAR* tszAccountNameL, char* szProtoNameL, int displayOrderL)
+{
+ accountState = MFENUM_MIRANDAACCOUNT_STATE_UNKNOWN;
+ id = idL;
+ szModuleName = szModuleNameL;
+ tszAccountName = tszAccountNameL;
+ szProtoName = szProtoNameL;
+ displayOrder = displayOrderL;
+}
+
+MirandaAccount::~MirandaAccount(void)
+{
+}
+
+MirandaAccount*
+MirandaAccount::getObjectPtr()
+{
+ return this;
+}
+
+
+
+
+/*
+ * MirandaContact
+ * class functions implementation
+ */
+
+MirandaContact::MirandaContact(HANDLE contactHandleL)
+{
+ contactState = MFENUM_MIRANDACONTACT_STATE_UNKNOWN;
+ contactHandle = contactHandleL;
+ mirandaAccountPtr = NULL;
+}
+
+MirandaContact::~MirandaContact(void)
+{
+}
+
+MirandaContact*
+MirandaContact::getObjectPtr()
+{
+ return this;
+}
+
+
+
+
+
+
diff --git a/plugins/MirFox/src/MirfoxData.h b/plugins/MirFox/src/MirfoxData.h new file mode 100644 index 0000000000..3623fd2d1d --- /dev/null +++ b/plugins/MirFox/src/MirfoxData.h @@ -0,0 +1,276 @@ +#ifndef _MIRFOXDATA_INC
+#define _MIRFOXDATA_INC
+
+
+
+enum MFENUM_PLUGIN_STATE {
+ MFENUM_PLUGIN_STATE_NEW, //just started - unstable
+ MFENUM_PLUGIN_STATE_INIT, //inicializing inner data
+ MFENUM_PLUGIN_STATE_WORK, //inited and ready to work
+ MFENUM_PLUGIN_STATE_ERROR //error occured, plugin doesn't work
+};
+
+enum MFENUM_OPTIONS_STATE {
+ MFENUM_OPTIONS_NEW, //just started - unstable
+ MFENUM_OPTIONS_INIT, //inicializing inner data
+ MFENUM_OPTIONS_WORK //inited and ready to work
+};
+
+enum MFENUM_MIRANDAACCOUNT_STATE {
+ MFENUM_MIRANDAACCOUNT_STATE_UNKNOWN, //just loaded - unstable
+ MFENUM_MIRANDAACCOUNT_STATE_ON, //miranda account checked in options
+ MFENUM_MIRANDAACCOUNT_STATE_OFF //miranda account not checked in options
+};
+
+enum MFENUM_MIRANDACONTACT_STATE {
+ MFENUM_MIRANDACONTACT_STATE_UNKNOWN, //just loaded - unstable
+ MFENUM_MIRANDACONTACT_STATE_ON, //miranda contact checked in options
+ MFENUM_MIRANDACONTACT_STATE_OFF //miranda contact not checked in options
+};
+
+enum MFENUM_SEND_MESSAGE_MODE {
+ MFENUM_SMM_ONLY_SEND = 1, // 1 - only send message, show popup
+ MFENUM_SMM_SEND_AND_SHOW_MW = 2, // 2 - send message and open message window, no show popup
+ MFENUM_SMM_ONLY_SHOW_MW = 3 // 3 - only show message window with pasted message, no show popup
+};
+
+
+
+
+class MirandaAccount;
+class MirandaContact;
+
+
+class MirfoxData
+{
+
+public:
+
+ MirfoxData(void);
+ ~MirfoxData(void);
+
+
+ //Miranda handles to open message window hook procedure
+ HANDLE hhook_EventOpenMW;
+ HANDLE hhook_OpenMW;
+
+ bool volatile Plugin_Terminated;
+ int volatile workerThreadsCount;
+
+ MFENUM_SEND_MESSAGE_MODE leftClickSendMode;
+ MFENUM_SEND_MESSAGE_MODE rightClickSendMode;
+ MFENUM_SEND_MESSAGE_MODE middleClickSendMode;
+
+
+ /*
+ * getters, setters, adding
+ */
+
+ //inline
+ //get current plugin state MFENUM_PLUGINSTATE
+ MFENUM_PLUGIN_STATE getPluginState() const {
+ return pluginState;
+ }
+
+ //inline
+ //set current plugin state MFENUM_PLUGINSTATE
+ void setPluginState(MFENUM_PLUGIN_STATE pluginStateL){
+ pluginState = pluginStateL;
+ }
+
+ //inline
+ //get current tab1 options state MFENUM_OPTIONS_STATE
+ MFENUM_OPTIONS_STATE getTab1OptionsState() const {
+ return tab1OptionsState;
+ }
+
+ //inline
+ //set current tab1 options state MFENUM_OPTIONS_STATE
+ void setTab1OptionsState(MFENUM_OPTIONS_STATE tab1OptionsStateL){
+ tab1OptionsState = tab1OptionsStateL;
+ }
+
+ //inline
+ //get current tab2 options state MFENUM_OPTIONS_STATE
+ MFENUM_OPTIONS_STATE getTab2OptionsState() const {
+ return tab2OptionsState;
+ }
+
+ //inline
+ //set current tab2 options state MFENUM_OPTIONS_STATE
+ void setTab2OptionsState(MFENUM_OPTIONS_STATE tab2OptionsStateL){
+ tab2OptionsState = tab2OptionsStateL;
+ }
+
+ //inline
+ //get current tab1 options state MFENUM_OPTIONS_STATE
+ MFENUM_OPTIONS_STATE getTab3OptionsState() const {
+ return tab3OptionsState;
+ }
+
+ //inline
+ //set current tab1 options state MFENUM_OPTIONS_STATE
+ void setTab3OptionsState(MFENUM_OPTIONS_STATE tab3OptionsStateL){
+ tab3OptionsState = tab3OptionsStateL;
+ }
+
+
+ static bool shouldProtoBeActiveByName(std::string protoName);
+
+ int getAccountDefaultState(MirandaAccount* account);
+
+ int getContactDefaultState(MirandaContact* hContact);
+
+
+ //Contacts
+ //add MirandaContact item to list of MirandaContacts
+ void addMirandaContact(MirandaContact* mirandaContactL);
+
+ //get list of MirandaAContacts
+ boost::ptr_list<MirandaContact>* getMirandaContacts();
+
+ //clears list of MirandaContacts
+ void clearMirandaContacts();
+
+ //update MirandaContact's state by id
+ //return 0 - ok,
+ int updateMirandaContactState(HANDLE contactHandle, MFENUM_MIRANDACONTACT_STATE & contactState);
+
+ //return MirandaContact* by HANDLE
+ MirandaContact* getMirandaContactPtrByHandle(HANDLE contactHandle);
+
+
+
+
+ //Accounts
+ //add MirandaAccount item to list of MirandaAccounts
+ void addMirandaAccount(MirandaAccount* mirandaAccountL);
+
+ //get list of MirandaAccounts
+ boost::ptr_list<MirandaAccount>* getMirandaAccounts();
+
+ //clears list of MirandaAccounts
+ void clearMirandaAccounts();
+
+ //update MirandaAccount's state by id
+ //return 0 - ok,
+ int updateMirandaAccountState(char* szModuleName, MFENUM_MIRANDAACCOUNT_STATE& accountState);
+
+ //you MUST delete returned char* (if it is not NULL)
+ char* getAccountSzModuleNameById(uint64_t id);
+
+ //return MirandaAccount* by szModuleName
+ MirandaAccount* getMirandaAccountPtrBySzModuleName(char* szModuleName);
+
+
+ //options
+ //inline
+ //get clientsProfilesFilterCheckbox bool
+ bool getClientsProfilesFilterCheckbox() const {
+ return clientsProfilesFilterCheckbox;
+ }
+
+ //inline
+ //set clientsProfilesFilterCheckbox bool
+ void setClientsProfilesFilterCheckbox(bool clientsProfilesFilterCheckboxL){
+ clientsProfilesFilterCheckbox = clientsProfilesFilterCheckboxL;
+ }
+
+ //inline
+ //get ptr to clientsProfilesFilterWString std::string
+ std::wstring * getClientsProfilesFilterStringPtr();
+ //normalize clientsProfilesFilterString
+ void normalizeClientsProfilesFilterString(std::size_t maxCSize);
+
+
+ //id of process record in csm
+ uint16_t processCsmId;
+
+
+ /*
+ * functions
+ */
+
+ void initializeMirfoxData();
+
+
+ void releaseMirfoxData();
+
+
+private:
+
+
+ // current plugin state
+ // @see MFENUM_PLUGINSTATE
+ MFENUM_PLUGIN_STATE pluginState;
+
+ MFENUM_OPTIONS_STATE tab1OptionsState;
+ MFENUM_OPTIONS_STATE tab2OptionsState;
+ MFENUM_OPTIONS_STATE tab3OptionsState;
+
+
+ // list of pointers to MirandaAccount class instances
+ boost::ptr_list<MirandaAccount> mirandaAccounts;
+
+ //initialize accounts list
+ void initializeMirandaAccounts();
+
+
+ // list of pointers to MirandaContact class instances
+ boost::ptr_list<MirandaContact> mirandaContacts;
+
+ //initialize contacts list
+ void initializeMirandaContacts();
+
+
+ //options
+ bool clientsProfilesFilterCheckbox;
+ std::wstring clientsProfilesFilterString;
+
+ void initializeOptions();
+
+};
+
+
+
+
+class MirandaAccount
+{
+public:
+
+ MirandaAccount(uint64_t idL, char* szModuleNameL, TCHAR* tszAccountNameL, char* szProtoNameL, int displayOrderL);
+ ~MirandaAccount(void);
+ MirandaAccount* getObjectPtr();
+
+ uint64_t id; //selfgenerated id, used in sm
+ char* szModuleName; //unique string id of account
+ TCHAR* tszAccountName; //account name
+ char* szProtoName; //physical protocol name
+ int displayOrder; //presentation order - not used now
+ MFENUM_MIRANDAACCOUNT_STATE accountState; //state in options
+
+};
+
+
+class MirandaContact
+{
+public:
+
+ MirandaContact(HANDLE contactHandleL);
+ ~MirandaContact(void);
+ MirandaContact* getObjectPtr();
+
+ HANDLE contactHandle; //HANDLE to contact in miranda (unikalne)
+ std::wstring contactNameW; //presented name
+ MFENUM_MIRANDACONTACT_STATE contactState; //state in options
+ MirandaAccount* mirandaAccountPtr; //account of hContact
+
+};
+
+
+
+
+
+
+
+#endif //#ifndef _MIRFOXDATA_INC
diff --git a/plugins/MirFox/src/MirfoxMiranda.cpp b/plugins/MirFox/src/MirfoxMiranda.cpp new file mode 100644 index 0000000000..13a302996f --- /dev/null +++ b/plugins/MirFox/src/MirfoxMiranda.cpp @@ -0,0 +1,458 @@ +#include "common.h"
+#include "MirfoxMiranda.h"
+
+
+
+
+CMirfoxMiranda::CMirfoxMiranda()
+ : sharedMemoryUtils(SharedMemoryUtils::getInstance())
+ , mirandaUtils(MirandaUtils::getInstance())
+ , logger(MFLogger::getInstance())
+{
+}
+
+
+
+CMirfoxMiranda::~CMirfoxMiranda()
+{
+}
+
+
+MirfoxData&
+CMirfoxMiranda::getMirfoxData(){
+ return mirfoxData;
+}
+
+
+bool
+CMirfoxMiranda::onMirandaPluginInfoExCheck(DWORD actualMirandaVersion)
+{
+// DWORD minimalMirandaVersion = PLUGIN_MAKE_VERSION(0,8,0,0);
+// if ( actualMirandaVersion < minimalMirandaVersion) {
+// return false;
+// } else {
+ return true;
+// }
+}
+
+
+
+int
+CMirfoxMiranda::onMirandaInterfaceLoad()
+{
+
+ mirandaUtils->netlibRegister(); //for Miranda logger init
+ logger->initLogger(&MirandaUtils::netlibLog);
+ logger->set6CharsPrefix(L"MNG ");
+
+ mirandaUtils->translateOldDBNames();
+
+ mirfoxData.initializeMirfoxData();
+ logger->log(L"dll init, MirfoxData initialized");
+
+ initializeSharedMemory(mirfoxData);
+ if (mirfoxData.getPluginState() == MFENUM_PLUGIN_STATE_ERROR){
+ return 0;
+ }
+
+ initializeMessageQueue(mirfoxData);
+ if (mirfoxData.getPluginState() == MFENUM_PLUGIN_STATE_ERROR){
+ return 0;
+ }
+
+ mirfoxData.hhook_EventOpenMW = CreateHookableEvent("MirFox/OpenMW");
+ mirfoxData.hhook_OpenMW = HookEvent("MirFox/OpenMW", MirandaUtils::on_hook_OpenMW);
+
+ commitSharedMemory();
+
+
+ return 0;
+}
+
+
+int
+CMirfoxMiranda::onMirandaInterfaceUnload()
+{
+
+ UnhookEvent(mirfoxData.hhook_OpenMW);
+ DestroyHookableEvent(mirfoxData.hhook_EventOpenMW);
+
+ unloadMessageQueue(mirfoxData.processCsmId);
+ unloadSharedMemory();
+
+ mirfoxData.releaseMirfoxData();
+
+ logger->releaseLogger();
+ mirandaUtils->netlibUnregister();
+
+ return 0;
+}
+
+
+void
+CMirfoxMiranda::initializeSharedMemory(MirfoxData& mirfoxData)
+{
+
+ //initialize CSM record and MSMs with data from mirfoxData
+ initializeSharedMemoryData(mirfoxData, sharedMemoryUtils);
+
+ if (mirfoxData.getPluginState() == MFENUM_PLUGIN_STATE_ERROR){
+ return;
+ }
+
+ //Create new thread to maintain shared memory data
+ mir_forkthread(CMirfoxMiranda::csmThread, this);
+
+}
+
+void
+CMirfoxMiranda::commitSharedMemory()
+{
+ //commitSM();
+ sharedMemoryUtils->commitSM();
+}
+
+
+void
+CMirfoxMiranda::initializeSharedMemoryData(MirfoxData& mirfoxData, SharedMemoryUtils* sharedMemoryUtils)
+{
+
+ std::wstring visableTo;
+ if (mirfoxData.getClientsProfilesFilterCheckbox()){
+ visableTo = *mirfoxData.getClientsProfilesFilterStringPtr();
+ }else{
+ visableTo = TEXT("");
+ }
+ OpenOrCreateSMReturnStruct result = sharedMemoryUtils->openOrCreateSM('M', mirandaUtils->getDisplayName(), visableTo, false);
+ logger->log_p(L"openOrCreateCSM('M') result = [%u]", result);
+
+ if(result.errorCode != 0){
+ //error
+ if (result.errorCode == -3){ //existing csm version is too high -> i'm too old
+ MessageBox(NULL,
+ MirandaUtils::getInstance()->mfTranslate(LPGENT("mirfox.msgbox.csmtooold.message"), TEXT("This MirFox (Miranda) plugin is too old. Please update it.")),
+ MirandaUtils::getInstance()->mfTranslate(LPGENT("mirfox.msgbox.csmtooold.title"), TEXT("MirFox (Miranda) - Error")),
+ MB_OK | MB_ICONWARNING );
+ }
+ if (result.errorCode == -4){ //existing csm version is too low -> sb is too old
+ MessageBox(NULL,
+ MirandaUtils::getInstance()->mfTranslate(LPGENT("mirfox.msgbox.csmtoonew.message"), TEXT("This MirFox (Miranda) plugin can not start beacouse some other MirFox component is too old. Please, check and update your MirFox components.")),
+ MirandaUtils::getInstance()->mfTranslate(LPGENT("mirfox.msgbox.csmtoonew.title"), TEXT("MirFox (Miranda) - Error")),
+ MB_OK | MB_ICONWARNING );
+ }
+ mirfoxData.setPluginState(MFENUM_PLUGIN_STATE_ERROR);
+ return;
+ } else {
+ mirfoxData.processCsmId = result.processCsmId;
+ wchar_t prefix[7];
+ wsprintf(prefix, L"MNG%d", result.processCsmId);
+ logger->set6CharsPrefix(prefix);
+ }
+
+
+ sharedMemoryUtils->resetMsmParameters();
+
+ //addOptionToSM();
+ // no options to add yet
+
+ //addTranslationToSM();
+ // no translations to add yet
+
+ //addAccountToSM();
+ boost::ptr_list<MirandaAccount>* mirandaAccountsPtr = mirfoxData.getMirandaAccounts();
+ boost::ptr_list<MirandaAccount>::iterator mirandaAccountsIter;
+ for (mirandaAccountsIter = mirandaAccountsPtr->begin(); mirandaAccountsIter != mirandaAccountsPtr->end(); mirandaAccountsIter++){
+ if (mirandaAccountsIter->accountState == MFENUM_MIRANDAACCOUNT_STATE_ON){
+ std::wstring tszAccountNameW = mirandaAccountsIter->tszAccountName;
+ sharedMemoryUtils->addAccountToSM(mirandaAccountsIter->id, tszAccountNameW);
+ }
+ }
+
+ //addGroupToSM();
+ //TODO groups support
+ std::wstring groupName = L"ROOT GROUP";
+ sharedMemoryUtils->addGroupToSM((uint64_t)1, (uint64_t)NULL, 'R', groupName);
+
+ //addContactToSM();
+ boost::ptr_list<MirandaContact>* mirandaContactsPtr = mirfoxData.getMirandaContacts();
+ boost::ptr_list<MirandaContact>::iterator mirandaContactsIter;
+ for (mirandaContactsIter = mirandaContactsPtr->begin(); mirandaContactsIter != mirandaContactsPtr->end(); mirandaContactsIter++){
+ if (mirandaContactsIter->contactState == MFENUM_MIRANDACONTACT_STATE_ON){
+ //TODO mirandaAccountHandle support
+ sharedMemoryUtils->addContactToSM((uint64_t)mirandaContactsIter->contactHandle, (uint64_t)NULL, (uint64_t)1, mirandaContactsIter->contactNameW);
+ }
+ }
+
+
+}
+
+
+
+void
+CMirfoxMiranda::unloadSharedMemory()
+{
+
+ sharedMemoryUtils->unloadSharedMemory(mirfoxData.processCsmId);
+ //all msm's will be deleted when miranda process returns
+
+}
+
+
+
+
+
+/*static*/ void
+CMirfoxMiranda::csmThread(void* threadArg)
+{
+ Thread_Push(0);
+
+ CMirfoxMiranda* mirfoxMirandaPtr = (CMirfoxMiranda*)threadArg;
+ MirfoxData* mirfoxDataPtr = &(mirfoxMirandaPtr->getMirfoxData());
+ SharedMemoryUtils* sharedMemoryUtils = SharedMemoryUtils::getInstance();
+ MirandaUtils* mirandaUtils = MirandaUtils::getInstance();
+ MFLogger* logger = MFLogger::getInstance();
+
+ mirfoxDataPtr->workerThreadsCount++;
+
+ logger->log_p(L"MirfoxMiranda::csmThread (processCsmId = [%u]) - started", mirfoxDataPtr->processCsmId);
+
+ int i = CSMTHREAD_FIRSTRUN_TIME; //first run after 10s (100 * 100ms)
+ for (;;)
+ {
+ if (i <= 0){
+ i = CSMTHREAD_NEXTRUN_TIME; //next run after 10s
+
+ logger->log_p(L"MirfoxMiranda::csmThread (processCsmId = [%u]) - checking", mirfoxDataPtr->processCsmId);
+
+ boost::interprocess::windows_shared_memory* checkedCsm =
+ sharedMemoryUtils->getSmById(sharedMemoryUtils->getCsmName(), sharedMemoryUtils->getCsmTotalSize());
+
+ // - check if our csm record is correct
+ int result = sharedMemoryUtils->checkCSM(checkedCsm, mirfoxDataPtr->processCsmId, mirandaUtils->getDisplayName());
+
+ if (result == 1){
+ //wrong record in CSM - try to recreate own record
+ logger->log_p(L"MirfoxMiranda::csmThread (old processCsmId = [%u]) - checkCSM returned 1, try to recreate record in CSM", mirfoxDataPtr->processCsmId);
+
+ mirfoxDataPtr->setPluginState(MFENUM_PLUGIN_STATE_INIT);
+
+ uint16_t unloadedMQProcessId = mirfoxDataPtr->processCsmId;
+ //refresh msm
+ mirfoxMirandaPtr->initializeSharedMemoryData(*mirfoxDataPtr, sharedMemoryUtils);
+ if (unloadedMQProcessId != mirfoxDataPtr->processCsmId){
+ //refresh miranda message queue if id changed
+ mirfoxMirandaPtr->unloadMessageQueue(unloadedMQProcessId);
+ mirfoxMirandaPtr->initializeMessageQueue(*mirfoxDataPtr);
+ }
+
+ if (mirfoxDataPtr->getPluginState() != MFENUM_PLUGIN_STATE_ERROR){
+
+ sharedMemoryUtils->commitSM();
+
+ mirfoxDataPtr->setPluginState(MFENUM_PLUGIN_STATE_WORK);
+ result = 0; //ok
+ logger->log_p(L"MirfoxMiranda::csmThread - Success of recreating own record in CSM and own MSMs. new processCsmId = [%u]", mirfoxDataPtr->processCsmId);
+
+ }
+
+ }
+
+ if (result != 0){ //can't recreate own shared memory record
+ logger->log_p(L"ERROR. CSM record data is still corrupted. goto plugin error state result: %i", result);
+ mirfoxDataPtr->setPluginState(MFENUM_PLUGIN_STATE_ERROR);
+ break; //exit thread
+ }
+
+ // - update our timestamp
+ sharedMemoryUtils->updateCsmTimestamp(*checkedCsm, mirfoxDataPtr->processCsmId);
+
+ // - delete another records with too old timestamps
+ sharedMemoryUtils->checkAnotherCsm(*checkedCsm, mirfoxDataPtr->processCsmId);
+
+ //delete checkedCsm object, clear handle
+ delete checkedCsm;
+
+ }
+
+ i--;
+ SleepEx(CSMTHREAD_TICK_TIME, TRUE); //check exit every 0,1s
+
+ //if miranda is exiting - exit this thread
+ if (Miranda_Terminated() || mirfoxDataPtr->Plugin_Terminated){
+ logger->log_p(L"MirfoxMiranda::csmThread break by Plugin_Terminated (=%d) or Miranda_Terminated()", mirfoxDataPtr->Plugin_Terminated);
+ break;
+ }
+
+ }
+
+ mirfoxDataPtr->workerThreadsCount--;
+ Thread_Pop();
+ return;
+
+}
+
+
+
+
+void
+CMirfoxMiranda::initializeMessageQueue(MirfoxData& mirfoxData)
+{
+
+ MessageQueueUtils* messageQueueUtils = MessageQueueUtils::getInstance();
+
+ //get name of message queue for this client
+ std::string mqName = messageQueueUtils->getMqName(mirfoxData.processCsmId);
+ //create own mq
+ int result = messageQueueUtils->createMessageQueue(mqName);
+ if (result > 0){
+ mirfoxData.setPluginState(MFENUM_PLUGIN_STATE_ERROR);
+ //sm will not be commited
+ return;
+ }
+
+ //Create new thread to maintain actions from message queue
+ mir_forkthread(CMirfoxMiranda::msgQueueThread, this);
+
+}
+
+void
+CMirfoxMiranda::unloadMessageQueue(uint16_t unloadedMQProcessId)
+{
+
+ MessageQueueUtils* messageQueueUtils = MessageQueueUtils::getInstance();
+ messageQueueUtils->unloadMessageQueue(unloadedMQProcessId);
+
+}
+
+
+/*static*/ void
+CMirfoxMiranda::msgQueueThread(void* threadArg)
+{
+ Thread_Push(0);
+
+ CMirfoxMiranda* mirfoxMirandaPtr = (CMirfoxMiranda*)threadArg;
+ MirfoxData* mirfoxDataPtr = &(mirfoxMirandaPtr->getMirfoxData());
+ uint16_t myProcessCsmId = mirfoxDataPtr->processCsmId;
+ MFLogger* logger = MFLogger::getInstance();
+
+ mirfoxDataPtr->workerThreadsCount++;
+
+ logger->log_p(L"MirfoxMiranda::msgQueueThread - started for processCsmId = [%u]", myProcessCsmId);
+
+ MessageQueueUtils* messageQueueUtils = MessageQueueUtils::getInstance();
+ MirandaUtils* mirandaUtils = MirandaUtils::getInstance();
+
+ char menuItemType;
+ char userActionType;
+ char userButton;
+ uint64_t targetHandle;
+ wchar_t* userActionSelection = new wchar_t[MQCONST_MQSM_TEXT_SIZEC + 1];
+
+
+ //infinite loop for listening to messages from queue
+ int i = MQTHREAD_FIRSTRUN_TIME; //first run after 0s (0 * 100ms)
+ for (;;)
+ {
+ if (i<=0){
+ i = MQTHREAD_NEXTRUN_TIME; //next run after 0,10s
+
+ if (messageQueueUtils->tryReceiveMessage(menuItemType, userActionType, userButton, targetHandle, userActionSelection, MQCONST_MQSM_TEXT_SIZEC + 1) == true){
+ //message received, variables are available
+
+ logger->log_p(L"mqThread: message received menuItemType = [%c] userActionType = [%c] userButton = [%c] targetHandle = [%I64u]",
+ menuItemType, userActionType, userButton, targetHandle);
+
+ if (menuItemType == 'B'){
+
+ //for B - one action thread per one account needed
+
+ //for all enabled accounts;
+ boost::ptr_list<MirandaAccount>* mirandaAccountsPtr = mirfoxDataPtr->getMirandaAccounts();
+ boost::ptr_list<MirandaAccount>::iterator mirandaAccountsIter;
+ for (mirandaAccountsIter = mirandaAccountsPtr->begin(); mirandaAccountsIter != mirandaAccountsPtr->end(); mirandaAccountsIter++){
+ if (mirandaAccountsIter->accountState == MFENUM_MIRANDAACCOUNT_STATE_ON){
+
+ ActionThreadArgStruct* actionThreadArgPtr = new(ActionThreadArgStruct);
+
+ actionThreadArgPtr->userActionType = userActionType;
+ actionThreadArgPtr->menuItemType = 'A';
+ actionThreadArgPtr->userButton = userButton;
+
+ actionThreadArgPtr->targetHandle = NULL;
+
+ std::size_t mnSize = strlen(mirandaAccountsIter->szModuleName) + 1;
+ char* accountSzModuleName = new char[mnSize];
+ memset(accountSzModuleName, 0, mnSize * sizeof(char));
+ strcpy_s(accountSzModuleName, mnSize, mirandaAccountsIter->szModuleName);
+ actionThreadArgPtr->accountSzModuleName = accountSzModuleName;
+
+ std::size_t uasSize = wcslen(userActionSelection) + 1;
+ actionThreadArgPtr->userActionSelection = new wchar_t[uasSize];
+ memset(actionThreadArgPtr->userActionSelection, 0, uasSize * sizeof(wchar_t));
+ wcsncpy_s(actionThreadArgPtr->userActionSelection, uasSize, userActionSelection, uasSize - 1);
+
+ actionThreadArgPtr->instancePtr = mirandaUtils;
+ actionThreadArgPtr->mirfoxDataPtr = mirfoxDataPtr;
+
+ mir_forkthread(MirandaUtils::userActionThread, actionThreadArgPtr);
+
+ }
+ }
+
+ } else {
+
+ //for A and C - one action thread needed
+
+ ActionThreadArgStruct* actionThreadArgPtr = new(ActionThreadArgStruct);
+
+ actionThreadArgPtr->userActionType = userActionType;
+ actionThreadArgPtr->menuItemType = menuItemType;
+ actionThreadArgPtr->userButton = userButton;
+
+ actionThreadArgPtr->targetHandle = (HANDLE)targetHandle;
+ if (menuItemType == 'A'){ //action on account
+ actionThreadArgPtr->accountSzModuleName = mirfoxDataPtr->getAccountSzModuleNameById(targetHandle);
+ }
+
+ std::size_t uasSize = wcslen(userActionSelection) + 1;
+ actionThreadArgPtr->userActionSelection = new wchar_t[uasSize];
+ memset(actionThreadArgPtr->userActionSelection, 0, uasSize * sizeof(wchar_t));
+ wcsncpy_s(actionThreadArgPtr->userActionSelection, uasSize, userActionSelection, uasSize - 1);
+
+ actionThreadArgPtr->instancePtr = mirandaUtils;
+ actionThreadArgPtr->mirfoxDataPtr = mirfoxDataPtr;
+
+ mir_forkthread(MirandaUtils::userActionThread, actionThreadArgPtr);
+
+ }
+
+
+ }
+
+ }
+
+ i--;
+ SleepEx(MQTHREAD_TICK_TIME, TRUE); //check exit every 0,1s
+
+ //if miranda is exiting - exit this thread
+ if (Miranda_Terminated() || mirfoxDataPtr->Plugin_Terminated){
+ logger->log_p(L"mqThread break by Plugin_Terminated (=%d) or Miranda_Terminated()", mirfoxDataPtr->Plugin_Terminated);
+ delete [] userActionSelection;
+ break;
+ }
+ if(messageQueueUtils->unloadedMQProcessId == myProcessCsmId){
+ messageQueueUtils->unloadedMQProcessId = -1;
+ logger->log_p(L"mqThread [%u]: returning. unloadedMQProcessId == myProcessCsmId", myProcessCsmId);
+ delete [] userActionSelection;
+ break;
+ }
+
+ }
+
+ mirfoxDataPtr->workerThreadsCount--;
+ Thread_Pop();
+ return;
+
+}
+
+
diff --git a/plugins/MirFox/src/MirfoxMiranda.h b/plugins/MirFox/src/MirfoxMiranda.h new file mode 100644 index 0000000000..0d78e0cfc0 --- /dev/null +++ b/plugins/MirFox/src/MirfoxMiranda.h @@ -0,0 +1,60 @@ +#ifndef _MIRFOXMIRANDA_INC
+#define _MIRFOXMIRANDA_INC
+
+#include "MirfoxData.h"
+#include "MirandaUtils.h"
+
+
+
+class CMirfoxMiranda
+{
+
+public:
+ CMirfoxMiranda();
+ ~CMirfoxMiranda();
+
+
+ //functions needed by MirandaInterface and Miranda Options
+
+ MirfoxData& getMirfoxData();
+
+
+
+ bool onMirandaPluginInfoExCheck(DWORD actualMirandaVersion);
+
+ int onMirandaInterfaceLoad();
+
+ int onMirandaInterfaceUnload();
+
+ //csm maintanance thread function (threadArg - pointer to this CMirfoxMiranda class instance)
+ static void csmThread(void* threadArg);
+
+ //message queue thread function (threadArg - pointer to this CMirfoxMiranda class instance)
+ static void msgQueueThread(void* threadArg);
+
+
+
+private:
+
+ void initializeSharedMemory(MirfoxData& mirfoxData);
+ void initializeSharedMemoryData(MirfoxData& mirfoxData, SharedMemoryUtils* sharedMemoryUtils);
+ void commitSharedMemory();
+ void unloadSharedMemory();
+
+ void initializeMessageQueue(MirfoxData& mirfoxData);
+ void unloadMessageQueue(uint16_t unloadedMQProcessId);
+
+
+
+ MirfoxData mirfoxData;
+
+ SharedMemoryUtils* sharedMemoryUtils;
+ MirandaUtils* mirandaUtils;
+
+ MFLogger* logger;
+
+};
+
+
+
+#endif //#IFNDEF _MIRFOXMIRANDA_INC
diff --git a/plugins/MirFox/src/common.cpp b/plugins/MirFox/src/common.cpp new file mode 100644 index 0000000000..3324856b04 --- /dev/null +++ b/plugins/MirFox/src/common.cpp @@ -0,0 +1 @@ +#include "common.h"
diff --git a/plugins/MirFox/src/common.h b/plugins/MirFox/src/common.h new file mode 100644 index 0000000000..d0a0c2ff5a --- /dev/null +++ b/plugins/MirFox/src/common.h @@ -0,0 +1,52 @@ +#include "MirFoxCommons_pch.h"
+
+
+#pragma comment(lib, "comctl32.lib")
+#include <commctrl.h>
+
+
+
+#define MIRANDA_VER 0x0A00
+
+
+
+//Miranda headers
+#include <win2k.h>
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_database.h>
+#include <m_langpack.h>
+#include <m_options.h>
+#include <m_clistint.h>
+#include <m_protosvc.h>
+#include <m_popup.h>
+#include <m_message.h>
+//for future use #include <m_clist.h>
+
+
+#define PLUGIN_DB_ID "MirFox"
+#define PLUGIN_OPTIONS_NAME "MirFox"
+
+
+
+
+//for MirandaUtils.h and MirfoxData.h and MirfoxMiranda.h
+#include "MirFoxCommons_logger.h"
+
+//for MirfoxMiranda
+#include "MirFoxCommons_sharedMemory.h"
+#include "MirFoxCommons_messageQueueBySM.h"
+
+//for MirandaUtils.h
+#include <iostream> //for ostringstream
+#include <sstream> //for ostringstream
+#include <locale> //for use_facet
+#include <map> //for map
+
+#include <winsock.h> //needed for m_netlib.h
+#include <m_netlib.h>
+
+//for MirfoxData.h
+#include <boost/algorithm/string.hpp> //for boost::iequals
+#include <boost/algorithm/string/replace.hpp> //for boost::replace_all
+
diff --git a/plugins/MirFox/src/lib/MirFoxCommonsDebug32.lib b/plugins/MirFox/src/lib/MirFoxCommonsDebug32.lib Binary files differnew file mode 100644 index 0000000000..baf2b0447c --- /dev/null +++ b/plugins/MirFox/src/lib/MirFoxCommonsDebug32.lib diff --git a/plugins/MirFox/src/lib/MirFoxCommonsDebug32.pdb b/plugins/MirFox/src/lib/MirFoxCommonsDebug32.pdb Binary files differnew file mode 100644 index 0000000000..c14655686d --- /dev/null +++ b/plugins/MirFox/src/lib/MirFoxCommonsDebug32.pdb diff --git a/plugins/MirFox/src/lib/MirFoxCommonsDebug64.lib b/plugins/MirFox/src/lib/MirFoxCommonsDebug64.lib Binary files differnew file mode 100644 index 0000000000..94a950db06 --- /dev/null +++ b/plugins/MirFox/src/lib/MirFoxCommonsDebug64.lib diff --git a/plugins/MirFox/src/lib/MirFoxCommonsDebug64.pdb b/plugins/MirFox/src/lib/MirFoxCommonsDebug64.pdb Binary files differnew file mode 100644 index 0000000000..f548a1a86f --- /dev/null +++ b/plugins/MirFox/src/lib/MirFoxCommonsDebug64.pdb diff --git a/plugins/MirFox/src/lib/MirFoxCommonsRelease32.lib b/plugins/MirFox/src/lib/MirFoxCommonsRelease32.lib Binary files differnew file mode 100644 index 0000000000..46b3185bff --- /dev/null +++ b/plugins/MirFox/src/lib/MirFoxCommonsRelease32.lib diff --git a/plugins/MirFox/src/lib/MirFoxCommonsRelease32.pdb b/plugins/MirFox/src/lib/MirFoxCommonsRelease32.pdb Binary files differnew file mode 100644 index 0000000000..6cfc177341 --- /dev/null +++ b/plugins/MirFox/src/lib/MirFoxCommonsRelease32.pdb diff --git a/plugins/MirFox/src/lib/MirFoxCommonsRelease64.lib b/plugins/MirFox/src/lib/MirFoxCommonsRelease64.lib Binary files differnew file mode 100644 index 0000000000..c0f3f89d7f --- /dev/null +++ b/plugins/MirFox/src/lib/MirFoxCommonsRelease64.lib diff --git a/plugins/MirFox/src/lib/MirFoxCommonsRelease64.pdb b/plugins/MirFox/src/lib/MirFoxCommonsRelease64.pdb Binary files differnew file mode 100644 index 0000000000..e45191307e --- /dev/null +++ b/plugins/MirFox/src/lib/MirFoxCommonsRelease64.pdb diff --git a/plugins/MirFox/src/lib/MirFoxCommons_logger.h b/plugins/MirFox/src/lib/MirFoxCommons_logger.h new file mode 100644 index 0000000000..20a0cc6ccc --- /dev/null +++ b/plugins/MirFox/src/lib/MirFoxCommons_logger.h @@ -0,0 +1,58 @@ +#ifndef _WSX22_UTILS_LOGGER
+#define _WSX22_UTILS_LOGGER
+
+#define PREFIX_SIZE 6
+typedef void (__cdecl *LogFunction)(const wchar_t* szText);
+
+
+/**
+ * Universal Logger
+ *
+ * Singleton pattern based on
+ * http://www.codeproject.com/KB/threads/SingletonThreadSafety.aspx
+ */
+class MFLogger
+{
+
+public:
+
+ //static method that returns only instance of MFLogger
+ //////no thread safe so use it first time from only one thread (guaranted in mirfox)
+ static MFLogger *
+ getInstance() {
+ //initialized always from one thread
+ if (m_pOnlyOneInstance == NULL) {
+ if (m_pOnlyOneInstance == NULL) {
+ m_pOnlyOneInstance = new MFLogger();
+ }
+ }
+ return m_pOnlyOneInstance;
+ }
+
+ MFLogger();
+
+ void initLogger(LogFunction logFunction_p);
+ void set6CharsPrefix(const wchar_t* prefix);
+ void releaseLogger();
+
+ void log(const wchar_t* szText);
+ void log_p(const wchar_t* szText, ...);
+ void log_d(const wchar_t* szText);
+ void log_dp(const wchar_t* szText, ...);
+
+private:
+
+ void log_int(const wchar_t* szText);
+
+ //holds one and only object of MySingleton
+ static MFLogger* m_pOnlyOneInstance;
+
+ wchar_t m_prefix[PREFIX_SIZE];
+ LogFunction logFunction;
+
+ CRITICAL_SECTION logCs;
+
+};
+
+
+#endif //#ifndef _WSX22_UTILS_LOGGER
diff --git a/plugins/MirFox/src/lib/MirFoxCommons_messageQueueBySM.h b/plugins/MirFox/src/lib/MirFoxCommons_messageQueueBySM.h new file mode 100644 index 0000000000..513b720ee7 --- /dev/null +++ b/plugins/MirFox/src/lib/MirFoxCommons_messageQueueBySM.h @@ -0,0 +1,87 @@ +#ifndef _WSX22_IPC_MESSAGEQUEUEBYSM
+#define _WSX22_IPC_MESSAGEQUEUEBYSM
+
+
+
+//message queue by shared memory related definitions
+#define MQCONST_MQSM_TEXT_SIZEC 2042 //number of wchar_t chars in message - now used sharedmemory mode
+
+#define MQTHREAD_TICK_TIME 100 // 100ms - check exit every this time
+#define MQTHREAD_FIRSTRUN_TIME 0 // MQTHREAD_FIRSTRUN_TIME * MQTHREAD_TICK_TIME = 0s - time to first run of checking message queue in mq thread (after thread start)
+#define MQTHREAD_NEXTRUN_TIME 1 // MQTHREAD_NEXTRUN_TIME * MQTHREAD_TICK_TIME = 0s - time to next run of checking message queue in mq thread
+
+
+
+#include "MirFoxCommons_logger.h"
+
+
+
+
+
+
+/**
+ * MessageQueue Utils
+ *
+ * based on Boost Shared Memory, beacouse boost message queue doesn't work between 32bit and 64bit processes (at boost 1.46)
+ *
+ * Singleton pattern based on
+ * http://www.codeproject.com/KB/threads/SingletonThreadSafety.aspx
+ */
+class MessageQueueUtils
+{
+
+public:
+
+ //constructor
+ MessageQueueUtils();
+ //destructor
+ ~MessageQueueUtils();
+
+
+
+ std::string getMqName(uint16_t processId);
+
+ //return 0 if success, >0 if error
+ int createMessageQueue(std::string mqName);
+
+ void unloadMessageQueue(uint16_t unloadedMQProcessId);
+
+ //wchar_t*& - pointer by reference
+ bool tryReceiveMessage (char& menuItemType, char& userActionType, char& userButton, uint64_t& targetHandle, wchar_t*& userActionSelection, size_t uasBuffCSize);
+
+ void sendMessage(int clientRecordId, char menuItemType, char userActionType, char userButton, uint64_t targetHandle, std::wstring userActionSelection);
+
+ uint16_t volatile unloadedMQProcessId;
+
+
+ //static method that returns only instance of SharedMemoryUtils
+ static MessageQueueUtils * getInstance()
+ {
+ //initialized always from one thread at a time
+ if (m_pOnlyOneInstance == NULL) {
+ if (m_pOnlyOneInstance == NULL) {
+ m_pOnlyOneInstance = new MessageQueueUtils();
+ }
+ }
+ return m_pOnlyOneInstance;
+ }
+
+
+private:
+
+ boost::interprocess::windows_shared_memory* volatile mqMirSm;
+
+ std::size_t getMqMirSmTotalSize();
+
+ //CRITICAL_SECTION smCs;
+ HANDLE smMutex;
+
+ //holds one and only object of MySingleton
+ static MessageQueueUtils * m_pOnlyOneInstance;
+
+ MFLogger* logger;
+
+};
+
+
+#endif //#ifndef _WSX22_IPC_MESSAGEQUEUEBYSM
diff --git a/plugins/MirFox/src/lib/MirFoxCommons_pch.h b/plugins/MirFox/src/lib/MirFoxCommons_pch.h new file mode 100644 index 0000000000..d8b53974af --- /dev/null +++ b/plugins/MirFox/src/lib/MirFoxCommons_pch.h @@ -0,0 +1,54 @@ +
+//used in: all
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+#ifndef WINVER // Allow use of features specific to Windows XP or later.
+#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
+#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
+#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
+#endif
+
+#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later.
+#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE.
+#endif
+
+#if defined( UNICODE ) && !defined( _UNICODE )
+#define _UNICODE
+#endif
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#include <stdint.h> //for [u]intNN_t types
+#ifdef _X64 // [
+# define SCNoPTR L"%I64o"
+# define SCNuPTR L"%I64u"
+# define SCNxPTR L"%I64x"
+# define SCNXPTR L"%I64X"
+#else // _X64 ][
+# define SCNoPTR L"%lo"
+# define SCNuPTR L"%lu"
+# define SCNxPTR L"%lx"
+# define SCNXPTR L"%lX"
+#endif // _X64 ]
+#include <windows.h> //for NULL
+#include <string> //for std::string, std::wstring, TEXT and _T macros, operator<<
+
+
+//used in: MirFoxCommons_messageQueueBySM.h and MirFoxCommons_sharedMemory.h
+#define BOOST_DATE_TIME_NO_LIB
+#include <boost/interprocess/windows_shared_memory.hpp>
+#include <boost/interprocess/mapped_region.hpp>
+
+//used in: MirFoxCommons_sharedMemory.h
+#include <time.h> //for time
+#include <boost/ptr_container/ptr_list.hpp> //for boost::ptr_list
+#include <boost/tokenizer.hpp> //for boost::tokenizer
+#include <boost/foreach.hpp> //for BOOST_FOREACH
+
+
diff --git a/plugins/MirFox/src/lib/MirFoxCommons_sharedMemory.h b/plugins/MirFox/src/lib/MirFoxCommons_sharedMemory.h new file mode 100644 index 0000000000..c488268ee6 --- /dev/null +++ b/plugins/MirFox/src/lib/MirFoxCommons_sharedMemory.h @@ -0,0 +1,207 @@ +#ifndef _WSX22_IPC_SHAREDMEMORY
+#define _WSX22_IPC_SHAREDMEMORY
+
+
+#include "MirFoxCommons_logger.h"
+
+
+//shared memory related definitions
+#define CSMTHREAD_TICK_TIME 100 // 100ms - check exit every this time
+#define CSMTHREAD_FIRSTRUN_TIME 100 // CSMTHREAD_FIRSTRUN_TIME * CSMTHREAD_TICK_TIME = 10s - time to first run of checking csm state in csm thread (after thread start)
+#define CSMTHREAD_NEXTRUN_TIME 100 // CSMTHREAD_NEXTRUN_TIME * CSMTHREAD_TICK_TIME = 10s - time to next run of checking csm state in csm thread
+
+#define SMUCONST_CSM_RECORD_VISABLETO_SIZEC_DEF 128
+#define SMUCONST_CSM_RECORD_DNAME_SIZEC_DEF 78
+#define SMUCONST_MSM_RECORD_DNAME_SIZEC_DEF 78
+
+
+
+class ClientInstanceClass
+{
+public:
+ std::wstring displayName; //display name
+ uint16_t recordId; //id
+};
+
+class ContactClass
+{
+public:
+ std::wstring displayName; //display name
+ uint64_t handle; //miranda HANDLE to contact (casted pointer)
+};
+
+class AccountClass
+{
+public:
+ std::wstring displayName; //display name
+ uint64_t handle; //miranda HANDLE to account (casted pointer)
+};
+
+
+
+struct OpenOrCreateSMReturnStruct {
+ int errorCode;
+ uint16_t processCsmId;
+};
+
+
+
+/**
+ * SharedMemory Utils
+ *
+ * Singleton pattern based on
+ * http://www.codeproject.com/KB/threads/SingletonThreadSafety.aspx
+ */
+class SharedMemoryUtils
+{
+
+public:
+
+
+ //constructor
+ SharedMemoryUtils();
+ //destructor
+ ~SharedMemoryUtils();
+
+
+ /**
+ * open existing or create new central shared memory
+ *
+ * type - char - 'M' - Miranda, 'F' - Firefox
+ *
+ * return OpenOrCreateSMReturnStruct
+ * .errorCode
+ * 0 - ok, and .processCsmId = id of process record in csm
+ * -2 - no more available (Empty) records in central shared memory
+ * -3 - existing csm version is too high (from checkCsmVersion)
+ * -4 - existing csm version is too low (from checkCsmVersion)
+ */
+ OpenOrCreateSMReturnStruct openOrCreateSM(char type, std::wstring& displayName, std::wstring& visableTo, bool doCommitSM);
+
+
+ int addOptionToSM(int optionID, std::wstring& optionValue);
+
+ int addTranslationToSM(int translationId, std::wstring& translationValue );
+
+ int addAccountToSM(uint64_t mirandaAccountId, std::wstring& displayName);
+
+ // group type: R - root, N - normal
+ int addGroupToSM(uint64_t mirandaGroupHandle, uint64_t parentGroupHandle, char groupType, std::wstring& displayName);
+
+ int addContactToSM(uint64_t mirandaContactHandle, uint64_t mirandaAccountHandle, uint64_t mirandaGroupHandle, std::wstring& displayName);
+
+ //call after openOrCreateSM and after creating sm thread
+ int commitSM();
+
+ //delete returned sm object after use
+ boost::interprocess::windows_shared_memory* getSmById(const char* smName, std::size_t smSize);
+
+ //returns:
+ // 0 - ok
+ // 1 - record error (state != 'W' (working) or wrong displayName)
+ // -3 - existing csm version is too high (from checkCsmVersion)
+ // -4 - existing csm version is too low (from checkCsmVersion)
+ int checkCSM(boost::interprocess::windows_shared_memory* checkedCsm, uint16_t processCsmId, std::wstring& displayNameProfile);
+
+ void updateCsmTimestamp(boost::interprocess::windows_shared_memory& updateCsm, uint16_t processCsmId);
+
+ //dla wszystkich innych rekord�w w csm w statusie W, sprawdza czy rekord w csm nie jest przeterminowany jeli tak to go usuwa
+ void checkAnotherCsm(boost::interprocess::windows_shared_memory& checkedCsm, uint16_t processCsmId);
+
+ //unload and free shared memory records and structures
+ void unloadSharedMemory(uint16_t processCsmId);
+
+ //execute before start creating MSMs
+ void resetMsmParameters();
+
+
+ ////FUNCTIONS FOR FIREFOX
+
+ //return true if any client (miranda instance) is available in csm for current firefox profile
+ bool isAnyMirandaCsmRecordAvailable(std::wstring& forThisProfileName);
+
+ //return number of records in clientInstanceNamesList, empty list as parameter
+ int getClientInstances(boost::ptr_list<ClientInstanceClass> * clientInstancesListPtr, std::wstring& forThisProfileName);
+
+ //return number of records in contactsListPtr, empty list as parameter
+ int getContacts(boost::ptr_list<ContactClass> * contactsListPtr, unsigned short clientRecordNo);
+
+ //return number of records in accountsListPtr, empty list as parameter
+ int getAccounts(boost::ptr_list<AccountClass> * accountsListPtr, unsigned short clientRecordNo);
+
+ ////FUNCTIONS FOR FIREFOX - end
+
+
+
+
+ const char* getCsmName();
+ std::string getMsmName(uint16_t id, int currentNumber);
+ std::size_t getCsmTotalSize();
+ std::size_t getMsmTotalSize();
+
+
+
+ //static method that returns only instance of SharedMemoryUtils
+ static SharedMemoryUtils * getInstance()
+ {
+ //initialized always from one thread at a time
+ if (m_pOnlyOneInstance == NULL) {
+ if (m_pOnlyOneInstance == NULL) {
+ m_pOnlyOneInstance = new SharedMemoryUtils();
+ }
+ }
+ return m_pOnlyOneInstance;
+ }
+
+
+private:
+
+ //holds one and only object of MySingleton
+ static SharedMemoryUtils* m_pOnlyOneInstance;
+
+ MFLogger* logger;
+
+
+ //global variables
+ boost::interprocess::windows_shared_memory* csm;
+ boost::ptr_list<boost::interprocess::windows_shared_memory> msmList;
+
+
+
+ bool isCsmInited(boost::interprocess::windows_shared_memory& csm);
+ void initCsm(boost::interprocess::windows_shared_memory& csm);
+
+ //return:
+ // 0 - versions match,
+ // -3 - existing csm version is too high
+ // -4 - existing csm version is too low
+ int checkCsmVersion(boost::interprocess::windows_shared_memory& csm);
+
+ uint16_t allocateRecordInCsm(boost::interprocess::windows_shared_memory& csm, char type, std::wstring& displayName, std::wstring& visableTo, bool doCommitSM);
+
+ time_t mfGetCurrentTimestamp();
+
+ int addRecordToMsm(char type, uint64_t agcHandle, uint64_t accountHandle, uint64_t groupHandle, char status, std::wstring& value);
+
+ int checkCsmRecord(boost::interprocess::windows_shared_memory& checkedCsm, uint16_t processCsmId, std::wstring& displayNameProfile);
+
+ void freeCsmRecord(boost::interprocess::windows_shared_memory& csm, uint16_t recordNo);
+
+ bool isTokenOnList(std::wstring& token, std::wstring& tokensList);
+
+ //free own record in csm
+ void unloadFromCSM(uint16_t processCsmId);
+
+ //free msm instances
+ void unloadMSMs();
+
+ uint16_t processCsmId;
+ int freeMsmRecordsCount;
+ int nextMsmNumber; //from 1
+
+
+};
+
+
+#endif //#ifndef _WSX22_IPC_SHAREDMEMORY
+
diff --git a/plugins/MirFox/src/resource.h b/plugins/MirFox/src/resource.h new file mode 100644 index 0000000000..cd73d322ad --- /dev/null +++ b/plugins/MirFox/src/resource.h @@ -0,0 +1,35 @@ +// Used by resource.rc
+
+
+#define IDD_OPT1 110
+#define IDD_OPT2 111
+#define IDD_OPT3 112
+
+#define IDI_ICON_OFF 121
+#define IDI_ICON_FF 122
+#define IDI_ICON_PN 123
+#define IDI_ICON_PE 124
+
+//@IDD_OPT1
+#define IDC1_STATIC_G1 1101
+#define IDC1_LABEL1 1102
+#define IDC1_LABEL2 1103
+#define IDC1_COMBO1 1104
+#define IDC1_LABEL3 1105
+#define IDC1_COMBO2 1106
+#define IDC1_LABEL4 1107
+#define IDC1_COMBO3 1108
+#define IDC1_STATIC_G2 1109
+#define IDC1_CHECK1 1110
+#define IDC1_EDIT1 1111
+#define IDC1_STATIC_G3 1112
+#define IDC1_STATIC_INVALIDATE 1113
+#define IDC1_BUTTON_INVALIDATE 1114
+//@IDD_OPT2
+#define IDC2_LABEL1 1201
+#define IDC2_CONTACTS_LIST 1202
+//@IDD_OPT3
+#define IDC3_STATIC_G1 1301
+#define IDC3_LABEL1 1302
+#define IDC3_PROTOCOLS_LIST 1303
+
diff --git a/plugins/MirFox/src/version.h b/plugins/MirFox/src/version.h new file mode 100644 index 0000000000..753e5f6394 --- /dev/null +++ b/plugins/MirFox/src/version.h @@ -0,0 +1,15 @@ +#define __MAJOR_VERSION 0
+#define __MINOR_VERSION 5
+#define __RELEASE_NUM 0
+#define __BUILD_NUM 0
+#define __VERSION_STRING "0.5.0.0"
+
+#define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM
+
+#define __PLUGIN_NAME "MirFox"
+#define __FILENAME "MirFox.dll"
+#define __DESCRIPTION "MirFox (Miranda NG) - part of Miranda-Firefox integration - http://wsx22.3.xpdev-hosted.com"
+#define __AUTHOR "Szymon Tokarz"
+#define __AUTHOREMAIL "wsx22@o2.pl"
+#define __AUTHORWEB "http://miranda-ng.org/"
+#define __COPYRIGHT "© 2013 Szymon Tokarz"
|