From c628a13d98fde8d2555cc6fa8628e0b575021bd4 Mon Sep 17 00:00:00 2001 From: Szymon Tokarz Date: Mon, 27 May 2013 22:29:01 +0000 Subject: 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 --- plugins/MirFox/MirFoxNG_10.vcxproj | 217 ++++++ plugins/MirFox/MirFoxNG_10.vcxproj.filters | 76 ++ .../doc/default_BuildInDll_langpack_english.txt | 85 +++ plugins/MirFox/doc/langpack_belarussian.txt | 85 +++ plugins/MirFox/doc/langpack_deutsch.txt | 84 +++ plugins/MirFox/doc/langpack_polish.txt | 85 +++ plugins/MirFox/doc/langpack_russian.txt | 85 +++ plugins/MirFox/res/option_off.ico | Bin 0 -> 318 bytes plugins/MirFox/res/option_showinff.ico | Bin 0 -> 2550 bytes plugins/MirFox/res/popup_error.ico | Bin 0 -> 1150 bytes plugins/MirFox/res/popup_notify.ico | Bin 0 -> 1150 bytes plugins/MirFox/res/resource.rc | 183 +++++ plugins/MirFox/src/MirandaInterface.cpp | 177 +++++ plugins/MirFox/src/MirandaInterface.h | 11 + plugins/MirFox/src/MirandaOptions.cpp | 814 +++++++++++++++++++++ plugins/MirFox/src/MirandaOptions.h | 10 + plugins/MirFox/src/MirandaUtils.cpp | 705 ++++++++++++++++++ plugins/MirFox/src/MirandaUtils.h | 125 ++++ plugins/MirFox/src/MirfoxData.cpp | 607 +++++++++++++++ plugins/MirFox/src/MirfoxData.h | 276 +++++++ plugins/MirFox/src/MirfoxMiranda.cpp | 458 ++++++++++++ plugins/MirFox/src/MirfoxMiranda.h | 60 ++ plugins/MirFox/src/common.cpp | 1 + plugins/MirFox/src/common.h | 52 ++ plugins/MirFox/src/lib/MirFoxCommonsDebug32.lib | Bin 0 -> 2286562 bytes plugins/MirFox/src/lib/MirFoxCommonsDebug32.pdb | Bin 0 -> 2510848 bytes plugins/MirFox/src/lib/MirFoxCommonsDebug64.lib | Bin 0 -> 2799848 bytes plugins/MirFox/src/lib/MirFoxCommonsDebug64.pdb | Bin 0 -> 2519040 bytes plugins/MirFox/src/lib/MirFoxCommonsRelease32.lib | Bin 0 -> 3481610 bytes plugins/MirFox/src/lib/MirFoxCommonsRelease32.pdb | Bin 0 -> 2494464 bytes plugins/MirFox/src/lib/MirFoxCommonsRelease64.lib | Bin 0 -> 3507872 bytes plugins/MirFox/src/lib/MirFoxCommonsRelease64.pdb | Bin 0 -> 2510848 bytes plugins/MirFox/src/lib/MirFoxCommons_logger.h | 58 ++ .../src/lib/MirFoxCommons_messageQueueBySM.h | 87 +++ plugins/MirFox/src/lib/MirFoxCommons_pch.h | 54 ++ .../MirFox/src/lib/MirFoxCommons_sharedMemory.h | 207 ++++++ plugins/MirFox/src/resource.h | 35 + plugins/MirFox/src/version.h | 15 + 38 files changed, 4652 insertions(+) create mode 100644 plugins/MirFox/MirFoxNG_10.vcxproj create mode 100644 plugins/MirFox/MirFoxNG_10.vcxproj.filters create mode 100644 plugins/MirFox/doc/default_BuildInDll_langpack_english.txt create mode 100644 plugins/MirFox/doc/langpack_belarussian.txt create mode 100644 plugins/MirFox/doc/langpack_deutsch.txt create mode 100644 plugins/MirFox/doc/langpack_polish.txt create mode 100644 plugins/MirFox/doc/langpack_russian.txt create mode 100644 plugins/MirFox/res/option_off.ico create mode 100644 plugins/MirFox/res/option_showinff.ico create mode 100644 plugins/MirFox/res/popup_error.ico create mode 100644 plugins/MirFox/res/popup_notify.ico create mode 100644 plugins/MirFox/res/resource.rc create mode 100644 plugins/MirFox/src/MirandaInterface.cpp create mode 100644 plugins/MirFox/src/MirandaInterface.h create mode 100644 plugins/MirFox/src/MirandaOptions.cpp create mode 100644 plugins/MirFox/src/MirandaOptions.h create mode 100644 plugins/MirFox/src/MirandaUtils.cpp create mode 100644 plugins/MirFox/src/MirandaUtils.h create mode 100644 plugins/MirFox/src/MirfoxData.cpp create mode 100644 plugins/MirFox/src/MirfoxData.h create mode 100644 plugins/MirFox/src/MirfoxMiranda.cpp create mode 100644 plugins/MirFox/src/MirfoxMiranda.h create mode 100644 plugins/MirFox/src/common.cpp create mode 100644 plugins/MirFox/src/common.h create mode 100644 plugins/MirFox/src/lib/MirFoxCommonsDebug32.lib create mode 100644 plugins/MirFox/src/lib/MirFoxCommonsDebug32.pdb create mode 100644 plugins/MirFox/src/lib/MirFoxCommonsDebug64.lib create mode 100644 plugins/MirFox/src/lib/MirFoxCommonsDebug64.pdb create mode 100644 plugins/MirFox/src/lib/MirFoxCommonsRelease32.lib create mode 100644 plugins/MirFox/src/lib/MirFoxCommonsRelease32.pdb create mode 100644 plugins/MirFox/src/lib/MirFoxCommonsRelease64.lib create mode 100644 plugins/MirFox/src/lib/MirFoxCommonsRelease64.pdb create mode 100644 plugins/MirFox/src/lib/MirFoxCommons_logger.h create mode 100644 plugins/MirFox/src/lib/MirFoxCommons_messageQueueBySM.h create mode 100644 plugins/MirFox/src/lib/MirFoxCommons_pch.h create mode 100644 plugins/MirFox/src/lib/MirFoxCommons_sharedMemory.h create mode 100644 plugins/MirFox/src/resource.h create mode 100644 plugins/MirFox/src/version.h (limited to 'plugins') diff --git a/plugins/MirFox/MirFoxNG_10.vcxproj b/plugins/MirFox/MirFoxNG_10.vcxproj new file mode 100644 index 0000000000..05bfaf6db6 --- /dev/null +++ b/plugins/MirFox/MirFoxNG_10.vcxproj @@ -0,0 +1,217 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + MirFox + {3E9DA555-4C7B-463C-AD5C-214073DE29D6} + MirFoxNG + + + + DynamicLibrary + true + Unicode + + + DynamicLibrary + true + Unicode + + + DynamicLibrary + false + true + Unicode + + + DynamicLibrary + false + true + Unicode + + + + + + + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\Plugins\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + true + + + $(SolutionDir)$(Configuration)\Plugins\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + true + + + $(SolutionDir)$(Configuration)64\Plugins\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + true + + + $(SolutionDir)$(Configuration)64\Plugins\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + true + + + + Level3 + Disabled + .\src\lib\;..\..\include\;..\..\..\boost\;%(AdditionalIncludeDirectories) + _DEBUG;_WINDOWS;_USERDLL;UNICODE;_UNICODE;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Use + common.h + + + true + $(ProfileDir)..\..\bin10\lib + src\lib\MirFoxCommonsDebug32.lib;%(AdditionalDependencies) + Windows + $(IntDir)$(TargetName).lib + + + ..\..\include\msapi + + + + + Level3 + Disabled + .\src\lib\;..\..\include\;..\..\..\boost\;%(AdditionalIncludeDirectories) + _DEBUG;_WINDOWS;_USERDLL;UNICODE;_UNICODE;X64;_X64;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Use + common.h + + + true + $(ProfileDir)..\..\bin10\lib + src\lib\MirFoxCommonsDebug64.lib;mir_core64.lib;Miranda64.lib;%(AdditionalDependencies) + Windows + $(IntDir)$(TargetName).lib + + + ..\..\include\msapi + _X64;%(PreprocessorDefinitions) + + + + + Level3 + MaxSpeed + true + true + .\src\lib\;..\..\include\;..\..\..\boost\;%(AdditionalIncludeDirectories) + NDEBUG;_WINDOWS;_USERDLL;UNICODE;_UNICODE;%(PreprocessorDefinitions) + MultiThreadedDLL + Use + common.h + + + true + true + true + $(ProfileDir)..\..\bin10\lib;%(AdditionalLibraryDirectories) + src\lib\MirFoxCommonsRelease32.lib;%(AdditionalDependencies) + Windows + $(IntDir)$(TargetName).lib + + + ..\..\include\msapi + + + + + Level3 + MaxSpeed + true + true + .\src\lib\;..\..\include\;..\..\..\boost\;%(AdditionalIncludeDirectories) + NDEBUG;_WINDOWS;_USERDLL;UNICODE;_UNICODE;X64;_X64;%(PreprocessorDefinitions) + MultiThreadedDLL + Use + common.h + + + true + true + true + src\lib\MirFoxCommonsRelease64.lib;mir_core64.lib;Miranda64.lib;%(AdditionalDependencies) + Windows + $(IntDir)$(TargetName).lib + $(ProfileDir)..\..\bin10\lib + + + ..\..\include\msapi + _X64;%(PreprocessorDefinitions) + + + + + + + + + .\src\lib\ + .\src\lib\ + .\src\lib\ + .\src\lib\ + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/MirFox/MirFoxNG_10.vcxproj.filters b/plugins/MirFox/MirFoxNG_10.vcxproj.filters new file mode 100644 index 0000000000..40928d5016 --- /dev/null +++ b/plugins/MirFox/MirFoxNG_10.vcxproj.filters @@ -0,0 +1,76 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Resource Files + + + Resource Files + + + + + Resource Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/plugins/MirFox/doc/default_BuildInDll_langpack_english.txt b/plugins/MirFox/doc/default_BuildInDll_langpack_english.txt new file mode 100644 index 0000000000..506d3ba55c --- /dev/null +++ b/plugins/MirFox/doc/default_BuildInDll_langpack_english.txt @@ -0,0 +1,85 @@ +#muuid {cb5d6b27-b8e0-484c-87b0-4d4691a94dee} +;============================================================ +; File: MirFox.dll +; Plugin: MirFox +; Version: 0.5.0.0 +; Authors: Szymon Tokarz +; Authors-email: wsx22@o2.pl +; Language: English +;============================================================ +[MirFox (Miranda) - part of Miranda-Firefox integration - http://wsx22.3.xpdev-hosted.com] +MirFox (Miranda) - part of Miranda-Firefox integration - http://wsx22.3.xpdev-hosted.com +;file \plugins\MirFox\src\MirandaInterface.cpp +[mirfox.popup.notify.description] +MirFox/Notification +[mirfox.popup.error.description] +MirFox/Error +;file \plugins\MirFox\src\MirandaOptions.cpp +[mirfox.options.tab1.sendtocontacts] +Send to contact action +[mirfox.options.tab1.left] +on left mouse button click +[mirfox.options.onlysend] +just send message +[mirfox.options.sendandshow] +send message and open message window +[mirfox.options.onlyshow] +show message window with pasted message +[mirfox.options.tab1.right] +on right mouse button click +[mirfox.options.tab1.middle] +on middle mouse button click\n(note: use middle mouse button to send multiple messages from Firefox) +[mirfox.options.tab1.profiles] +Show Miranda menu only in this firefox profiles (comma delimeted) +[mirfox.options.tab2.contacts] +Show this contacts in 'Send ... to' option in Firefox +[mirfox.options.tab2.allcontacts] +** All contacts ** +[mirfox.options.tab3.accounts] +Show this accounts in 'Set status message' option in Firefox +[mirfox.options.tab1] +Options +[mirfox.options.tab2] +Contacts +[mirfox.options.tab3] +Accounts +;file \plugins\MirFox\src\MirandaUtils.cpp +[mirfox.netlib.name] +MirFox log +[mirfox.message.sent] +Message sent to %s (%s) +[mirfox.message.sent.unknown] +Message sent +[mirfox.popup.notify.title] +MirFox +[mirfox.message.badack.errordesc] +Can not send message to %s (%s) - %S +[mirfox.message.badack.errordesc.unknown] +Can not send message - %S +[mirfox.message.badack] +Can not send message to %s (%s) +[mirfox.message.badack.unknown] +Can not send message +[mirfox.message.noack] +Can not send message to %s (%s) +[mirfox.message.noack.unknown] +Can not send message +[mirfox.popup.error.title] +MirFox error +[mirfox.statusmsg.set] +Status message set on %s +[mirfox.statusmsg.set.unknown] +Status message set +[mirfox.statusmsg.error] +Can not set status message on %s +[mirfox.statusmsg.error.unknown] +Can not set status message +;file \plugins\MirFox\src\MirfoxMiranda.cpp +[mirfox.msgbox.csmtooold.message] +This MirFox (Miranda) plugin is too old. Please update it. +[mirfox.msgbox.csmtooold.title] +MirFox (Miranda) - Error +[mirfox.msgbox.csmtoonew.message] +This MirFox (Miranda) plugin can not start beacouse some other MirFox component is too old. Please, check and update your MirFox components. +[mirfox.msgbox.csmtoonew.title] +MirFox (Miranda) - Error diff --git a/plugins/MirFox/doc/langpack_belarussian.txt b/plugins/MirFox/doc/langpack_belarussian.txt new file mode 100644 index 0000000000..a601c81b54 --- /dev/null +++ b/plugins/MirFox/doc/langpack_belarussian.txt @@ -0,0 +1,85 @@ +#muuid {cb5d6b27-b8e0-484c-87b0-4d4691a94dee} +;============================================================ +; File: MirFox.dll +; Plugin: MirFox +; Version: 0.5.0.0 +; Authors: Jerbifor +; Authors-email: jerbifor@tut.by +; Language: Belarussian +;============================================================ +[MirFox (Miranda) - part of Miranda-Firefox integration - http://wsx22.3.xpdev-hosted.com] +MirFox (Міранда) - частка Міранда-Firefox інтэграцыі - http://wsx22.3.xpdev-hosted.com +;file \plugins\MirFox\src\MirandaInterface.cpp +[mirfox.popup.notify.description] +MirFox/Notification +[mirfox.popup.error.description] +MirFox/Error +;file \plugins\MirFox\src\MirandaOptions.cpp +[mirfox.options.tab1.sendtocontacts] +Для таго каб адправіць +[mirfox.options.tab1.left] +пры націску левай кнопкі мышы +[mirfox.options.onlysend] +проста адправіць паведамленне +[mirfox.options.sendandshow] +адправіць і адчыніць акно гутаркі +[mirfox.options.onlyshow] +паказаць акно гутаркі з устаўленым паведамленнем +[mirfox.options.tab1.right] +пры націску правай кнопкі мышы +[mirfox.options.tab1.middle] +пры націску сярэдняй кнопкі мышы\n(нататка: выкарыстоўвайце, каб адправіць некалькі паведамленняў з Firefox) +[mirfox.options.tab1.profiles] +Паказаць Міранда меню толькі для гэтых профіляў (падзельнік коска) +[mirfox.options.tab2.contacts] +Паказаць гэтыя кантакты ў меню Firefox "Адправіць ... " +[mirfox.options.tab2.allcontacts] +** Усе кантакты ** +[mirfox.options.tab3.accounts] +Паказаць аккуант у опцыі Firefox 'Статус паведамленне' +[mirfox.options.tab1] +Опцыі +[mirfox.options.tab2] +Кантакты +[mirfox.options.tab3] +Аккуанты +;file \plugins\MirFox\src\MirandaUtils.cpp +[mirfox.netlib.name] +MirFox log +[mirfox.message.sent] +паведамленне адпраўлена для %s (%s) +[mirfox.message.sent.unknown] +паведамленне адпраўлена +[mirfox.popup.notify.title] +MirFox +[mirfox.message.badack.errordesc] +не магу адправіць паведамленне для %s (%s) - %S +[mirfox.message.badack.errordesc.unknown] +не магу адправіць паведамленне - %S +[mirfox.message.badack] +не магу адправіць паведамленне для %s (%s) +[mirfox.message.badack.unknown] +не магу адправіць паведамленне +[mirfox.message.noack] +не магу адправіць паведамленне для %s (%s) +[mirfox.message.noack.unknown] +не магу адправіць паведамленне +[mirfox.popup.error.title] +MirFox Памылка +[mirfox.statusmsg.set] +Усталёўка статусу на %s +[mirfox.statusmsg.set.unknown] +Усталёўка статусу +[mirfox.statusmsg.error] +не магу ўсталяваць статус на %s +[mirfox.statusmsg.error.unknown] +не магу ўсталяваць статус +;file \plugins\MirFox\src\MirfoxMiranda.cpp +[mirfox.msgbox.csmtooold.message] +Гэта старая версія MirFox убудовы. Калі ласка, абновіце яго. +[mirfox.msgbox.csmtooold.title] +MirFox (Міранда) - Памылка +[mirfox.msgbox.csmtoonew.message] +Гэты MirFox (Міранда) плагін не можа працаваць - іншыя кампаненты MirFox састарэлі. Калі ласка, праверце і абнавіце ваша MirFox дапаўненне. +[mirfox.msgbox.csmtoonew.title] +MirFox (Міранда) - Памылка diff --git a/plugins/MirFox/doc/langpack_deutsch.txt b/plugins/MirFox/doc/langpack_deutsch.txt new file mode 100644 index 0000000000..1e4a615775 --- /dev/null +++ b/plugins/MirFox/doc/langpack_deutsch.txt @@ -0,0 +1,84 @@ +#muuid {cb5d6b27-b8e0-484c-87b0-4d4691a94dee} +;============================================================ +; File: MirFox.dll +; Plugin: MirFox +; Version: 0.5.0.0 +; Authors: CHEF-KOCH +; Language: Deutsch +;============================================================ +[MirFox (Miranda) - part of Miranda-Firefox integration - http://wsx22.3.xpdev-hosted.com] +MirFox (Miranda IM) - ein Stück Miranda IM - Firefox Integration - http://wsx22.3.xpdev-hosted.com +;file \plugins\MirFox\src\MirandaInterface.cpp +[mirfox.popup.notify.description] +MirFox/Notification +[mirfox.popup.error.description] +MirFox/Error +;file \plugins\MirFox\src\MirandaOptions.cpp +[mirfox.options.tab1.sendtocontacts] +Send to contact action +[mirfox.options.tab1.left] +on left mouse button click +[mirfox.options.onlysend] +just send message +[mirfox.options.sendandshow] +send message and open message window +[mirfox.options.onlyshow] +show message window with pasted message +[mirfox.options.tab1.right] +on right mouse button click +[mirfox.options.tab1.middle] +on middle mouse button click\n(note: use middle mouse button to send multiple messages from Firefox) +[mirfox.options.tab1.profiles] +Zeige Miranda IM Menü nur in diesen Firefox Profilen (Komma als Trennzeichen) +[mirfox.options.tab2.contacts] +Zeige diese Kontakte in der 'Sende ... zu' Option aus Firefox heraus +[mirfox.options.tab2.allcontacts] +** Alle Kontakte ** +[mirfox.options.tab3.accounts] +Zeige diesen Account in 'Setze Statusnachricht' Option in Firefox +[mirfox.options.tab1] +Optionen +[mirfox.options.tab2] +Kontakte +[mirfox.options.tab3] +Accounts +;file \plugins\MirFox\src\MirandaUtils.cpp +[mirfox.netlib.name] +MirFox log +[mirfox.message.sent] +Message sent to %s (%s) +[mirfox.message.sent.unknown] +Message sent +[mirfox.popup.notify.title] +MirFox +[mirfox.message.badack.errordesc] +Konnte Nachricht nicht senden zu %s (%s) - %S +[mirfox.message.badack.errordesc.unknown] +Konnte Nachricht nicht senden - %S +[mirfox.message.badack] +Konnte Nachricht nicht senden zu %s (%s) +[mirfox.message.badack.unknown] +Konnte Nachricht nicht senden +[mirfox.message.noack] +Konnte Nachricht nicht senden zu %s (%s) +[mirfox.message.noack.unknown] +Konnte Nachricht nicht senden +[mirfox.popup.error.title] +MirFox Fehler +[mirfox.statusmsg.set] +Statusnachricht erfolgreich gesetzt auf %s +[mirfox.statusmsg.set.unknown] +Statusnachricht erfolgreich gesetzt +[mirfox.statusmsg.error] +Konnte Statusnachricht nicht setzen auf %s +[mirfox.statusmsg.error.unknown] +Konnte Statusnachricht nicht setzen +;file \plugins\MirFox\src\MirfoxMiranda.cpp +[mirfox.msgbox.csmtooold.message] +Dieses MirFox (Miranda IM) Plugin ist zu alt. Bitte updaten. +[mirfox.msgbox.csmtooold.title] +MirFox (Miranda IM) - Fehler +[mirfox.msgbox.csmtoonew.message] +Dieses MirFox (Miranda IM) Plugin konnte nicht gestartet werden, da andere MirFox Komponenten veraltet sind. Bitte auf MirFox Updates prüfen. +[mirfox.msgbox.csmtoonew.title] +MirFox (Miranda IM) - Fehler diff --git a/plugins/MirFox/doc/langpack_polish.txt b/plugins/MirFox/doc/langpack_polish.txt new file mode 100644 index 0000000000..fbca984881 --- /dev/null +++ b/plugins/MirFox/doc/langpack_polish.txt @@ -0,0 +1,85 @@ +#muuid {cb5d6b27-b8e0-484c-87b0-4d4691a94dee} +;============================================================ +; File: MirFox.dll +; Plugin: MirFox +; Version: 0.5.0.0 +; Authors: Szymon Tokarz +; Authors-email: wsx22@o2.pl +; Language: Polish +;============================================================ +[MirFox (Miranda) - part of Miranda-Firefox integration - http://wsx22.3.xpdev-hosted.com] +MirFox (Miranda) - plugin integrujący Miranda-Firefox - http://wsx22.3.xpdev-hosted.com +;file \plugins\MirFox\src\MirandaInterface.cpp +[mirfox.popup.notify.description] +MirFox/Informacja +[mirfox.popup.error.description] +MirFox/Błąd +;file \plugins\MirFox\src\MirandaOptions.cpp +[mirfox.options.tab1.sendtocontacts] +Wyślij do kontaktu +[mirfox.options.tab1.left] +po kliknięciu lewym przyciskiem myszy +[mirfox.options.onlysend] +tylko wyślij wiadomość +[mirfox.options.sendandshow] +wyślij wiadomość i otwórz okno wiadomości +[mirfox.options.onlyshow] +otwórz okno wiadomości i wklej wiadomość +[mirfox.options.tab1.right] +po kliknięciu prawym przyciskiem myszy +[mirfox.options.tab1.middle] +po kliknięciu środkowym przyciskiem myszy\n(używając środkowego przycisku można wysłać wiadomość wielokrotnie) +[mirfox.options.tab1.profiles] +Aktywuj MirFox tylko dla następujących profili Firefox (rozdzielone przecinkiem) +[mirfox.options.tab2.contacts] +Pokazuj następujące kontakty w menu 'wyślij do' w Firefox +[mirfox.options.tab2.allcontacts] +** Wszystkie ** +[mirfox.options.tab3.accounts] +Pokazuj następujące konta w menu 'ustaw opis' w Firefox +[mirfox.options.tab1] +Opcje +[mirfox.options.tab2] +Kontakty +[mirfox.options.tab3] +Konta +;file \plugins\MirFox\src\MirandaUtils.cpp +[mirfox.netlib.name] +MirFox log +[mirfox.message.sent] +Wiadomość wysłana do %s (%s) +[mirfox.message.sent.unknown] +Wiadomość wysłana +[mirfox.popup.notify.title] +MirFox +[mirfox.message.badack.errordesc] +Błąd przy wysyłaniu wiadomości do %s (%s) - %S +[mirfox.message.badack.errordesc.unknown] +Błąd przy wysyłaniu wiadomości - %S +[mirfox.message.badack] +Błąd przy wysyłaniu wiadomości do %s (%s) +[mirfox.message.badack.unknown] +Błąd przy wysyłaniu wiadomości +[mirfox.message.noack] +Błąd przy wysyłaniu wiadomości do %s (%s) +[mirfox.message.noack.unknown] +Błąd przy wysyłaniu wiadomości +[mirfox.popup.error.title] +MirFox - błąd +[mirfox.statusmsg.set] +Ustawiono opis dla %s +[mirfox.statusmsg.set.unknown] +Ustawiono opis +[mirfox.statusmsg.error] +Błąd przy próbie ustawienia opisu dla %s +[mirfox.statusmsg.error.unknown] +Błąd przy próbie ustawienia opisu +;file \plugins\MirFox\src\MirfoxMiranda.cpp +[mirfox.msgbox.csmtooold.message] +Ten plugin MirFox (Miranda) jest nieaktualny. Zaktualizuj go. +[mirfox.msgbox.csmtooold.title] +MirFox (Miranda) - Błąd +[mirfox.msgbox.csmtoonew.message] +Nie można uruchomić pluginu MirFox (Miranda), inny komponent MirFox jest nieaktualny. Sprawdź i zaktualizuj komponenty MirFox. +[mirfox.msgbox.csmtoonew.title] +MirFox (Miranda) - Błąd diff --git a/plugins/MirFox/doc/langpack_russian.txt b/plugins/MirFox/doc/langpack_russian.txt new file mode 100644 index 0000000000..6851ff6bfe --- /dev/null +++ b/plugins/MirFox/doc/langpack_russian.txt @@ -0,0 +1,85 @@ +#muuid {cb5d6b27-b8e0-484c-87b0-4d4691a94dee} +;============================================================ +; File: MirFox.dll +; Plugin: MirFox +; Version: 0.5.0.0 +; Authors: Jerbifor +; Authors-email: jerbifor@tut.by +; Language: Russian +;============================================================ +[MirFox (Miranda) - part of Miranda-Firefox integration - http://wsx22.3.xpdev-hosted.com] +MirFox (Миранда) - часть Миранда-Firefox интеграции - http://wsx22.3.xpdev-hosted.com +;file \plugins\MirFox\src\MirandaInterface.cpp +[mirfox.popup.notify.description] +MirFox/Notification +[mirfox.popup.error.description] +MirFox/Error +;file \plugins\MirFox\src\MirandaOptions.cpp +[mirfox.options.tab1.sendtocontacts] +Для того чтобы отправить +[mirfox.options.tab1.left] +на левую кнопку мыши, нажмите кнопку +[mirfox.options.onlysend] +просто отправить сообщение +[mirfox.options.sendandshow] +отправить и открыть окно сообщений +[mirfox.options.onlyshow] +показать окно сообщения с вставленным сообщение +[mirfox.options.tab1.right] +при нажатии правой кнопки мыши +[mirfox.options.tab1.middle] +на среднюю кнопку мыши, нажмите кнопку\n(примечание: использование средней кнопки мыши, чтобы отправить несколько сообщений из Firefox) +[mirfox.options.tab1.profiles] +Показать Миранда меню только для этих профилей (разделитель запятая) +[mirfox.options.tab2.contacts] +Показать эти контакты в меню Firefox "Отправить ... " +[mirfox.options.tab2.allcontacts] +** Все контакты ** +[mirfox.options.tab3.accounts] +Показать аккуант в опции в Firefox 'Статус сообщение' +[mirfox.options.tab1] +Опции +[mirfox.options.tab2] +Контакты +[mirfox.options.tab3] +Аккуанты +;file \plugins\MirFox\src\MirandaUtils.cpp +[mirfox.netlib.name] +MirFox log +[mirfox.message.sent] +сообщение отправлено для %s (%s) +[mirfox.message.sent.unknown] +сообщение отправлено +[mirfox.popup.notify.title] +MirFox +[mirfox.message.badack.errordesc] +не Могу отправить сообщение для %s (%s) - %S +[mirfox.message.badack.errordesc.unknown] +не Могу отправить сообщение - %S +[mirfox.message.badack] +не Могу отправить сообщение для %s (%s) +[mirfox.message.badack.unknown] +не Могу отправить сообщение +[mirfox.message.noack] +не Могу отправить сообщение для %s (%s) +[mirfox.message.noack.unknown] +не Могу отправить сообщение +[mirfox.popup.error.title] +MirFox Ошибка +[mirfox.statusmsg.set] +сообщение о установке статуса на %s +[mirfox.statusmsg.set.unknown] +сообщение о установке статуса +[mirfox.statusmsg.error] +не Могу установить статус сообщение на %s +[mirfox.statusmsg.error.unknown] +не Могу установить статус сообщение +;file \plugins\MirFox\src\MirfoxMiranda.cpp +[mirfox.msgbox.csmtooold.message] +Это старая версия MirFox плагина. Пожалуйста, обновите его. +[mirfox.msgbox.csmtooold.title] +MirFox (Миранда) - Ошибка +[mirfox.msgbox.csmtoonew.message] +Этот MirFox (Миранда) плагин не может работать - другие компоненты MirFox устарели. Пожалуйста, проверьте и обновите ваше MirFox дополнение. +[mirfox.msgbox.csmtoonew.title] +MirFox (Миранда) - Ошибка diff --git a/plugins/MirFox/res/option_off.ico b/plugins/MirFox/res/option_off.ico new file mode 100644 index 0000000000..0cb0e4c92b Binary files /dev/null and b/plugins/MirFox/res/option_off.ico differ diff --git a/plugins/MirFox/res/option_showinff.ico b/plugins/MirFox/res/option_showinff.ico new file mode 100644 index 0000000000..7147cd6bb8 Binary files /dev/null and b/plugins/MirFox/res/option_showinff.ico differ diff --git a/plugins/MirFox/res/popup_error.ico b/plugins/MirFox/res/popup_error.ico new file mode 100644 index 0000000000..5f8956218e Binary files /dev/null and b/plugins/MirFox/res/popup_error.ico differ diff --git a/plugins/MirFox/res/popup_notify.ico b/plugins/MirFox/res/popup_notify.ico new file mode 100644 index 0000000000..b4934e4e1f Binary files /dev/null and b/plugins/MirFox/res/popup_notify.ico differ diff --git a/plugins/MirFox/res/resource.rc b/plugins/MirFox/res/resource.rc new file mode 100644 index 0000000000..881a90cca5 --- /dev/null +++ b/plugins/MirFox/res/resource.rc @@ -0,0 +1,183 @@ +#include "..\src\resource.h" +#include "..\src\version.h" +#include + + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION __FILEVERSION_STRING + PRODUCTVERSION __FILEVERSION_STRING + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN +#ifdef _X64 + VALUE "FileDescription", __DESCRIPTION " (x64)" + VALUE "ProductName", __PLUGIN_NAME " (x64)" + VALUE "FileVersion", __VERSION_STRING " (x64)" + VALUE "ProductVersion", __VERSION_STRING " (x64)" +#else + VALUE "FileDescription", __DESCRIPTION + VALUE "ProductName", __PLUGIN_NAME + VALUE "FileVersion", __VERSION_STRING + VALUE "ProductVersion", __VERSION_STRING +#endif + VALUE "InternalName", __PLUGIN_NAME + VALUE "OriginalFilename", __FILENAME + VALUE "Author", __AUTHOR + VALUE "LegalCopyright", __COPYRIGHT + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END + + + + + + + + +///////////////////////////////////////////////////////////////////////////// +// Neutral (Default) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUD) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT +#pragma code_page(1250) +#endif //_WIN32 + + + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_OPT1 DIALOGEX 0, 0, 310, 230 +STYLE DS_SETFONT | WS_POPUP +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + GROUPBOX "",IDC1_STATIC_G1,17,10,275,146 + LTEXT "",IDC1_LABEL1,25,16,261,20 + LTEXT "",IDC1_LABEL2,48,37,234,10 + COMBOBOX IDC1_COMBO1,48,48,235,16,CBS_DROPDOWNLIST | WS_TABSTOP + LTEXT "",IDC1_LABEL3,48,71,234,10 + COMBOBOX IDC1_COMBO2,48,83,235,12,CBS_DROPDOWNLIST | WS_TABSTOP + LTEXT "",IDC1_LABEL4,48,110,234,30 + COMBOBOX IDC1_COMBO3,48,132,235,15,CBS_DROPDOWNLIST | WS_TABSTOP + GROUPBOX "",IDC1_STATIC_G2,17,162,275,55 + CONTROL "",IDC1_CHECK1,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,27,171,259,20 + EDITTEXT IDC1_EDIT1,41,195,242,14,ES_AUTOHSCROLL + GROUPBOX "",IDC1_STATIC_G3,19,218,273,10,NOT WS_VISIBLE + //LTEXT "Refresh firefox data",IDC1_STATIC_INVALIDATE,25,218,178,8,NOT WS_VISIBLE + //PUSHBUTTON "Refresh",IDC1_BUTTON_INVALIDATE,205,219,77,6,NOT WS_VISIBLE +END + +IDD_OPT2 DIALOGEX 0, 0, 310, 230 +STYLE DS_SETFONT | WS_POPUP +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + LTEXT "",IDC2_LABEL1,4,5,301,19 + CONTROL "",IDC2_CONTACTS_LIST,"CListControl",WS_TABSTOP | 0x1d2,4,25,302,201,WS_EX_CLIENTEDGE +END + +IDD_OPT3 DIALOGEX 0, 0, 310, 230 +STYLE DS_SETFONT | WS_POPUP +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + GROUPBOX "",IDC3_STATIC_G1,17,18,275,180 + LTEXT "",IDC3_LABEL1,23,31,261,19 + CONTROL "",IDC3_PROTOCOLS_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SORTASCENDING | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,61,52,183,126 +END + + + + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Neutral (Default) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Polish resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_PLK) +#ifdef _WIN32 +LANGUAGE LANG_POLISH, SUBLANG_DEFAULT +#pragma code_page(1250) +#endif //_WIN32 + + + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON_OFF ICON "res\\option_off.ico" +IDI_ICON_FF ICON "res\\option_showinff.ico" +IDI_ICON_PN ICON "res\\popup_notify.ico" +IDI_ICON_PE ICON "res\\popup_error.ico" +#endif // Polish resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + 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] Uywasz starszej wersji Mirandy, dla ktrej 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 * mirandaContactsPtr = mirfoxMiranda.getMirfoxData().getMirandaContacts(); + boost::ptr_list::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 obsugujca 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 * mirandaAccountsPtr = mirfoxMiranda.getMirfoxData().getMirandaAccounts(); + boost::ptr_list::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; imfTranslate(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; ilog_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 ackMap; + std::map::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* 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* mirandaContactsPtr = getMirandaContacts(); + boost::ptr_list::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* mirandaContactsPtr = getMirandaContacts(); + boost::ptr_list::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* 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* mirandaAccountsPtr = getMirandaAccounts(); + boost::ptr_list::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* mirandaAccountsPtr = getMirandaAccounts(); + boost::ptr_list::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* mirandaAccountsPtr = getMirandaAccounts(); + boost::ptr_list::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; ibIsEnabled == 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* mirandaContactsPtr = getMirandaContacts(); + boost::ptr_list::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"" : 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* 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* 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 mirandaAccounts; + + //initialize accounts list + void initializeMirandaAccounts(); + + + // list of pointers to MirandaContact class instances + boost::ptr_list 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* mirandaAccountsPtr = mirfoxData.getMirandaAccounts(); + boost::ptr_list::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* mirandaContactsPtr = mirfoxData.getMirandaContacts(); + boost::ptr_list::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* mirandaAccountsPtr = mirfoxDataPtr->getMirandaAccounts(); + boost::ptr_list::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 + + + +#define MIRANDA_VER 0x0A00 + + + +//Miranda headers +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//for future use #include + + +#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 //for ostringstream +#include //for ostringstream +#include //for use_facet +#include //for map + +#include //needed for m_netlib.h +#include + +//for MirfoxData.h +#include //for boost::iequals +#include //for boost::replace_all + diff --git a/plugins/MirFox/src/lib/MirFoxCommonsDebug32.lib b/plugins/MirFox/src/lib/MirFoxCommonsDebug32.lib new file mode 100644 index 0000000000..baf2b0447c Binary files /dev/null and b/plugins/MirFox/src/lib/MirFoxCommonsDebug32.lib differ diff --git a/plugins/MirFox/src/lib/MirFoxCommonsDebug32.pdb b/plugins/MirFox/src/lib/MirFoxCommonsDebug32.pdb new file mode 100644 index 0000000000..c14655686d Binary files /dev/null and b/plugins/MirFox/src/lib/MirFoxCommonsDebug32.pdb differ diff --git a/plugins/MirFox/src/lib/MirFoxCommonsDebug64.lib b/plugins/MirFox/src/lib/MirFoxCommonsDebug64.lib new file mode 100644 index 0000000000..94a950db06 Binary files /dev/null and b/plugins/MirFox/src/lib/MirFoxCommonsDebug64.lib differ diff --git a/plugins/MirFox/src/lib/MirFoxCommonsDebug64.pdb b/plugins/MirFox/src/lib/MirFoxCommonsDebug64.pdb new file mode 100644 index 0000000000..f548a1a86f Binary files /dev/null and b/plugins/MirFox/src/lib/MirFoxCommonsDebug64.pdb differ diff --git a/plugins/MirFox/src/lib/MirFoxCommonsRelease32.lib b/plugins/MirFox/src/lib/MirFoxCommonsRelease32.lib new file mode 100644 index 0000000000..46b3185bff Binary files /dev/null and b/plugins/MirFox/src/lib/MirFoxCommonsRelease32.lib differ diff --git a/plugins/MirFox/src/lib/MirFoxCommonsRelease32.pdb b/plugins/MirFox/src/lib/MirFoxCommonsRelease32.pdb new file mode 100644 index 0000000000..6cfc177341 Binary files /dev/null and b/plugins/MirFox/src/lib/MirFoxCommonsRelease32.pdb differ diff --git a/plugins/MirFox/src/lib/MirFoxCommonsRelease64.lib b/plugins/MirFox/src/lib/MirFoxCommonsRelease64.lib new file mode 100644 index 0000000000..c0f3f89d7f Binary files /dev/null and b/plugins/MirFox/src/lib/MirFoxCommonsRelease64.lib differ diff --git a/plugins/MirFox/src/lib/MirFoxCommonsRelease64.pdb b/plugins/MirFox/src/lib/MirFoxCommonsRelease64.pdb new file mode 100644 index 0000000000..e45191307e Binary files /dev/null and b/plugins/MirFox/src/lib/MirFoxCommonsRelease64.pdb differ 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 //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 //for NULL +#include //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 +#include + +//used in: MirFoxCommons_sharedMemory.h +#include //for time +#include //for boost::ptr_list +#include //for boost::tokenizer +#include //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 * clientInstancesListPtr, std::wstring& forThisProfileName); + + //return number of records in contactsListPtr, empty list as parameter + int getContacts(boost::ptr_list * contactsListPtr, unsigned short clientRecordNo); + + //return number of records in accountsListPtr, empty list as parameter + int getAccounts(boost::ptr_list * 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 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" -- cgit v1.2.3