From 3c0233134bc5a8e42e3a621f0a5eef2aaf487474 Mon Sep 17 00:00:00 2001 From: watcherhd Date: Thu, 17 Nov 2011 12:37:21 +0000 Subject: adding from berlios: dbx_tree, lastseen-mod, nudge, yamn git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@173 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- dbx_tree/BTree.h | 1358 ++++++++++++++ dbx_tree/BlockManager.cpp | 965 ++++++++++ dbx_tree/BlockManager.h | 401 ++++ dbx_tree/Compatibility.cpp | 866 +++++++++ dbx_tree/Compatibility.h | 65 + dbx_tree/DataBase.cpp | 374 ++++ dbx_tree/DataBase.h | 157 ++ dbx_tree/DatabaseLink.cpp | 178 ++ dbx_tree/DatabaseLink.h | 29 + dbx_tree/DirectAccess.cpp | 118 ++ dbx_tree/DirectAccess.h | 43 + dbx_tree/EncryptionManager.cpp | 241 +++ dbx_tree/EncryptionManager.h | 107 ++ dbx_tree/Entities.cpp | 1032 ++++++++++ dbx_tree/Entities.h | 299 +++ dbx_tree/Events.cpp | 986 ++++++++++ dbx_tree/Events.h | 263 +++ dbx_tree/FileAccess.cpp | 299 +++ dbx_tree/FileAccess.h | 191 ++ dbx_tree/FileBTree.h | 102 + dbx_tree/Filestructure.txt | Bin 0 -> 25894 bytes dbx_tree/Hash.cpp | 183 ++ dbx_tree/Hash.h | 29 + dbx_tree/Interface.h | 58 + dbx_tree/IterationHeap.h | 196 ++ dbx_tree/Logger.cpp | 124 ++ dbx_tree/Logger.h | 76 + dbx_tree/MREWSync.cpp | 330 ++++ dbx_tree/MREWSync.h | 55 + dbx_tree/MappedMemory.cpp | 167 ++ dbx_tree/MappedMemory.h | 47 + dbx_tree/SHA256.cpp | 301 +++ dbx_tree/SHA256.h | 49 + dbx_tree/Services.cpp | 402 ++++ dbx_tree/Services.h | 69 + dbx_tree/Settings.cpp | 1479 +++++++++++++++ dbx_tree/Settings.h | 235 +++ dbx_tree/TLS.h | 161 ++ dbx_tree/Thread.cpp | 114 ++ dbx_tree/Thread.h | 77 + dbx_tree/dbConfig.rc | 113 ++ dbx_tree/dbConfig_rc.h | 20 + dbx_tree/dbVersion.rc | 105 ++ dbx_tree/dbVersion_rc.h | 14 + dbx_tree/dbx_tree.vcproj | 1169 ++++++++++++ dbx_tree/dbx_tree_10.vcxproj | 710 +++++++ dbx_tree/dbx_tree_10.vcxproj.filters | 204 ++ dbx_tree/encryption/ARC4.cpp | 129 ++ dbx_tree/encryption/ARC4.h | 65 + dbx_tree/encryption/ARC4.vcproj | 376 ++++ dbx_tree/encryption/ARC4.vcxproj | 476 +++++ dbx_tree/encryption/ARC4.vcxproj.filters | 30 + dbx_tree/encryption/CAST128.cpp | 260 +++ dbx_tree/encryption/CAST128.h | 61 + dbx_tree/encryption/CAST128.inc | 302 +++ dbx_tree/encryption/Cast128.vcproj | 380 ++++ dbx_tree/encryption/Cast128.vcxproj | 479 +++++ dbx_tree/encryption/Cast128.vcxproj.filters | 35 + dbx_tree/encryption/Cipher.h | 180 ++ dbx_tree/encryption/HC256.cpp | 243 +++ dbx_tree/encryption/HC256.h | 66 + dbx_tree/encryption/HC256.vcproj | 376 ++++ dbx_tree/encryption/HC256.vcxproj | 476 +++++ dbx_tree/encryption/HC256.vcxproj.filters | 30 + dbx_tree/init.cpp | 83 + dbx_tree/intrinsics.h | 407 ++++ dbx_tree/inttypes.h | 305 +++ dbx_tree/lockfree_hashmap.h | 749 ++++++++ dbx_tree/lockfree_hashmultimap.h | 750 ++++++++ dbx_tree/m_dbx_tree.h | 688 +++++++ dbx_tree/savestrings_gcc.h | 127 ++ dbx_tree/sigslot.h | 2639 ++++++++++++++++++++++++++ dbx_tree/stdint.h | 247 +++ lastseen-mod/file.c | 119 ++ lastseen-mod/history.c | 347 ++++ lastseen-mod/main.c | 191 ++ lastseen-mod/menu.c | 112 ++ lastseen-mod/missed.c | 301 +++ lastseen-mod/options.c | 608 ++++++ lastseen-mod/readme_src.txt | 23 + lastseen-mod/resource.h | 98 + lastseen-mod/resource.rc | 301 +++ lastseen-mod/seen.h | 123 ++ lastseen-mod/seen_info.txt | 216 +++ lastseen-mod/seen_langpack.txt | 172 ++ lastseen-mod/seenplugin.dev | 189 ++ lastseen-mod/seenplugin.dsp | 225 +++ lastseen-mod/seenplugin.dsw | 29 + lastseen-mod/seenplugin.win | 63 + lastseen-mod/userinfo.c | 95 + lastseen-mod/utils.c | 967 ++++++++++ nudge/ChangeLog.txt | 183 ++ nudge/headers.h | 75 + nudge/include/IcoLib.h | 26 + nudge/include/m_folders.h | 284 +++ nudge/include/m_kbdnotify.h | 64 + nudge/include/m_metacontacts.h | 166 ++ nudge/include/m_msg_buttonsbar.h | 120 ++ nudge/include/m_popup.h | 318 ++++ nudge/include/m_popupw.h | 56 + nudge/include/m_toptoolbar.h | 105 ++ nudge/include/m_trigger.h | 1004 ++++++++++ nudge/include/m_uninstaller.h | 700 +++++++ nudge/include/m_updater.h | 150 ++ nudge/m_nudge.h | 10 + nudge/main.cpp | 1020 ++++++++++ nudge/main.h | 96 + nudge/miranda.ico | Bin 0 -> 3638 bytes nudge/nudge.cpp | 135 ++ nudge/nudge.dsp | 241 +++ nudge/nudge.dsw | 29 + nudge/nudge.h | 72 + nudge/nudge.vcproj | 353 ++++ nudge/nudge_10.vcxproj | 482 +++++ nudge/nudge_8.sln | 19 + nudge/nudge_8.vcproj | 368 ++++ nudge/options.cpp | 578 ++++++ nudge/options.h | 17 + nudge/resource.h | 88 + nudge/resource.rc | 370 ++++ nudge/resources/Nudge.ico | Bin 0 -> 2038 bytes nudge/resources/NudgeIRC.ico | Bin 0 -> 2038 bytes nudge/resources/NudgeMSN.ico | Bin 0 -> 2038 bytes nudge/resources/NudgeMeta.ico | Bin 0 -> 2038 bytes nudge/resources/NudgeTlen.ico | Bin 0 -> 2038 bytes nudge/resources/NudgeYahoo.ico | Bin 0 -> 2038 bytes nudge/resources/nudge msn.ico | Bin 0 -> 1406 bytes nudge/shake.cpp | 195 ++ nudge/shake.h | 27 + yamn/ChangeLog.txt | 243 +++ yamn/YAMN.dsp | 376 ++++ yamn/YAMN.dsw | 65 + yamn/YAMN.mak | 1736 +++++++++++++++++ yamn/YAMN.vcproj | 1593 ++++++++++++++++ yamn/YAMN_9.vcproj | 915 +++++++++ yamn/YAMNopts.cpp | 2 + yamn/account.cpp | 1539 +++++++++++++++ yamn/browser/badconnect.cpp | 391 ++++ yamn/browser/m_browser.h | 42 + yamn/browser/mailbrowser.cpp | 2692 +++++++++++++++++++++++++++ yamn/debug.cpp | 142 ++ yamn/debug.h | 64 + yamn/docs/InstallScript.xml | 49 + yamn/docs/YAMN-License.txt | 340 ++++ yamn/docs/YAMN-Readme.developers.txt | 205 ++ yamn/docs/YAMN-Readme.txt | 79 + yamn/docs/language.pop3.txt | 118 ++ yamn/docs/language.txt | 75 + yamn/filter/Base/AggressiveOptimize.h | 168 ++ yamn/filter/Base/Base.dsp | 108 ++ yamn/filter/Base/Base.mak | 229 +++ yamn/filter/Base/debug.cpp | 73 + yamn/filter/Base/docs/base-readme.txt | 63 + yamn/filter/Base/maindll.cpp | 238 +++ yamn/filter/Simple/AggressiveOptimize.h | 168 ++ yamn/filter/Simple/docs/simple-readme.txt | 51 + yamn/filter/Simple/maindll.cpp | 132 ++ yamn/filter/Simple/simple.dsp | 105 ++ yamn/filter/Simple/simple.mak | 207 ++ yamn/filter/readme.txt | 1 + yamn/filterplugin.cpp | 226 +++ yamn/icons/iconttbup.ico | Bin 0 -> 1150 bytes yamn/icons/icoyamn1.ico | Bin 0 -> 1150 bytes yamn/icons/icoyamn2.ico | Bin 0 -> 1150 bytes yamn/icons/proto_YAMN.dsp | 91 + yamn/icons/proto_YAMN.mak | 112 ++ yamn/icons/proto_YAMN.rc | 19 + yamn/icons/resource.h | 2 + yamn/include/IcoLib.h | 26 + yamn/include/m_icolib.h | 75 + yamn/include/m_kbdnotify.h | 64 + yamn/include/m_popup.h | 318 ++++ yamn/include/m_toptoolbar.h | 125 ++ yamn/include/m_uninstaller.h | 700 +++++++ yamn/include/m_updater.h | 156 ++ yamn/libs/unicows.lib | Bin 0 -> 492376 bytes yamn/m_account.h | 239 +++ yamn/m_filterplugin.h | 139 ++ yamn/m_messages.h | 41 + yamn/m_protoplugin.h | 389 ++++ yamn/m_synchro.h | 160 ++ yamn/m_yamn.h | 154 ++ yamn/mails/decode.cpp | 558 ++++++ yamn/mails/m_decode.h | 25 + yamn/mails/m_mails.h | 285 +++ yamn/mails/mails.cpp | 499 +++++ yamn/mails/mime.cpp | 732 ++++++++ yamn/mails/test/header.txt | 28 + yamn/mails/test/header2.txt | 97 + yamn/mails/test/readme.txt | 4 + yamn/mails/test/test.cpp | 42 + yamn/mails/test/test.dsp | 112 ++ yamn/mails/test/test.dsw | 29 + yamn/main.cpp | 846 +++++++++ yamn/main.h | 66 + yamn/mingw/base.dev | 69 + yamn/mingw/base.win | 38 + yamn/mingw/simple.dev | 59 + yamn/mingw/simple.win | 35 + yamn/mingw/yamn-2in1.dev | 469 +++++ yamn/mingw/yamn-2in1.win | 92 + yamn/mingw/yamn-w9x.dev | 469 +++++ yamn/mingw/yamn-w9x.win | 92 + yamn/mingw/yamn.dev | 469 +++++ yamn/mingw/yamn.win | 92 + yamn/proto/md5.c | 260 +++ yamn/proto/md5.h | 27 + yamn/proto/netclient.h | 22 + yamn/proto/netlib.cpp | 278 +++ yamn/proto/netlib.h | 55 + yamn/proto/pop3/pop3.cpp | 374 ++++ yamn/proto/pop3/pop3.h | 66 + yamn/proto/pop3/pop3comm.cpp | 1636 ++++++++++++++++ yamn/proto/pop3/pop3comm.h | 97 + yamn/proto/pop3/pop3opt.cpp | 1671 +++++++++++++++++ yamn/proto/pop3/pop3opt.h | 38 + yamn/proto/ssl.cpp | 344 ++++ yamn/proto/ssl.h | 61 + yamn/protoplugin.cpp | 258 +++ yamn/resources/YAMN.rc | 383 ++++ yamn/resources/iconeutral.ico | Bin 0 -> 1150 bytes yamn/resources/iconttbdown.ico | Bin 0 -> 1150 bytes yamn/resources/icooffline.ico | Bin 0 -> 1150 bytes yamn/resources/icoyamn3.ico | Bin 0 -> 1150 bytes yamn/resources/resource.h | 130 ++ yamn/resources/yamn.bmp | Bin 0 -> 502 bytes yamn/services.cpp | 541 ++++++ yamn/synchro.cpp | 378 ++++ yamn/version.h | 3 + yamn/yamn.cpp | 478 +++++ yamn/yamn.h | 178 ++ 231 files changed, 63780 insertions(+) create mode 100644 dbx_tree/BTree.h create mode 100644 dbx_tree/BlockManager.cpp create mode 100644 dbx_tree/BlockManager.h create mode 100644 dbx_tree/Compatibility.cpp create mode 100644 dbx_tree/Compatibility.h create mode 100644 dbx_tree/DataBase.cpp create mode 100644 dbx_tree/DataBase.h create mode 100644 dbx_tree/DatabaseLink.cpp create mode 100644 dbx_tree/DatabaseLink.h create mode 100644 dbx_tree/DirectAccess.cpp create mode 100644 dbx_tree/DirectAccess.h create mode 100644 dbx_tree/EncryptionManager.cpp create mode 100644 dbx_tree/EncryptionManager.h create mode 100644 dbx_tree/Entities.cpp create mode 100644 dbx_tree/Entities.h create mode 100644 dbx_tree/Events.cpp create mode 100644 dbx_tree/Events.h create mode 100644 dbx_tree/FileAccess.cpp create mode 100644 dbx_tree/FileAccess.h create mode 100644 dbx_tree/FileBTree.h create mode 100644 dbx_tree/Filestructure.txt create mode 100644 dbx_tree/Hash.cpp create mode 100644 dbx_tree/Hash.h create mode 100644 dbx_tree/Interface.h create mode 100644 dbx_tree/IterationHeap.h create mode 100644 dbx_tree/Logger.cpp create mode 100644 dbx_tree/Logger.h create mode 100644 dbx_tree/MREWSync.cpp create mode 100644 dbx_tree/MREWSync.h create mode 100644 dbx_tree/MappedMemory.cpp create mode 100644 dbx_tree/MappedMemory.h create mode 100644 dbx_tree/SHA256.cpp create mode 100644 dbx_tree/SHA256.h create mode 100644 dbx_tree/Services.cpp create mode 100644 dbx_tree/Services.h create mode 100644 dbx_tree/Settings.cpp create mode 100644 dbx_tree/Settings.h create mode 100644 dbx_tree/TLS.h create mode 100644 dbx_tree/Thread.cpp create mode 100644 dbx_tree/Thread.h create mode 100644 dbx_tree/dbConfig.rc create mode 100644 dbx_tree/dbConfig_rc.h create mode 100644 dbx_tree/dbVersion.rc create mode 100644 dbx_tree/dbVersion_rc.h create mode 100644 dbx_tree/dbx_tree.vcproj create mode 100644 dbx_tree/dbx_tree_10.vcxproj create mode 100644 dbx_tree/dbx_tree_10.vcxproj.filters create mode 100644 dbx_tree/encryption/ARC4.cpp create mode 100644 dbx_tree/encryption/ARC4.h create mode 100644 dbx_tree/encryption/ARC4.vcproj create mode 100644 dbx_tree/encryption/ARC4.vcxproj create mode 100644 dbx_tree/encryption/ARC4.vcxproj.filters create mode 100644 dbx_tree/encryption/CAST128.cpp create mode 100644 dbx_tree/encryption/CAST128.h create mode 100644 dbx_tree/encryption/CAST128.inc create mode 100644 dbx_tree/encryption/Cast128.vcproj create mode 100644 dbx_tree/encryption/Cast128.vcxproj create mode 100644 dbx_tree/encryption/Cast128.vcxproj.filters create mode 100644 dbx_tree/encryption/Cipher.h create mode 100644 dbx_tree/encryption/HC256.cpp create mode 100644 dbx_tree/encryption/HC256.h create mode 100644 dbx_tree/encryption/HC256.vcproj create mode 100644 dbx_tree/encryption/HC256.vcxproj create mode 100644 dbx_tree/encryption/HC256.vcxproj.filters create mode 100644 dbx_tree/init.cpp create mode 100644 dbx_tree/intrinsics.h create mode 100644 dbx_tree/inttypes.h create mode 100644 dbx_tree/lockfree_hashmap.h create mode 100644 dbx_tree/lockfree_hashmultimap.h create mode 100644 dbx_tree/m_dbx_tree.h create mode 100644 dbx_tree/savestrings_gcc.h create mode 100644 dbx_tree/sigslot.h create mode 100644 dbx_tree/stdint.h create mode 100644 lastseen-mod/file.c create mode 100644 lastseen-mod/history.c create mode 100644 lastseen-mod/main.c create mode 100644 lastseen-mod/menu.c create mode 100644 lastseen-mod/missed.c create mode 100644 lastseen-mod/options.c create mode 100644 lastseen-mod/readme_src.txt create mode 100644 lastseen-mod/resource.h create mode 100644 lastseen-mod/resource.rc create mode 100644 lastseen-mod/seen.h create mode 100644 lastseen-mod/seen_info.txt create mode 100644 lastseen-mod/seen_langpack.txt create mode 100644 lastseen-mod/seenplugin.dev create mode 100644 lastseen-mod/seenplugin.dsp create mode 100644 lastseen-mod/seenplugin.dsw create mode 100644 lastseen-mod/seenplugin.win create mode 100644 lastseen-mod/userinfo.c create mode 100644 lastseen-mod/utils.c create mode 100644 nudge/ChangeLog.txt create mode 100644 nudge/headers.h create mode 100644 nudge/include/IcoLib.h create mode 100644 nudge/include/m_folders.h create mode 100644 nudge/include/m_kbdnotify.h create mode 100644 nudge/include/m_metacontacts.h create mode 100644 nudge/include/m_msg_buttonsbar.h create mode 100644 nudge/include/m_popup.h create mode 100644 nudge/include/m_popupw.h create mode 100644 nudge/include/m_toptoolbar.h create mode 100644 nudge/include/m_trigger.h create mode 100644 nudge/include/m_uninstaller.h create mode 100644 nudge/include/m_updater.h create mode 100644 nudge/m_nudge.h create mode 100644 nudge/main.cpp create mode 100644 nudge/main.h create mode 100644 nudge/miranda.ico create mode 100644 nudge/nudge.cpp create mode 100644 nudge/nudge.dsp create mode 100644 nudge/nudge.dsw create mode 100644 nudge/nudge.h create mode 100644 nudge/nudge.vcproj create mode 100644 nudge/nudge_10.vcxproj create mode 100644 nudge/nudge_8.sln create mode 100644 nudge/nudge_8.vcproj create mode 100644 nudge/options.cpp create mode 100644 nudge/options.h create mode 100644 nudge/resource.h create mode 100644 nudge/resource.rc create mode 100644 nudge/resources/Nudge.ico create mode 100644 nudge/resources/NudgeIRC.ico create mode 100644 nudge/resources/NudgeMSN.ico create mode 100644 nudge/resources/NudgeMeta.ico create mode 100644 nudge/resources/NudgeTlen.ico create mode 100644 nudge/resources/NudgeYahoo.ico create mode 100644 nudge/resources/nudge msn.ico create mode 100644 nudge/shake.cpp create mode 100644 nudge/shake.h create mode 100644 yamn/ChangeLog.txt create mode 100644 yamn/YAMN.dsp create mode 100644 yamn/YAMN.dsw create mode 100644 yamn/YAMN.mak create mode 100644 yamn/YAMN.vcproj create mode 100644 yamn/YAMN_9.vcproj create mode 100644 yamn/YAMNopts.cpp create mode 100644 yamn/account.cpp create mode 100644 yamn/browser/badconnect.cpp create mode 100644 yamn/browser/m_browser.h create mode 100644 yamn/browser/mailbrowser.cpp create mode 100644 yamn/debug.cpp create mode 100644 yamn/debug.h create mode 100644 yamn/docs/InstallScript.xml create mode 100644 yamn/docs/YAMN-License.txt create mode 100644 yamn/docs/YAMN-Readme.developers.txt create mode 100644 yamn/docs/YAMN-Readme.txt create mode 100644 yamn/docs/language.pop3.txt create mode 100644 yamn/docs/language.txt create mode 100644 yamn/filter/Base/AggressiveOptimize.h create mode 100644 yamn/filter/Base/Base.dsp create mode 100644 yamn/filter/Base/Base.mak create mode 100644 yamn/filter/Base/debug.cpp create mode 100644 yamn/filter/Base/docs/base-readme.txt create mode 100644 yamn/filter/Base/maindll.cpp create mode 100644 yamn/filter/Simple/AggressiveOptimize.h create mode 100644 yamn/filter/Simple/docs/simple-readme.txt create mode 100644 yamn/filter/Simple/maindll.cpp create mode 100644 yamn/filter/Simple/simple.dsp create mode 100644 yamn/filter/Simple/simple.mak create mode 100644 yamn/filter/readme.txt create mode 100644 yamn/filterplugin.cpp create mode 100644 yamn/icons/iconttbup.ico create mode 100644 yamn/icons/icoyamn1.ico create mode 100644 yamn/icons/icoyamn2.ico create mode 100644 yamn/icons/proto_YAMN.dsp create mode 100644 yamn/icons/proto_YAMN.mak create mode 100644 yamn/icons/proto_YAMN.rc create mode 100644 yamn/icons/resource.h create mode 100644 yamn/include/IcoLib.h create mode 100644 yamn/include/m_icolib.h create mode 100644 yamn/include/m_kbdnotify.h create mode 100644 yamn/include/m_popup.h create mode 100644 yamn/include/m_toptoolbar.h create mode 100644 yamn/include/m_uninstaller.h create mode 100644 yamn/include/m_updater.h create mode 100644 yamn/libs/unicows.lib create mode 100644 yamn/m_account.h create mode 100644 yamn/m_filterplugin.h create mode 100644 yamn/m_messages.h create mode 100644 yamn/m_protoplugin.h create mode 100644 yamn/m_synchro.h create mode 100644 yamn/m_yamn.h create mode 100644 yamn/mails/decode.cpp create mode 100644 yamn/mails/m_decode.h create mode 100644 yamn/mails/m_mails.h create mode 100644 yamn/mails/mails.cpp create mode 100644 yamn/mails/mime.cpp create mode 100644 yamn/mails/test/header.txt create mode 100644 yamn/mails/test/header2.txt create mode 100644 yamn/mails/test/readme.txt create mode 100644 yamn/mails/test/test.cpp create mode 100644 yamn/mails/test/test.dsp create mode 100644 yamn/mails/test/test.dsw create mode 100644 yamn/main.cpp create mode 100644 yamn/main.h create mode 100644 yamn/mingw/base.dev create mode 100644 yamn/mingw/base.win create mode 100644 yamn/mingw/simple.dev create mode 100644 yamn/mingw/simple.win create mode 100644 yamn/mingw/yamn-2in1.dev create mode 100644 yamn/mingw/yamn-2in1.win create mode 100644 yamn/mingw/yamn-w9x.dev create mode 100644 yamn/mingw/yamn-w9x.win create mode 100644 yamn/mingw/yamn.dev create mode 100644 yamn/mingw/yamn.win create mode 100644 yamn/proto/md5.c create mode 100644 yamn/proto/md5.h create mode 100644 yamn/proto/netclient.h create mode 100644 yamn/proto/netlib.cpp create mode 100644 yamn/proto/netlib.h create mode 100644 yamn/proto/pop3/pop3.cpp create mode 100644 yamn/proto/pop3/pop3.h create mode 100644 yamn/proto/pop3/pop3comm.cpp create mode 100644 yamn/proto/pop3/pop3comm.h create mode 100644 yamn/proto/pop3/pop3opt.cpp create mode 100644 yamn/proto/pop3/pop3opt.h create mode 100644 yamn/proto/ssl.cpp create mode 100644 yamn/proto/ssl.h create mode 100644 yamn/protoplugin.cpp create mode 100644 yamn/resources/YAMN.rc create mode 100644 yamn/resources/iconeutral.ico create mode 100644 yamn/resources/iconttbdown.ico create mode 100644 yamn/resources/icooffline.ico create mode 100644 yamn/resources/icoyamn3.ico create mode 100644 yamn/resources/resource.h create mode 100644 yamn/resources/yamn.bmp create mode 100644 yamn/services.cpp create mode 100644 yamn/synchro.cpp create mode 100644 yamn/version.h create mode 100644 yamn/yamn.cpp create mode 100644 yamn/yamn.h diff --git a/dbx_tree/BTree.h b/dbx_tree/BTree.h new file mode 100644 index 0000000..20c2abf --- /dev/null +++ b/dbx_tree/BTree.h @@ -0,0 +1,1358 @@ +/* + +dbx_tree: tree database driver for Miranda IM + +Copyright 2007-2010 Michael "Protogenes" Kunz, + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#pragma once + +#include +#include "lockfree_hashmultimap.h" +#include "sigslot.h" +#ifdef _MSC_VER +#include "stdint.h" +#else +#include +#endif + +#include "Logger.h" + +#ifndef _MSC_VER +#ifdef offsetof +#undef offsetof +#endif +#define offsetof(TYPE, MEMBER) \ + ( (reinterpret_cast \ + (&reinterpret_cast \ + (static_cast (0)->MEMBER)))) +#endif + +template +class CBTree +{ +public: + typedef uint32_t TNodeRef; /// 32bit indices (not storing pointers) + typedef sigslot::signal2< void *, TNodeRef > TOnRootChanged; + + #pragma pack(push, 1) // push current alignment to stack, set alignment to 1 byte boundary + + typedef struct TNode { + uint16_t Info; /// Node information (IsLeaf and stored KeyCount) + uint16_t Signature; /// signature + TNodeRef Parent; /// Handle to the parent node + TKey Key[SizeParam * 2 - 1]; /// array with Keys + TNodeRef Child[SizeParam * 2]; /// array with child node handles + } TNode; + + #pragma pack(pop) + + class iterator + { + public: + iterator(); + iterator(CBTree* Tree, TNodeRef Node, uint16_t Index); + iterator(const iterator& Other); + ~iterator(); + + CBTree * Tree(); + + /** + \brief Keeps track of changes in the tree and refresh the iterator + **/ + void setManaged(); + bool wasDeleted(); + + operator bool() const; + bool operator !() const; + + const TKey & operator *(); + const TKey * operator->(); + + + bool operator == (iterator & Other); + bool operator < (iterator & Other); + bool operator > (iterator & Other); + + iterator& operator =(const iterator& Other); + + iterator& operator ++(); //pre ++i + iterator& operator --(); //pre --i + iterator operator ++(int); //post i++ + iterator operator --(int); //post i-- + + + protected: + friend class CBTree; + + TNodeRef m_Node; + uint16_t m_Index; + CBTree* m_Tree; + + bool m_Managed; + bool m_LoadedKey; + TKey m_ManagedKey; + bool m_ManagedDeleted; + + void Backup(); + void Dec(); + void Inc(); + void RemoveManaged(TNodeRef FromNode); + void InsertManaged(); + }; + + + CBTree(TNodeRef RootNode = 0); + virtual ~CBTree(); + + iterator Insert(const TKey & Key); + iterator Find(const TKey & Key); + iterator LowerBound(const TKey & Key); + iterator UpperBound(const TKey & Key); + bool Delete(const TKey & Key); + + typedef sigslot::signal3 TDeleteCallback; + void DeleteTree(TDeleteCallback * CallBack, uint32_t Param); + + TNodeRef getRoot(); + void setRoot(TNodeRef NewRoot); + + TOnRootChanged & sigRootChanged() {return m_sigRootChanged;}; + + +protected: + static const uint16_t cIsLeafMask = 0x8000; + static const uint16_t cKeyCountMask = 0x7FFF; + static const uint16_t cFullNode = SizeParam * 2 - 1; + static const uint16_t cEmptyNode = SizeParam - 1; + + typedef lockfree::hash_multimap TManagedMap; + + TNodeRef m_Root; + TOnRootChanged m_sigRootChanged; + TManagedMap m_ManagedIterators; + + bool m_DestroyTree; + + uint32_t m_AllocCount; + uint32_t m_Count; + uint32_t m_FreeIndex; + TNode * m_Alloc; + + virtual void PrepareInsertOperation(); + virtual TNode * CreateNewNode(TNodeRef & NodeRef); + virtual void DeleteNode(TNodeRef Node); + virtual TNode * Read(TNodeRef Node); + virtual void Write(TNodeRef Node); + + void DestroyTree(); + + +private: + friend class iterator; + + bool InNodeFind(const TNode * Node, const TKey & Key, uint16_t & GreaterEqual); + void SplitNode(TNodeRef Node, TNode * NodeData, TNodeRef & Left, TNodeRef & Right, TKey & UpKey, TNodeRef ParentNode, uint16_t ParentIndex); + TNodeRef MergeNodes(TNodeRef Left, TNode * LeftData, TNodeRef Right, TNode * RightData, const TKey & DownKey, TNodeRef ParentNode, uint16_t ParentIndex); + void KeyInsert(TNodeRef Node, TNode * NodeData, uint16_t Where); + void KeyDelete(TNodeRef Node, TNode * NodeData, uint16_t Where); + void KeyMove(TNodeRef Source, uint16_t SourceIndex, const TNode * SourceData, TNodeRef Dest, uint16_t DestIndex, TNode * DestData); +}; + + + + + + +template +CBTree::CBTree(TNodeRef RootNode = NULL) +: m_sigRootChanged(), + m_ManagedIterators() +{ + m_Root = RootNode; + m_DestroyTree = true; + + m_AllocCount = 0; + m_Count = 0; + m_FreeIndex = 0; + m_Alloc = NULL; +} + +template +CBTree::~CBTree() +{ + typename TManagedMap::iterator i = m_ManagedIterators.begin(); + while (i != m_ManagedIterators.end()) + { + i->second->m_Tree = NULL; + i++; + } + + if (m_DestroyTree) + DestroyTree(); +} + +template +inline bool CBTree::InNodeFind(const TNode * Node, const TKey & Key, uint16_t & GreaterEqual) +{ + uint16_t l = 0; + uint16_t r = (Node->Info & cKeyCountMask); + bool res = false; + GreaterEqual = 0; + while ((l < r) && !res) + { + GreaterEqual = (l + r) >> 1; + if (Node->Key[GreaterEqual] < Key) + { + GreaterEqual++; + l = GreaterEqual; + } else if (Node->Key[GreaterEqual] == Key) + { + //r = -1; + res = true; + } else { + r = GreaterEqual; + } + } + + return res; +} + + +template +inline void CBTree::SplitNode(TNodeRef Node, TNode * NodeData, TNodeRef & Left, TNodeRef & Right, TKey & UpKey, TNodeRef ParentNode, uint16_t ParentIndex) +{ + const uint16_t upindex = SizeParam - 1; + TNode *ldata, *rdata; + Left = Node; + ldata = NodeData; + rdata = CreateNewNode(Right); + + typename TManagedMap::iterator it = m_ManagedIterators.find(Node); + while ((it != m_ManagedIterators.end()) && (it->first == Node)) + { + if (it->second->m_Index == upindex) + { + it->second->m_Index = ParentIndex; + it->second->m_Node = ParentNode; + m_ManagedIterators.insert(std::make_pair(ParentNode, it->second)); + it = m_ManagedIterators.erase(it); + } else if (it->second->m_Index > upindex) + { + it->second->m_Index = it->second->m_Index - upindex - 1; + it->second->m_Node = Right; + m_ManagedIterators.insert(std::make_pair(Right, it->second)); + it = m_ManagedIterators.erase(it); + } else { + ++it; + } + } + + UpKey = NodeData->Key[upindex]; + + memcpy(&(rdata->Key[0]), &(NodeData->Key[upindex+1]), sizeof(TKey) * (cFullNode - upindex)); + if ((NodeData->Info & cIsLeafMask) == 0) + { + memcpy(&(rdata->Child[0]), &(NodeData->Child[upindex+1]), sizeof(TNodeRef) * (cFullNode - upindex + 1)); + + for (int i = 0; i <= upindex; i++) + { + TNode * tmp = Read(rdata->Child[i]); + tmp->Parent = Right; + Write(rdata->Child[i]); + } + } + + rdata->Info = (NodeData->Info & cIsLeafMask) | upindex; + NodeData->Info = rdata->Info; + rdata->Parent = NodeData->Parent; + + Write(Left); + Write(Right); +} + +template +inline typename CBTree::TNodeRef CBTree::MergeNodes(TNodeRef Left, TNode * LeftData, TNodeRef Right, TNode * RightData, const TKey & DownKey, TNodeRef ParentNode, uint16_t ParentIndex) +{ + uint16_t downindex = LeftData->Info & cKeyCountMask; + LeftData->Key[downindex] = DownKey; + + typename TManagedMap::iterator it = m_ManagedIterators.find(Right); + while ((it != m_ManagedIterators.end()) && (it->first == Right)) + { + it->second->m_Index = it->second->m_Index + downindex + 1; + it->second->m_Node = Left; + m_ManagedIterators.insert(std::make_pair(Left, it->second)); + it = m_ManagedIterators.erase(it); + } + + it = m_ManagedIterators.find(ParentNode); + while ((it != m_ManagedIterators.end()) && (it->first == ParentNode)) + { + if (it->second->m_Index == ParentIndex) + { + it->second->m_Index = downindex; + it->second->m_Node = Left; + m_ManagedIterators.insert(std::make_pair(Left, it->second)); + it = m_ManagedIterators.erase(it); + } else { + ++it; + } + } + + memcpy(&(LeftData->Key[downindex+1]), &(RightData->Key[0]), sizeof(TKey) * (RightData->Info & cKeyCountMask)); + if ((LeftData->Info & cIsLeafMask) == 0) + { + memcpy(&(LeftData->Child[downindex+1]), &(RightData->Child[0]), sizeof(TNodeRef) * ((RightData->Info & cKeyCountMask) + 1)); + + for (int i = 0; i <= (RightData->Info & cKeyCountMask); i++) + { + TNode * tmp = Read(RightData->Child[i]); + tmp->Parent = Left; + Write(RightData->Child[i]); + } + } + + LeftData->Info = ((LeftData->Info & cIsLeafMask) | (downindex + 1 + (RightData->Info & cKeyCountMask))); + + Write(Left); + DeleteNode(Right); + + return Left; +} + + +template +inline void CBTree::KeyInsert(TNodeRef Node, TNode * NodeData, uint16_t Where) +{ + memcpy(&(NodeData->Key[Where+1]), &(NodeData->Key[Where]), sizeof(TKey) * ((NodeData->Info & cKeyCountMask) - Where)); + + if ((NodeData->Info & cIsLeafMask) == 0) + memcpy(&(NodeData->Child[Where+1]), &(NodeData->Child[Where]), sizeof(TNodeRef) * ((NodeData->Info & cKeyCountMask) - Where + 1)); + + NodeData->Info++; + + typename TManagedMap::iterator it = m_ManagedIterators.find(Node); + while ((it != m_ManagedIterators.end()) && (it->first == Node)) + { + if (it->second->m_Index >= Where) + it->second->m_Index++; + + ++it; + } +} + +template +inline void CBTree::KeyDelete(TNodeRef Node, TNode * NodeData, uint16_t Where) +{ + NodeData->Info--; + + typename TManagedMap::iterator it = m_ManagedIterators.find(Node); + while ((it != m_ManagedIterators.end()) && (it->first == Node)) + { + if (it->second->m_Index == Where) + { + it->second->Backup(); + } else if (it->second->m_Index > Where) + { + it->second->m_Index--; + } + + ++it; + } + + memcpy(&(NodeData->Key[Where]), &(NodeData->Key[Where+1]), sizeof(TKey) * ((NodeData->Info & cKeyCountMask) - Where)); + + if ((NodeData->Info & cIsLeafMask) == 0) + memcpy(&(NodeData->Child[Where]), &(NodeData->Child[Where+1]), sizeof(TNodeRef) * ((NodeData->Info & cKeyCountMask) - Where + 1)); +} + + +template +inline void CBTree::KeyMove(TNodeRef Source, uint16_t SourceIndex, const TNode * SourceData, TNodeRef Dest, uint16_t DestIndex, TNode * DestData) +{ + DestData->Key[DestIndex] = SourceData->Key[SourceIndex]; + + typename TManagedMap::iterator it = m_ManagedIterators.find(Source); + while ((it != m_ManagedIterators.end()) && (it->first == Source)) + { + if (it->second->m_Index == SourceIndex) + { + it->second->m_Index = DestIndex; + it->second->m_Node = Dest; + m_ManagedIterators.insert(std::make_pair(Dest, it->second)); + it = m_ManagedIterators.erase(it); + } else { + ++it; + } + } +} + +template +typename CBTree::iterator +CBTree::Insert(const TKey & Key) +{ + TNode *node, *node2; + TNodeRef actnode; + TNodeRef nextnode; + bool exists; + uint16_t ge; + + PrepareInsertOperation(); + + if (!m_Root) + { + node = CreateNewNode(m_Root); + node->Info = cIsLeafMask; + Write(m_Root); + m_sigRootChanged.emit(this, m_Root); + } + + actnode = m_Root; + node = Read(actnode); + if ((node->Info & cKeyCountMask) == cFullNode) // root split + { + // be a little tricky and let the main code handle the actual splitting. + // just assign a new root with keycount to zero and one child = old root + // the InNode test will fail with GreaterEqual = 0 + node2 = CreateNewNode(nextnode); + node2->Info = 0; + node2->Child[0] = actnode; + Write(nextnode); + + node->Parent = nextnode; + Write(actnode); + + node = node2; + actnode = nextnode; + + m_Root = nextnode; + m_sigRootChanged.emit(this, m_Root); + } + + while (actnode) + { + exists = InNodeFind(node, Key, ge); + if (exists) // already exists + { + return iterator(this, actnode, ge); + } else { + if (node->Info & cIsLeafMask) // direct insert to leaf node + { + KeyInsert(actnode, node, ge); + + node->Key[ge] = Key; + + Write(actnode); + + return iterator(this, actnode, ge); + + } else { // middle node + nextnode = node->Child[ge]; + node2 = Read(nextnode); + + if ((node2->Info & cKeyCountMask) == cFullNode) // split the childnode + { + KeyInsert(actnode, node, ge); + SplitNode(nextnode, node2, node->Child[ge], node->Child[ge+1], node->Key[ge], actnode, ge); + + Write(actnode); + if (node->Key[ge] == Key) + { + return iterator(this, actnode, ge); + } else { + if (node->Key[ge] < Key) + { + nextnode = node->Child[ge+1]; + } else { + nextnode = node->Child[ge]; + } + } + + } + actnode = nextnode; + node = Read(actnode); + + } // if (node.Info & cIsLeafMask) + } // if (exists) + } // while (actnode) + + // something went wrong + return iterator(this, 0, 0xFFFF); +} + + +template +typename CBTree::iterator +CBTree::Find(const TKey & Key) +{ + TNode * node; + TNodeRef actnode = m_Root; + uint16_t ge; + + if (!m_Root) return iterator(this, 0, 0xFFFF); + + node = Read(actnode); + + while (actnode) + { + if (InNodeFind(node, Key, ge)) + { + return iterator(this, actnode, ge); + } + + if (!(node->Info & cIsLeafMask)) + { + actnode = node->Child[ge]; + node = Read(actnode); + } else { + actnode = 0; + } + } + + return iterator(this, 0, 0xFFFF); +} + +template +typename CBTree::iterator +CBTree::LowerBound(const TKey & Key) +{ + TNode * node; + TNodeRef actnode = m_Root; + uint16_t ge; + + if (!m_Root) return iterator(this, 0, 0xFFFF); + + node = Read(actnode); + + while (actnode) + { + if (InNodeFind(node, Key, ge)) + { + return iterator(this, actnode, ge); + } + + if (node->Info & cIsLeafMask) + { + if (ge >= (node->Info & cKeyCountMask)) + { + iterator i(this, actnode, ge - 1); + ++i; + return i; + } else { + return iterator(this, actnode, ge); + } + } else { + actnode = node->Child[ge]; + node = Read(actnode); + } + } + + return iterator(this, 0, 0xFFFF); +} + +template +typename CBTree::iterator +CBTree::UpperBound(const TKey & Key) +{ + TNode * node; + TNodeRef actnode = m_Root; + uint16_t ge; + if (!m_Root) return iterator(this, 0, 0xFFFF); + + node = Read(actnode); + + while (actnode) + { + if (InNodeFind(node, Key, ge)) + { + return iterator(this, actnode, ge); + } + + if (node->Info & cIsLeafMask) + { + if (ge == 0) + { + iterator i(this, actnode, 0); + --i; + return i; + } else { + return iterator(this, actnode, ge - 1); + } + } else { + actnode = node->Child[ge]; + node = Read(actnode); + } + } + + return iterator(this, 0, 0xFFFF); +} + +template +bool CBTree::Delete(const TKey& Key) +{ + if (!m_Root) return false; + + TNode *node, *node2, *lnode, *rnode; + + TNodeRef actnode = m_Root; + TNodeRef nextnode, l, r; + bool exists, skipread; + uint16_t ge; + + bool foundininnernode = false; + bool wantleftmost = false; + TNodeRef innernode = 0; + TNode * innernodedata = NULL; + uint16_t innerindex = 0xFFFF; + + node = Read(actnode); + + while (actnode) + { + skipread = false; + + if (foundininnernode) + { + exists = false; + if (wantleftmost) + ge = 0; + else + ge = node->Info & cKeyCountMask; + + } else { + exists = InNodeFind(node, Key, ge); + } + + if (exists) + { + if (node->Info & cIsLeafMask) // delete in leaf + { + KeyDelete(actnode, node, ge); + Write(actnode); + + return true; + + } else { // delete in inner node + l = node->Child[ge]; + r = node->Child[ge+1]; + lnode = Read(l); + rnode = Read(r); + + + if (((rnode->Info & cKeyCountMask) == cEmptyNode) && ((lnode->Info & cKeyCountMask) == cEmptyNode)) + { // merge childnodes and keep going + nextnode = MergeNodes(l, lnode, r, rnode, node->Key[ge], actnode, ge); + + KeyDelete(actnode, node, ge); + node->Child[ge] = nextnode; + + if ((actnode == m_Root) && ((node->Info & cKeyCountMask) == 0)) + { // root node is empty. delete it + DeleteNode(actnode); + m_Root = nextnode; + m_sigRootChanged.emit(this, m_Root); + } else { + Write(actnode); + } + + } else { // need a key-data-pair from a leaf to replace deleted pair -> save position + foundininnernode = true; + innernode = actnode; + innerindex = ge; + innernodedata = node; + + if ((lnode->Info & cKeyCountMask) == cEmptyNode) + { + wantleftmost = true; + nextnode = r; + } else { + wantleftmost = false; + nextnode = l; + } + } + } + + } else if (node->Info & cIsLeafMask) { // we are at the bottom. finish it + if (foundininnernode) + { + if (wantleftmost) + { + KeyMove(actnode, 0, node, innernode, innerindex, innernodedata); + Write(innernode); + + KeyDelete(actnode, node, 0); + Write(actnode); + + } else { + KeyMove(actnode, (node->Info & cKeyCountMask) - 1, node, innernode, innerindex, innernodedata); + Write(innernode); + + //KeyDelete(actnode, node, node.Info & cKeyCountMask); + node->Info--; + Write(actnode); + } + } + return foundininnernode; + + } else { // inner node. go on and check if moving or merging is neccessary + nextnode = node->Child[ge]; + node2 = Read(nextnode); + + if ((node2->Info & cKeyCountMask) == cEmptyNode) // move or merge + { + // set l and r for easier access + if (ge > 0) + { + l = node->Child[ge - 1]; + lnode = Read(l); + } else + l = 0; + + if (ge < (node->Info & cKeyCountMask)) + { + r = node->Child[ge + 1]; + rnode = Read(r); + } else + r = 0; + + if ((r != 0) && ((rnode->Info & cKeyCountMask) > cEmptyNode)) // move a Key-Data-pair from the right + { + // move key-data-pair down from current to the next node + KeyMove(actnode, ge, node, nextnode, node2->Info & cKeyCountMask, node2); + + // move the child from right to next node + node2->Child[(node2->Info & cKeyCountMask) + 1] = rnode->Child[0]; + + // move key-data-pair up from right to current node + KeyMove(r, 0, rnode, actnode, ge, node); + Write(actnode); + + // decrement right node key count and remove the first key-data-pair + KeyDelete(r, rnode, 0); + + // increment KeyCount of the next node + node2->Info++; + + if ((node2->Info & cIsLeafMask) == 0) // update the parent property of moved child + { + TNode * tmp = Read(node2->Child[node2->Info & cKeyCountMask]); + tmp->Parent = nextnode; + Write(node2->Child[node2->Info & cKeyCountMask]); + } + + + Write(r); + Write(nextnode); + node = node2; + skipread = true; + + } else if ((l != 0) && ((lnode->Info & cKeyCountMask) > cEmptyNode)) // move a Key-Data-pair from the left + { + // increment next node key count and make new first key-data-pair + KeyInsert(nextnode, node2, 0); + + // move key-data-pair down from current to the next node + KeyMove(actnode, ge - 1, node, nextnode, 0, node2); + + // move the child from left to next node + node2->Child[0] = lnode->Child[lnode->Info & cKeyCountMask]; + + // move key-data-pair up from left to current node + KeyMove(l, (lnode->Info & cKeyCountMask) - 1, lnode, actnode, ge - 1, node); + Write(actnode); + + // decrement left node key count + lnode->Info--; + Write(l); + + if ((node2->Info & cIsLeafMask) == 0) // update the parent property of moved child + { + TNode * tmp = Read(node2->Child[0]); + tmp->Parent = nextnode; + Write(node2->Child[0]); + } + + Write(nextnode); + node = node2; + skipread = true; + + } else { + if (l != 0) // merge with the left node + { + nextnode = MergeNodes(l, lnode, nextnode, node2, node->Key[ge - 1], actnode, ge - 1); + KeyDelete(actnode, node, ge - 1); + node->Child[ge - 1] = nextnode; + + } else { // merge with the right node + nextnode = MergeNodes(nextnode, node2, r, rnode, node->Key[ge], actnode, ge); + KeyDelete(actnode, node, ge); + node->Child[ge] = nextnode; + } + + if ((actnode == m_Root) && ((node->Info & cKeyCountMask) == 0)) + { + DeleteNode(actnode); + m_Root = nextnode; + m_sigRootChanged(this, nextnode); + } else { + Write(actnode); + } + } + } + } // if (exists) else if (node.Info & cIsLeafMask) + + actnode = nextnode; + if (!skipread) + node = Read(actnode); + + } // while(actnode) + + return false; +} + +template +typename CBTree::TNodeRef CBTree::getRoot() +{ + return m_Root; +} + +template +void CBTree::setRoot(TNodeRef NewRoot) +{ + m_Root = NewRoot; + return; +} + +template +void CBTree::PrepareInsertOperation() +{ + if (m_Count + 64 > m_AllocCount) + { + m_AllocCount += 64; + m_Alloc = (TNode *)realloc(m_Alloc, sizeof(TNode) * m_AllocCount); + + for (TNodeRef i = m_AllocCount - 64; i < m_AllocCount; ++i) + m_Alloc[i].Parent = i + 1; + + m_Alloc[m_AllocCount - 1].Parent = 0; + + if (m_FreeIndex) + { + TNodeRef i = m_FreeIndex; + while (m_Alloc[i].Parent) + i = m_Alloc[i].Parent; + + m_Alloc[i].Parent = m_AllocCount - 64; + + } else { + m_FreeIndex = m_AllocCount - 63; + } + + } +} + +template +typename CBTree::TNode * CBTree::CreateNewNode(TNodeRef & NodeRef) +{ + NodeRef = m_FreeIndex; + m_FreeIndex = m_Alloc[m_FreeIndex].Parent; + m_Count++; + memset(m_Alloc + NodeRef, 0, sizeof(TNode)); + return m_Alloc + NodeRef; +} + +template +void CBTree::DeleteNode(TNodeRef Node) +{ + CHECK((Node > 0) && (Node < m_AllocCount), logERROR, _T("Invalid Node")); + m_Alloc[Node].Parent = m_FreeIndex; + m_FreeIndex = Node; + m_Count--; +} + +template +typename CBTree::TNode * CBTree::Read(TNodeRef Node) +{ + CHECK((Node > 0) && (Node < m_AllocCount), logERROR, _T("Invalid Node")); + return m_Alloc + Node; +} + +template +void CBTree::Write(TNodeRef Node) +{ + return; +} + +template +void CBTree::DestroyTree() +{ + std::stack s; + TNodeRef node; + TNode* nodedata; + uint16_t i; + + if (m_Root) + s.push(m_Root); + while (!s.empty()) + { + node = s.top(); + nodedata = Read(node); + s.pop(); + + if ((nodedata->Info & cIsLeafMask) == 0) + { + for (i = 0; i <= (nodedata->Info & cKeyCountMask); i++) + s.push(nodedata->Child[i]); + } + + DeleteNode(node); + } + + if (m_Alloc) + free(m_Alloc); + m_Alloc = NULL; + m_AllocCount = 0; + m_Count = 0; + m_FreeIndex = 0; +} + + +template +void CBTree::DeleteTree(TDeleteCallback * CallBack, uint32_t Param) +{ + std::stack s; + TNodeRef actnode; + TNode * node; + uint16_t i; + + typename TManagedMap::iterator it = m_ManagedIterators.begin(); + while (it != m_ManagedIterators.end()) + { + it->second->m_Node = 0; + it->second->m_Index = 0xffff; + ++it; + } + + if (m_Root) + s.push(m_Root); + + m_Root = 0; + m_sigRootChanged.emit(this, m_Root); + + while (!s.empty()) + { + actnode = s.top(); + s.pop(); + + node = Read(actnode); + + if ((node->Info & cIsLeafMask) == 0) + { + for (i = 0; i <= (node->Info & cKeyCountMask); i++) + s.push(node->Child[i]); + + } + if (CallBack) + { + for (i = 0; i < (node->Info & cKeyCountMask); i++) + CallBack->emit(this, node->Key[i], Param); + } + + DeleteNode(actnode); + } +} + + + + + + + +template +CBTree::iterator::iterator() +{ + m_Tree = NULL; + m_Node = 0; + m_Index = 0xFFFF; + m_Managed = false; + m_ManagedDeleted = false; + m_LoadedKey = false; +} +template +CBTree::iterator::iterator(CBTree* Tree, TNodeRef Node, uint16_t Index) +{ + m_Tree = Tree; + m_Node = Node; + m_Index = Index; + m_Managed = false; + m_ManagedDeleted = false; + m_LoadedKey = false; +} +template +CBTree::iterator::iterator(const iterator& Other) +{ + m_Tree = Other.m_Tree; + m_Node = Other.m_Node; + m_Index = Other.m_Index; + m_ManagedDeleted = Other.m_ManagedDeleted; + m_Managed = Other.m_Managed; + m_LoadedKey = Other.m_LoadedKey; + m_ManagedKey = Other.m_ManagedKey; + + if (m_Managed) + InsertManaged(); +} + +template +CBTree::iterator::~iterator() +{ + RemoveManaged(m_Node); +} + + +template +void CBTree::iterator::setManaged() +{ + if (!m_Managed) + InsertManaged(); + + m_Managed = true; +} + +template +inline void CBTree::iterator::RemoveManaged(TNodeRef FromNode) +{ + if (m_Managed && m_Tree) + { + typename TManagedMap::iterator i = m_Tree->m_ManagedIterators.find(FromNode); + + while ((i != m_Tree->m_ManagedIterators.end()) && (i->second != this) && (i->first == FromNode)) + ++i; + + if ((i != m_Tree->m_ManagedIterators.end()) && (i->second == this)) + m_Tree->m_ManagedIterators.erase(i); + } +} +template +inline void CBTree::iterator::InsertManaged() +{ + if (m_Tree) + m_Tree->m_ManagedIterators.insert(std::make_pair(m_Node, this)); +} + +template +bool CBTree::iterator::wasDeleted() +{ + return m_ManagedDeleted; +} + +template +void CBTree::iterator::Backup() +{ + if ((!m_ManagedDeleted) && (*this)) + { + TNode * tmp; + if (!m_LoadedKey) + { + tmp = m_Tree->Read(m_Node); + m_ManagedKey = tmp->Key[m_Index]; + } + m_LoadedKey = true; + } + + m_ManagedDeleted = true; +} + +template +CBTree * CBTree::iterator::Tree() +{ + return m_Tree; +} + +template +const TKey& CBTree::iterator::operator *() +{ + if (!m_LoadedKey) + { + TNode * node; + node = m_Tree->Read(m_Node); + m_ManagedKey = node->Key[m_Index]; + m_LoadedKey = true; + } + return m_ManagedKey; +} + +template +const TKey* CBTree::iterator::operator ->() +{ + if (!m_LoadedKey) + { + TNode * node; + node = m_Tree->Read(m_Node); + m_ManagedKey = node->Key[m_Index]; + m_LoadedKey = true; + } + return &m_ManagedKey; +} + +template +inline CBTree::iterator::operator bool() const +{ + if (m_Tree && m_Node) + { + TNode * node; + node = m_Tree->Read(m_Node); + return (m_Index < (node->Info & cKeyCountMask)); + } else + return false; +} + +template +inline bool CBTree::iterator::operator !() const +{ + if (m_Tree && m_Node) + { + TNode * node; + node = m_Tree->Read(m_Node); + return (m_Index > (node->Info & cKeyCountMask)); + } else + return true; +} + +template +inline bool CBTree::iterator::operator ==(iterator & Other) +{ + //return (m_Tree == Other.m_Tree) && (m_Node == Other.m_Node) && (m_Index == Other.m_Index) && (!m_ManagedDeleted) && (!Other.m_ManagedDeleted); + return Key() == Other.Key(); +} + +template +inline bool CBTree::iterator::operator < (iterator & Other) +{ + return Key() < Other.Key(); +} +template +inline bool CBTree::iterator::operator > (iterator & Other) +{ + return Key() > Other.Key(); +} + + +template +typename CBTree::iterator& +CBTree::iterator::operator =(const iterator& Other) +{ + RemoveManaged(m_Node); + + m_Tree = Other.m_Tree; + m_Node = Other.m_Node; + m_Index = Other.m_Index; + m_ManagedDeleted = Other.m_ManagedDeleted; + m_Managed = Other.m_Managed; + m_LoadedKey = Other.m_LoadedKey; + m_ManagedKey = Other.m_ManagedKey; + + if (m_Managed) + InsertManaged(); + + return *this; +} + +template +typename CBTree::iterator& +CBTree::iterator::operator ++() //pre ++i +{ + TNodeRef oldnode = m_Node; + if (m_Managed && m_ManagedDeleted) + { + TKey oldkey = m_ManagedKey; + m_LoadedKey = false; + m_ManagedDeleted = false; + iterator other = m_Tree->LowerBound(m_ManagedKey); + m_Node = other.m_Node; + m_Index = other.m_Index; + while (((**this) == oldkey) && (*this)) + Inc(); + + } else + Inc(); + + if (m_Managed && (oldnode != m_Node)) + { + RemoveManaged(oldnode); + InsertManaged(); + } + return *this; +} + +template +typename CBTree::iterator& +CBTree::iterator::operator --() //pre --i +{ + TNodeRef oldnode = m_Node; + if (m_Managed && m_ManagedDeleted) + { + TKey oldkey = m_ManagedKey; + m_LoadedKey = false; + + m_ManagedDeleted = false; + iterator other = m_Tree->UpperBound(m_ManagedKey); + m_Node = other.m_Node; + m_Index = other.m_Index; + while (((**this) == oldkey) && (*this)) + Dec(); + } else + Dec(); + + if (m_Managed && (oldnode != m_Node)) + { + RemoveManaged(oldnode); + InsertManaged(); + } + return *this; +} + +template +typename CBTree::iterator +CBTree::iterator::operator ++(int) //post i++ +{ + iterator tmp(*this); + ++(*this); + return tmp; +} +template +typename CBTree::iterator +CBTree::iterator::operator --(int) //post i-- +{ + iterator tmp(*this); + --(*this); + return tmp; +} + +template +void CBTree::iterator::Inc() +{ + TNode * node; + TNodeRef nextnode; + node = m_Tree->Read(m_Node); + + m_LoadedKey = false; + + if ((node->Info & cIsLeafMask) && ((node->Info & cKeyCountMask) > m_Index + 1)) // leaf + { + m_Index++; + return; + } + + if ((node->Info & cIsLeafMask) == 0) // inner node. go down + { + m_Node = node->Child[m_Index + 1]; + node = m_Tree->Read(m_Node); + + m_Index = 0; + + while ((node->Info & cIsLeafMask) == 0) // go down to a leaf + { + m_Node = node->Child[0]; + node = m_Tree->Read(m_Node); + } + + return; + } + + while (m_Index >= (node->Info & cKeyCountMask) - 1) // go up + { + if (m_Node == m_Tree->m_Root) // the root is the top, we cannot go further + { + m_Index = 0xFFFF; + m_Node = 0; + return; + } + + nextnode = node->Parent; + node = m_Tree->Read(nextnode); + m_Index = 0; + + while ((m_Index <= (node->Info & cKeyCountMask)) && (node->Child[m_Index] != m_Node)) + m_Index++; + + m_Node = nextnode; + + if (m_Index < (node->Info & cKeyCountMask)) + return; + } + +} + +template +void CBTree::iterator::Dec() +{ + TNode * node; + TNodeRef nextnode; + node = m_Tree->Read(m_Node); + + m_LoadedKey = false; + + if ((node->Info & cIsLeafMask) && (m_Index > 0)) // leaf + { + m_Index--; + return; + } + + if ((node->Info & cIsLeafMask) == 0) // inner node. go down + { + m_Node = node->Child[m_Index]; + node = m_Tree->Read(m_Node); + m_Index = (node->Info & cKeyCountMask) - 1; + + while ((node->Info & cIsLeafMask) == 0) // go down to a leaf + { + m_Node = node->Child[node->Info & cKeyCountMask]; + node = m_Tree->Read(m_Node); + m_Index = (node->Info & cKeyCountMask) - 1; + } + + return; + } + + while (m_Index == 0) // go up + { + if (m_Node == m_Tree->m_Root) // the root is the top, we cannot go further + { + m_Index = 0xFFFF; + m_Node = 0; + return; + } + + nextnode = node->Parent; + node = m_Tree->Read(nextnode); + m_Index = 0; + + while ((m_Index <= (node->Info & cKeyCountMask)) && (node->Child[m_Index] != m_Node)) + m_Index++; + + m_Node = nextnode; + + if (m_Index > 0) + { + m_Index--; + return; + } + } +} diff --git a/dbx_tree/BlockManager.cpp b/dbx_tree/BlockManager.cpp new file mode 100644 index 0000000..3be5d80 --- /dev/null +++ b/dbx_tree/BlockManager.cpp @@ -0,0 +1,965 @@ +/* + +dbx_tree: tree database driver for Miranda IM + +Copyright 2007-2010 Michael "Protogenes" Kunz, + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "BlockManager.h" +#include "Logger.h" + +CBlockManager::CBlockManager( + CFileAccess & FileAccess, + CEncryptionManager & EncryptionManager + ) +: m_BlockSync(), + m_FileAccess(FileAccess), + m_EncryptionManager(EncryptionManager), + m_BlockTable(1024), + m_FreeBlocks() +{ + m_Optimize.Thread = NULL; + m_Optimize.Source = 0; + m_Optimize.Dest = 0; + + m_CacheInfo.Growth = 0; + m_CacheInfo.Size = 0; + m_CacheInfo.LastPurge = time(NULL); + + m_PendingHead = NULL; + m_PendingTail = NULL; + m_PendingLast = NULL; + m_LastFlush = time(NULL); + m_BytesPending = 20; + m_FirstFreeIndex = 0; + + m_SaveMode = true; + m_ReadOnly = m_FileAccess.ReadOnly(); + + memset(m_Cache, 0, sizeof(m_Cache)); +} + +CBlockManager::~CBlockManager() +{ + m_BlockSync.BeginWrite(); + if (m_Optimize.Thread) + { + m_Optimize.Thread->FreeOnTerminate(false); + m_Optimize.Thread->Terminate(); + + m_BlockSync.EndWrite(); + m_Optimize.Thread->WaitFor(); + + delete m_Optimize.Thread; + } else { + m_BlockSync.EndWrite(); + } + + _PendingFlush(true); + + for (uint32_t buddy = 0; buddy < cCacheBuddyCount; buddy++) + { + TCacheEntry * i = m_Cache[buddy]; + while (i) + { + free(i->Cache); + + TCacheEntry * tmp = i; + i = i->Next; + free(tmp); + } + } +} + +// Optimize File Size +void CBlockManager::ExecuteOptimize() +{ /* + TBlockHeadFree h = {0,0}; + uint8_t * buf = (uint8_t*)malloc(1 << 18); // 256kb + uint32_t bufuse = 0; + uint32_t bufsize = 1 << 18; + uint32_t lastflush = 0; + + { + int i = 0; + while (!m_Optimize.Thread->Terminated() && (i < 600)) + { + ++i; + Sleep(100); // wait for Miranda to start + } + } + + TransactionBeginWrite(); + + while (!m_Optimize.Thread->Terminated() && (m_Optimize.Source < m_FileAccess.Size()) && !m_ReadOnly) + { + m_FileAccess.Read(&h, m_Optimize.Source, sizeof(h)); + if (h.ID == cFreeBlockID) + { + _RemoveFreeBlock(m_Optimize.Source, h.Size); + + m_Optimize.Source += h.Size; + } else { + + if (bufsize < bufuse + h.Size) + { + buf = (uint8_t*)realloc(buf, bufuse + h.Size); + bufsize = bufuse + h.Size; + } + m_FileAccess.Read(buf + bufuse, m_Optimize.Source, h.Size); + + m_BlockTable[h.ID >> 2].Addr = (m_Optimize.Dest + bufuse) >> 2; + + m_Optimize.Source += h.Size; + bufuse += h.Size; + } + + if ((m_BlockSync.Waiting() > 0) + || (bufuse + 1024 >= bufsize) + || (m_Optimize.Source >= m_FileAccess.Size())) // buffer is nearly full or EOF + { + if (m_Optimize.Dest != m_Optimize.Source) // move blocks + { + TBlockHeadFree h = {cFreeBlockID, m_Optimize.Source - m_Optimize.Dest}; + TBlockTailFree t = {m_Optimize.Source - m_Optimize.Dest, cFreeBlockID}; + + m_FileAccess.Write(buf, m_Optimize.Dest, bufuse); + + m_FileAccess.Write(&h, m_Optimize.Dest + bufuse, sizeof(h)); + m_FileAccess.Invalidate(m_Optimize.Dest + bufuse + sizeof(h), m_Optimize.Source - m_Optimize.Dest - bufuse - sizeof(h) - sizeof(t)); + m_FileAccess.Write(&t, m_Optimize.Dest + bufuse - sizeof(t), sizeof(t)); + + if (m_SaveMode) + { + m_FileAccess.CloseTransaction(); + m_FileAccess.Flush(); + m_FileAccess.UseJournal(false); + + m_FileAccess.Write(buf, m_Optimize.Dest, bufuse); + + m_FileAccess.Write(&h, m_Optimize.Dest + bufuse, sizeof(h)); + m_FileAccess.Invalidate(m_Optimize.Dest + bufuse + sizeof(h), m_Optimize.Source - m_Optimize.Dest - bufuse - sizeof(h) - sizeof(t)); + m_FileAccess.Write(&t, m_Optimize.Dest + bufuse - sizeof(t), sizeof(t)); + + m_FileAccess.Flush(); + m_FileAccess.CleanJournal(); + m_FileAccess.UseJournal(true); + } + + m_Optimize.Dest += bufuse; + bufuse = 0; + } + + if (m_BlockSync.Waiting() > 0) + { + unsigned int w = m_BlockSync.Waiting(); + m_BlockSync.EndWrite(); + Sleep(w * 64 + 1); + m_BlockSync.BeginWrite(); + m_FileAccess.UseJournal(m_SaveMode); + } + } + } + + if (m_Optimize.Source >= m_FileAccess.Size()) + m_FileAccess.Size(m_Optimize.Dest); + + m_Optimize.Thread = NULL; + m_Optimize.Source = 0; + m_Optimize.Dest = 0; + if (m_SaveMode) + TransactionEndWrite(); + else + m_BlockSync.EndWrite(); + + free(buf); */ + + m_Optimize.Thread = NULL; +} + +inline void CBlockManager::_PendingAdd(uint32_t BlockID, uint32_t Addr, uint32_t Size, TCacheEntry * Cache) +{ + TPendingOperation * p = NULL; + if (BlockID == cFreeBlockID) + { + p = (TPendingOperation*)malloc(sizeof(TPendingOperation)); + + p->BlockID = cFreeBlockID; + p->Addr = Addr; + p->Size = Size; + p->CacheEntry = NULL; + p->EncryptionBuffer = NULL; + + m_BytesPending += 24 + sizeof(TBlockHeadFree) + sizeof(TBlockTailFree); + if (Addr & cPendingInvalidate) + m_BytesPending += 12; + + } else { + if (Cache->Pending) + { + p = Cache->Pending; + _PendingRemove(Cache->Pending, false); + } else { + p = (TPendingOperation*)malloc(sizeof(TPendingOperation)); + } + + p->BlockID = BlockID; + p->Addr = Addr; + p->Size = Size; + p->CacheEntry = Cache; + p->EncryptionBuffer = NULL; + + m_BytesPending += 12 + Size; + + Cache->Pending = p; + } + + p->Next = NULL; + p->Prev = m_PendingTail; + if (m_PendingTail) + m_PendingTail->Next = p; + + m_PendingTail = p; + if (!m_PendingHead) + m_PendingHead = p; +} + +inline void CBlockManager::_PendingRemove(TPendingOperation * Pending, bool Free) +{ + if (Pending->Prev) + Pending->Prev->Next = Pending->Next; + else + m_PendingHead = Pending->Next; + + if (Pending->Next) + Pending->Next->Prev = Pending->Prev; + else + m_PendingTail = Pending->Prev; + + if (Pending->EncryptionBuffer) + free(Pending->EncryptionBuffer); + + if (m_PendingLast == Pending) + m_PendingLast = Pending->Prev; + + Pending->CacheEntry->Pending = NULL; + if (Free) + free(Pending); +} + +inline void CBlockManager::_PendingFlush(bool FullFlush) +{ + TPendingOperation * i = NULL; + + if (m_ReadOnly) + return; + + if (FullFlush) + { + if (m_SaveMode) + { + _PendingFlush(false); // write to journal + m_FileAccess.Flush(); + m_FileAccess.UseJournal(false); + m_FileAccess.Size(m_FileAccess.Size()); // resize real file + } else { + m_FileAccess.UseJournal(false); + } + + i = m_PendingHead; + } else if (m_PendingLast) + { + i = m_PendingLast->Next; + m_FileAccess.UseJournal(m_SaveMode); + } else { + i = m_PendingHead; + m_FileAccess.UseJournal(m_SaveMode); + } + + while (i) + { + if (i->BlockID == cFreeBlockID) + { + uint32_t addr = i->Addr & ~cPendingInvalidate; + if (addr + i->Size <= m_FileAccess.Size()) + { + TBlockHeadFree h = {cFreeBlockID, i->Size}; + TBlockTailFree t = {i->Size, cFreeBlockID}; + + m_FileAccess.Write(&h, addr, sizeof(h)); + if (i->Addr & cPendingInvalidate) + m_FileAccess.Invalidate(addr + sizeof(h), i->Size - sizeof(h) - sizeof(t)); + m_FileAccess.Write(&t, addr + i->Size - sizeof(t), sizeof(t)); + } + + } else { + + if (i->BlockID && !i->EncryptionBuffer && m_EncryptionManager.IsEncrypted(i->BlockID)) + { + i->EncryptionBuffer = (TBlockHeadOcc*) malloc(i->Size); + memcpy(i->EncryptionBuffer, i->CacheEntry->Cache, i->Size); + m_EncryptionManager.Encrypt(i->EncryptionBuffer + 1, i->Size - sizeof(TBlockHeadOcc) - sizeof(TBlockTailOcc), i->BlockID, 0); + } + + if (i->EncryptionBuffer) + { + m_FileAccess.Write(i->EncryptionBuffer, i->Addr, i->Size); + } else { + m_FileAccess.Write(i->CacheEntry->Cache, i->Addr, i->Size); + } + } + + i = i->Next; + } // while + + if (FullFlush) + { + m_FileAccess.Flush(); + if (m_SaveMode) + m_FileAccess.CleanJournal(); + + m_BytesPending = 20; + m_LastFlush = time(NULL); + + i = m_PendingHead; + while (i) + { + if (i->EncryptionBuffer) + free(i->EncryptionBuffer); + + if (i->CacheEntry) + i->CacheEntry->Pending = NULL; + + TPendingOperation * tmp = i; + i = i->Next; + free(tmp); + } + m_PendingHead = NULL; + m_PendingTail = NULL; + m_PendingLast = NULL; + } else { + m_PendingLast = m_PendingTail; + m_FileAccess.CloseTransaction(); + } +} + +inline CBlockManager::TCacheEntry * CBlockManager::_CacheInsert(uint32_t Idx, TBlockHeadOcc * Cache, bool Virtual) +{ + TCacheEntry * res; + uint32_t myidx = ROR_32(Idx, cCacheBuddyBits); + + res = (TCacheEntry *)malloc(sizeof(TCacheEntry)); + res->Cache = Cache; + res->Pending = NULL; + res->Idx = myidx; + res->Forced = Virtual; + + TCacheEntry * volatile * last = &m_Cache[Idx % cCacheBuddyCount]; + TCacheEntry * i; + do { + i = *last; + + while (i && (i->Idx < myidx)) + { + last = &i->Next; + i = i->Next; + } + + if (i && (i->Idx == myidx)) + { + free(res); + free(Cache); + + i->LastUse = time(NULL) >> 2; + return i; + } + + res->Next = i; + + } while (i != CMPXCHG_Ptr(*last, res, i) ); + + res->LastUse = time(NULL) >> 2; + + m_BlockTable[Idx].InCache = true; + if (!Virtual) + XADD_32(m_CacheInfo.Growth, res->Cache->Size); + + return res; +} + +inline CBlockManager::TCacheEntry * CBlockManager::_CacheFind(uint32_t Idx) +{ + TCacheEntry * i = m_Cache[Idx % cCacheBuddyCount]; + uint32_t myidx = ROR_32(Idx, cCacheBuddyBits); + while (i && (i->Idx < myidx)) + i = i->Next; + + if (i && (i->Idx == myidx)) + return i; + else + return NULL; +} + +inline void CBlockManager::_CacheErase(uint32_t Idx) +{ + TCacheEntry * i = m_Cache[Idx % cCacheBuddyCount]; + TCacheEntry * volatile * l = &m_Cache[Idx % cCacheBuddyCount]; + + uint32_t myidx = ROR_32(Idx, cCacheBuddyBits); + + while (i->Idx < myidx) + { + l = &i->Next; + i = i->Next; + } + *l = i->Next; + + if (i->Cache) + free(i->Cache); + free(i); +} + +inline void CBlockManager::_CachePurge() +{ + _PendingFlush(true); + + uint32_t ts = time(NULL); + if (m_CacheInfo.Size + m_CacheInfo.Growth > cCachePurgeSize) { + ts = ts - (ts - m_CacheInfo.LastPurge) * cCachePurgeSize / (m_CacheInfo.Size + 2 * m_CacheInfo.Growth); + } else if (m_CacheInfo.Growth > m_CacheInfo.Size) + { + ts = ts - (ts - m_CacheInfo.LastPurge) * m_CacheInfo.Size / m_CacheInfo.Growth; + } else if (m_CacheInfo.Size > m_CacheInfo.Growth) + { + ts = ts - (ts - m_CacheInfo.LastPurge) * m_CacheInfo.Growth / m_CacheInfo.Size; + } else { + ts = m_CacheInfo.LastPurge; + } + + m_CacheInfo.Size += m_CacheInfo.Growth; + m_CacheInfo.Growth = 0; + m_CacheInfo.LastPurge = time(NULL); + + for (uint32_t buddy = 0; buddy < cCacheBuddyCount; buddy++) + { + TCacheEntry * i = m_Cache[buddy]; + TCacheEntry * volatile * l = &m_Cache[buddy]; + + while (i) + { + if (!i->Forced && !i->KeepInCache && i->Idx && ((i->LastUse << 2) < ts)) + { + uint32_t idx = ROL_32(i->Idx, cCacheBuddyBits); + m_CacheInfo.Size -= i->Cache->Size; + m_BlockTable[idx].InCache = false; + free(i->Cache); + + *l = i->Next; + TCacheEntry * tmp = i; + i = i->Next; + free(tmp); + + } else { + l = &i->Next; + i = i->Next; + } + } + } +} + +inline uint32_t CBlockManager::_GetAvailableIndex() +{ + uint32_t id; + if (m_FirstFreeIndex) + { + id = m_FirstFreeIndex; + m_FirstFreeIndex = m_BlockTable[id].Addr; + TBlockTableEntry b = {false, false, 0}; + m_BlockTable[id] = b; + } else { + id = static_cast(m_BlockTable.size()); + if (id > (1 << 12)) + m_BlockTable.resize(id + (1 << 12)); + else + m_BlockTable.resize(id * 2); + + for (uint32_t i = static_cast(m_BlockTable.size() - 1); i > id; --i) + { + TBlockTableEntry b = {true, true, m_FirstFreeIndex}; + m_BlockTable[i] = b; + m_FirstFreeIndex = i; + } + } + return id; +} + +inline void CBlockManager::_InsertFreeBlock(uint32_t Addr, uint32_t Size, bool InvalidateData, bool Reuse) +{ + if (Addr + Size == m_FileAccess.Size()) + { + if (Reuse) // in FindFreePosition we would want to use that block + m_FileAccess.Size(Addr); + } else { + + if (Reuse) + m_FreeBlocks.insert(std::make_pair(Size, Addr)); + + if (!m_ReadOnly) + _PendingAdd(cFreeBlockID, InvalidateData ? Addr | cPendingInvalidate : Addr, Size, NULL); + + } +} + +inline void CBlockManager::_RemoveFreeBlock(uint32_t Addr, uint32_t Size) +{ + TFreeBlockMap::iterator i = m_FreeBlocks.find(Size); + while ((i != m_FreeBlocks.end()) && (i->first == Size)) + { + if (i->second == Addr) + { + m_FreeBlocks.erase(i); + i = m_FreeBlocks.end(); + } else { + ++i; + } + } +} + +inline uint32_t CBlockManager::_FindFreePosition(uint32_t Size) +{ + // try to find free block + TFreeBlockMap::iterator f; + TFreeBlockMap::iterator e = m_FreeBlocks.end(); + + if (m_FreeBlocks.size()) + { + f = m_FreeBlocks.find(Size); + if (f == e) + { + if (m_FreeBlocks.rbegin()->first > Size * 2) + { + f = m_FreeBlocks.end(); + --f; + } + } + } else { + f = e; + } + + uint32_t addr = 0; + + if (f == e) // no block found - expand file + { + addr = m_FileAccess.Size(); + m_FileAccess.Size(addr + Size); + + } else { + addr = f->second; + + if (f->first != Size) + { + _InsertFreeBlock(addr + Size, f->first - Size, false, true); + } + _InsertFreeBlock(addr, Size, false, false); + + m_FreeBlocks.erase(f); + } + + return addr; +} + +inline bool CBlockManager::_InitOperation(uint32_t BlockID, uint32_t & Addr, TCacheEntry * & Cache) +{ + if (!BlockID || (BlockID & 3) || ((BlockID >> 2) >= m_BlockTable.size())) + return false; + + uint32_t idx = BlockID >> 2; + TBlockTableEntry dat = m_BlockTable[idx]; + + if (dat.Deleted) // deleted or FreeIDList item + return false; + + Addr = dat.Addr << 2; + if (dat.InCache) + { + Cache = _CacheFind(idx); + } else if (Addr) + { + TBlockHeadOcc h; + + m_FileAccess.Read(&h, Addr, sizeof(h)); + + TBlockHeadOcc * block = (TBlockHeadOcc *) malloc(h.Size); + m_FileAccess.Read(block, Addr, h.Size); + + m_EncryptionManager.Decrypt(block + 1, h.Size - sizeof(TBlockHeadOcc) - sizeof(TBlockTailOcc), BlockID, 0); + + Cache = _CacheInsert(idx, block, false); + } else { + return false; + } + + return Cache != NULL; +} + +inline void CBlockManager::_UpdateBlock(uint32_t BlockID, TCacheEntry * CacheEntry, uint32_t Addr) +{ + CacheEntry->KeepInCache = m_ReadOnly; + + if (!CacheEntry->Forced) + { + if (!m_ReadOnly) + _PendingAdd(BlockID, Addr, CacheEntry->Cache->Size, CacheEntry); + } +} + + +uint32_t CBlockManager::ScanFile(uint32_t FirstBlockStart, uint32_t HeaderSignature, uint32_t FileSize) +{ + TBlockHeadOcc h, lasth = {0, 0, 0}; + uint32_t p; + uint32_t res = 0; + bool invalidateblock = false; + + p = FirstBlockStart; + m_FirstBlockStart = FirstBlockStart; + m_Optimize.Source = 0; + m_Optimize.Dest = 0; + + { // insert header cache element + void * header = malloc(FirstBlockStart); + m_FileAccess.Read(header, 0, FirstBlockStart); + _CacheInsert(0, (TBlockHeadOcc*)header, false); + } + + TransactionBeginWrite(); + + while (p < FileSize) + { + m_FileAccess.Read(&h, p, sizeof(h)); + if (CLogger::Instance().Level() >= CLogger::logERROR || !h.Size) + { + LOG(logCRITICAL, _T("Block-structure of file is corrupt!")); + return 0; + } + + if (h.ID == cFreeBlockID) + { + if (m_Optimize.Dest == 0) + m_Optimize.Dest = p; + + if (lasth.ID == cFreeBlockID) + { + lasth.Size += h.Size; + invalidateblock = true; + } else { + lasth = h; + } + + } else { + + if (lasth.ID == cFreeBlockID) + { + if (m_Optimize.Source == 0) + m_Optimize.Source = p; + + _InsertFreeBlock(p - lasth.Size, lasth.Size, invalidateblock, true); + } + lasth = h; + invalidateblock = false; + + while ((h.ID >> 2) >= m_BlockTable.size()) + m_BlockTable.resize(m_BlockTable.size() << 1); + + m_BlockTable[h.ID >> 2].Addr = p >> 2; + + if (h.Signature == HeaderSignature) + res = h.ID; + } + + p = p + h.Size; + } + + m_FirstFreeIndex = 0; + for (uint32_t i = static_cast(m_BlockTable.size() - 1); i > 0; --i) + { + if (m_BlockTable[i].Addr == 0) + { + TBlockTableEntry b = {true, true, m_FirstFreeIndex}; + m_BlockTable[i] = b; + m_FirstFreeIndex = i; + } + } + + TransactionEndWrite(); + + if (m_Optimize.Source && !m_FileAccess.ReadOnly()) + { + m_Optimize.Thread = new COptimizeThread(*this); + m_Optimize.Thread->Priority(CThread::tpLowest); + m_Optimize.Thread->FreeOnTerminate(true); + m_Optimize.Thread->Resume(); + } + + return res; +} + +void * CBlockManager::_CreateBlock(uint32_t & BlockID, const uint32_t Signature, uint32_t Size) +{ + uint32_t idx = _GetAvailableIndex(); + BlockID = idx << 2; + + Size = m_EncryptionManager.AlignSize(BlockID, (Size + 3) & 0xfffffffc); // align on cipher after we aligned on 4 bytes + + TBlockHeadOcc h = {BlockID, Size + sizeof(TBlockHeadOcc) + sizeof(TBlockTailOcc), Signature}; + TBlockTailOcc t = {BlockID}; + + TBlockHeadOcc * block = (TBlockHeadOcc*) malloc(Size + sizeof(h) + sizeof(t)); + *block = h; + memset(block + 1, 0, Size); + *(TBlockTailOcc*)(((uint8_t*)(block + 1)) + Size) = t; + + TCacheEntry * ce = _CacheInsert(idx, block, false); + + if (m_ReadOnly) + { + TBlockTableEntry b = {false, true, 0}; + m_BlockTable[idx] = b; + } else { + uint32_t addr = _FindFreePosition(Size + sizeof(h) + sizeof(t)); + TBlockTableEntry b = {false, true, addr >> 2 }; + m_BlockTable[idx] = b; + + _UpdateBlock(BlockID, ce, addr); + } + + return ce->Cache + 1; +} + +void * CBlockManager::_CreateBlockVirtual(uint32_t & BlockID, const uint32_t Signature, uint32_t Size) +{ + uint32_t idx = _GetAvailableIndex(); + BlockID = idx << 2; + + Size = m_EncryptionManager.AlignSize(BlockID, (Size + 3) & 0xfffffffc); // align on cipher after we aligned on 4 bytes + + TBlockHeadOcc h = {BlockID, Size + sizeof(TBlockHeadOcc) + sizeof(TBlockTailOcc), Signature}; + TBlockTailOcc t = {BlockID}; + + TBlockHeadOcc * block = (TBlockHeadOcc*) malloc(Size + sizeof(h) + sizeof(t)); + *block = h; + memset(block + 1, 0, Size); + *(TBlockTailOcc*)(((uint8_t*)(block + 1)) + Size) = t; + + return _CacheInsert(idx, block, true)->Cache + 1; +} + +bool CBlockManager::DeleteBlock(uint32_t BlockID) +{ + uint32_t idx = BlockID >> 2; + uint32_t addr; + uint32_t size; + TCacheEntry * ce; + if (!_InitOperation(BlockID, addr, ce)) + return false; + + if (!ce->Forced) + XADD_32(m_CacheInfo.Size, 0 - ce->Cache->Size); + + if (ce->Pending) + _PendingRemove(ce->Pending, true); + + size = ce->Cache->Size; + _CacheErase(idx); + + if (addr == 0) // Block in memory only + { + TBlockTableEntry b = {false, false, 0}; + m_BlockTable[idx] = b; + + } else if (m_ReadOnly) + { + m_BlockTable[idx].Deleted = true; + m_BlockTable[idx].InCache = false; + } else { + _InsertFreeBlock(addr, size, true, true); + + TBlockTableEntry b = {false, false, 0}; + m_BlockTable[idx] = b; + } + + return true; +} + +uint32_t CBlockManager::_ResizeBlock(uint32_t BlockID, void * & Buffer, uint32_t Size) +{ + uint32_t idx = BlockID >> 2; + uint32_t addr; + TCacheEntry * ce; + + if (Size == 0) + return 0; + + if (!_InitOperation(BlockID, addr, ce)) + return 0; + + Size = m_EncryptionManager.AlignSize(BlockID, (Size + 3) & 0xfffffffc); // align on cipher after we aligned on 4 bytes + + uint32_t os = ce->Cache->Size; + uint32_t ns = Size + sizeof(TBlockHeadOcc) + sizeof(TBlockTailOcc); + if (ns == ce->Cache->Size) + { + Buffer = ce->Cache + 1; + return Size; + } + + ce->Cache = (TBlockHeadOcc*) realloc(ce->Cache, ns); + ce->Cache->Size = ns; + TBlockTailOcc t = {BlockID}; + *(TBlockTailOcc*)(((uint8_t*)(ce->Cache + 1)) + Size) = t; + XADD_32(m_CacheInfo.Size, ns - os); + + Buffer = ce->Cache + 1; + ce->KeepInCache = m_ReadOnly; + + if (!m_ReadOnly && addr) + { + _InsertFreeBlock(addr, os, true, true); + addr = _FindFreePosition(ns); + m_BlockTable[idx].Addr = addr >> 2; + + _UpdateBlock(BlockID, ce, addr); // write down + } + + return Size; +} + +bool CBlockManager::IsForcedVirtual(uint32_t BlockID) +{ + TCacheEntry * ce = _CacheFind(BlockID >> 2); + return ce && ce->Forced; +} + +bool CBlockManager::WriteBlockToDisk(uint32_t BlockID) +{ + uint32_t addr; + TCacheEntry * ce; + + if (!_InitOperation(BlockID, addr, ce)) + return false; + + if (!ce->Forced) + return true; + + ce->Forced = false; + XADD_32(m_CacheInfo.Size, ce->Cache->Size); + + if (!m_ReadOnly) + { + addr = _FindFreePosition(ce->Cache->Size); + m_BlockTable[BlockID >> 2].Addr = addr >> 2; + _UpdateBlock(BlockID, ce, addr); + } + return true; +} + +bool CBlockManager::MakeBlockVirtual(uint32_t BlockID) +{ + uint32_t addr; + TCacheEntry * ce; + + if (!_InitOperation(BlockID, addr, ce)) + return false; + + if (ce->Forced) + return true; + + if (ce->Pending) // don't write down, we kill it anyway + _PendingRemove(ce->Pending, true); + + ce->Forced = true; + XADD_32(m_CacheInfo.Size, 0 - ce->Cache->Size); + + if (!m_ReadOnly) + { + _InsertFreeBlock(addr, ce->Cache->Size, true, true); + m_BlockTable[BlockID >> 2].Addr = 0; + } + return true; +} + +void * CBlockManager::_ReadBlock(uint32_t BlockID, uint32_t & Size, uint32_t & Signature) +{ + uint32_t addr; + TCacheEntry * ce; + + if ((BlockID == 0) && (Signature == -1)) + { + Size = m_FirstBlockStart; + return m_Cache[0]->Cache; + } + + if (!_InitOperation(BlockID, addr, ce)) + return NULL; + + if ((Signature != 0) && (Signature != ce->Cache->Signature)) + { + Signature = ce->Cache->Signature; + return NULL; + } + Signature = ce->Cache->Signature; + + if ((Size != 0) && (Size != ce->Cache->Size - sizeof(TBlockHeadOcc) - sizeof(TBlockTailOcc))) + { + Size = ce->Cache->Size - sizeof(TBlockHeadOcc) - sizeof(TBlockTailOcc); + return NULL; + } + Size = ce->Cache->Size - sizeof(TBlockHeadOcc) - sizeof(TBlockTailOcc); + + return ce->Cache + 1; +} + +bool CBlockManager::UpdateBlock(uint32_t BlockID, uint32_t Signature) +{ + uint32_t addr; + TCacheEntry * ce; + + if ((BlockID == 0) && (Signature == -1)) + { + if (!m_ReadOnly) + _PendingAdd(0, 0, m_FirstBlockStart, m_Cache[0]); + + return true; + } + + if (!_InitOperation(BlockID, addr, ce)) + return false; + + if (Signature) + ce->Cache->Signature = Signature; + + _UpdateBlock(BlockID, ce, addr); + + return true; +} + +// make file writeable: +// write all cached blocks to file and check for the old addresses +// remove virtual only from file +// update m_FreeBlocks along the way + diff --git a/dbx_tree/BlockManager.h b/dbx_tree/BlockManager.h new file mode 100644 index 0000000..dcccd4f --- /dev/null +++ b/dbx_tree/BlockManager.h @@ -0,0 +1,401 @@ +/* + +dbx_tree: tree database driver for Miranda IM + +Copyright 2007-2010 Michael "Protogenes" Kunz, + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#pragma once + +#include +#include +#include + +#include "stdint.h" +#include "FileAccess.h" +#include "EncryptionManager.h" +#include "MREWSync.h" +#include "Thread.h" +#include "intrinsics.h" + +class CBlockManager +{ +protected: + static const uint32_t cFreeBlockID = 0xFFFFFFFF; + + static const uint32_t cJournalFlushBytes = (1 << 20) - 2048; // flush before reserved journal-space is exhausted + static const uint32_t cJournalFlushTimeout = 300; // journal flush every 5 minutes + + static const uint32_t cCacheBuddyBits = 10; + static const uint32_t cCacheBuddyCount = 1 << cCacheBuddyBits; // count of static allocated buddy nodes + static const uint32_t cCacheBuddyCheck = 0xffffffff << cCacheBuddyBits; + + static const uint32_t cCacheMinimumTimeout = 2; // purge less than every n seconds (high priority) + static const uint32_t cCacheMaximumTimeout = 600; // purge every 10 minutes (high priority) + static const uint32_t cCachePurgeSize = 1 << 21; // cache up to 2MB + static const uint32_t cCacheMinimumGrowthForPurge = 1 << 19; // cache only when 512kb were added + + #pragma pack(push, 1) // push current alignment to stack, set alignment to 1 byte boundary + + typedef struct TBlockHeadFree { + uint32_t ID; + uint32_t Size; + } TBlockHeadFree; + typedef struct TBlockHeadOcc { + uint32_t ID; + uint32_t Size; + uint32_t Signature; /// if occupied block + } TBlockHeadOcc; + + typedef struct TBlockTailOcc { + uint32_t ID; + } TBlockTailOcc; + + typedef struct TBlockTailFree { + uint32_t Size; /// if free block + uint32_t ID; + } TBlockTailFree; + + #pragma pack(pop) + + //////////////////////////////////////////////////////////////////////////////////////////////////// + /// Block table entry. + /// + /// Addr Deleted InCache Meaning + /// 0 0 0 successfully deleted block + /// 0 0 1 virtual only block (either forced virtual or created on a read-only file) + /// 0 1 0 invalid + /// 0 1 1 FreeID list (last entry) + /// set 0 0 Normal in-file block + /// set 0 1 in file and cache (normal cache which could differ on a read-only file or forced virtual out of a read-only file - check TCacheEntry) + /// set 1 0 deleted block or a read-only file + /// set 1 1 FreeID list entry + /// + /// Michael "Protogenes" Kunz, 07.09.2010. + //////////////////////////////////////////////////////////////////////////////////////////////////// + typedef struct TBlockTableEntry { + uint32_t Deleted : 1; ///< Flag is set if the block was deleted but can't be removed, because the file is read-only + uint32_t InCache : 1; ///< Flag is set if block is in the cache (either forced virtual or from the file) + uint32_t Addr : 30; ///< The Offset in the file div 4, so we can address files up to 4GB + } TBlockTableEntry; + std::vector m_BlockTable; + + struct TPendingOperation; + typedef struct TCacheEntry { + TCacheEntry * volatile Next; + TBlockHeadOcc * volatile Cache; + TPendingOperation * Pending; + + uint32_t Idx; + uint32_t Forced : 1; + uint32_t KeepInCache : 1; + uint32_t LastUse : 30; + } TCacheEntry; + + TCacheEntry * m_Cache[cCacheBuddyCount]; + + struct { + uint32_t volatile Size; + uint32_t volatile Growth; + uint32_t volatile LastPurge; + } m_CacheInfo; + + CFileAccess & m_FileAccess; + CEncryptionManager & m_EncryptionManager; + CMultiReadExclusiveWriteSynchronizer m_BlockSync; + + uint32_t m_FirstBlockStart; + bool m_SaveMode; + bool m_ReadOnly; + + typedef std::multimap TFreeBlockMap; + TFreeBlockMap m_FreeBlocks; + uint32_t m_FirstFreeIndex; + + static const uint32_t cPendingInvalidate = 0x00000001; + typedef struct TPendingOperation { + TPendingOperation * Next; ///< The next + TPendingOperation * Prev; ///< The previous + uint32_t BlockID; ///< Identifier for the block + uint32_t Addr; ///< The address in the file + uint32_t Size; ///< The size of the block + TCacheEntry * CacheEntry; ///< The cache entry + TBlockHeadOcc * EncryptionBuffer; ///< Buffer for encrypted block + } TPendingOperation; + + TPendingOperation * m_PendingHead; ///< The double linked list head + TPendingOperation * m_PendingTail; ///< The double linked list tail + TPendingOperation * m_PendingLast; ///< The last processed item + + uint32_t m_LastFlush; ///< The last flush timestamp + uint32_t m_BytesPending; ///< The bytes pending for write + + class COptimizeThread : public CThread + { + protected: + CBlockManager & m_Owner; + void Execute() { m_Owner.ExecuteOptimize(); }; + public: + COptimizeThread(CBlockManager & Owner) : CThread(true), m_Owner(Owner) {}; + ~COptimizeThread() {}; + }; + + struct { + uint32_t Source; + uint32_t Dest; + COptimizeThread * Thread; + } m_Optimize; + void ExecuteOptimize(); + + uint32_t _GetAvailableIndex(); + void _InsertFreeBlock(uint32_t Addr, uint32_t Size, bool InvalidateData, bool Reuse); + void _RemoveFreeBlock(uint32_t Addr, uint32_t Size); + uint32_t _FindFreePosition(uint32_t Size); + + bool _InitOperation(uint32_t BlockID, uint32_t & Addr, TCacheEntry * & Cache); + void _UpdateBlock(uint32_t BlockID, TCacheEntry * CacheEntry, uint32_t Addr); + + void * _ReadBlock(uint32_t BlockID, uint32_t & Size, uint32_t & Signature); + void * _CreateBlock(uint32_t & BlockID, const uint32_t Signature, uint32_t Size); + void * _CreateBlockVirtual(uint32_t & BlockID, const uint32_t Signature, uint32_t Size); + uint32_t _ResizeBlock(uint32_t BlockID, void * & Buffer, uint32_t Size); + + TCacheEntry * _CacheInsert(uint32_t Idx, TBlockHeadOcc * Cache, bool Virtual); + TCacheEntry * _CacheFind(uint32_t Idx); + void _CacheErase(uint32_t Idx); + + void _CachePurge(); + void _PendingAdd(uint32_t BlockID, uint32_t Addr, uint32_t Size, TCacheEntry * Cache); + void _PendingRemove(TPendingOperation * Pending, bool Free); + void _PendingFlush(bool FullFlush); + + + + void TransactionBeginRead() + { + m_BlockSync.BeginRead(); + }; + + void TransactionEndRead() + { + m_BlockSync.EndRead(); + }; + + void TransactionBeginWrite() + { + m_BlockSync.BeginWrite(); + m_FileAccess.UseJournal(m_SaveMode); + }; + + void TransactionEndWrite() + { + if (m_BlockSync.WriteRecursionCount() == 1) + { + m_FileAccess.CompleteTransaction(); + m_BytesPending += 12; + + if ((m_CacheInfo.LastPurge + cCacheMaximumTimeout < time(NULL)) + || ((m_CacheInfo.Size + m_CacheInfo.Growth > cCachePurgeSize) + && (m_CacheInfo.Growth > cCacheMinimumGrowthForPurge) + && (m_CacheInfo.LastPurge + cCacheMinimumTimeout < time(NULL)))) + { + _CachePurge(); + } else if ((m_BytesPending >= cJournalFlushBytes) || (time(NULL) > m_LastFlush + cJournalFlushTimeout)) + { + _PendingFlush(true); + } else { + _PendingFlush(false); + } + } + + m_BlockSync.EndWrite(); + }; +public: + CBlockManager(CFileAccess & FileAccess, CEncryptionManager & EncryptionManager); + ~CBlockManager(); + + + class ReadTransaction + { + private: + CBlockManager * m_Owner; + uint32_t volatile * m_RefCount; + bool m_Closed; + public: + ReadTransaction() + : m_Owner(NULL), + m_RefCount(NULL), + m_Closed(true) + { + + }; + ReadTransaction(CBlockManager & BlockManager) + : m_Owner(&BlockManager), + m_RefCount(new uint32_t(1)), + m_Closed(false) + { + m_Owner->TransactionBeginRead(); + }; + ReadTransaction(const ReadTransaction & Other) + : m_Owner(Other.m_Owner), + m_RefCount(Other.m_RefCount), + m_Closed(Other.m_Closed) + { + if (!m_Closed) + INC_32(*m_RefCount); + }; + ~ReadTransaction() + { + if (!m_Closed && (DEC_32(*m_RefCount) == 0)) + { + delete m_RefCount; + m_Owner->TransactionEndRead(); + } + }; + + ReadTransaction & operator =(const ReadTransaction & Other) + { + if (!m_Closed && (DEC_32(*m_RefCount) == 0)) + { + delete m_RefCount; + m_Owner->TransactionEndRead(); + } + + m_Owner = Other.m_Owner; + m_RefCount = Other.m_RefCount; + m_Closed = Other.m_Closed; + if (!m_Closed) + INC_32(*m_RefCount); + + return *this; + } + + void Close() + { + if (!m_Closed && (DEC_32(*m_RefCount) == 0)) + { + delete m_RefCount; + m_Owner->TransactionEndRead(); + } + m_Closed = true; + } + + }; + class WriteTransaction + { + private: + CBlockManager * m_Owner; + uint32_t volatile * m_RefCount; + bool m_Closed; + public: + WriteTransaction() + : m_Owner(NULL), + m_RefCount(NULL), + m_Closed(true) + { + + }; + WriteTransaction(CBlockManager & BlockManager) + : m_Owner(&BlockManager), + m_RefCount(new uint32_t(1)), + m_Closed(false) + { + m_Owner->TransactionBeginWrite(); + }; + WriteTransaction(const WriteTransaction & Other) + : m_Owner(Other.m_Owner), + m_RefCount(Other.m_RefCount), + m_Closed(Other.m_Closed) + { + if (!m_Closed) + INC_32(*m_RefCount); + }; + ~WriteTransaction() + { + if (!m_Closed && (DEC_32(*m_RefCount) == 0)) + { + delete m_RefCount; + m_Owner->TransactionEndWrite(); + } + }; + + WriteTransaction & operator =(const WriteTransaction & Other) + { + if (!m_Closed && (DEC_32(*m_RefCount) == 0)) + { + delete m_RefCount; + m_Owner->TransactionEndWrite(); + } + + m_Owner = Other.m_Owner; + m_RefCount = Other.m_RefCount; + m_Closed = Other.m_Closed; + if (!m_Closed) + INC_32(*m_RefCount); + + return *this; + } + + void Close() + { + if (!m_Closed && (DEC_32(*m_RefCount) == 0)) + { + delete m_RefCount; + m_Owner->TransactionEndWrite(); + } + m_Closed = true; + } + + }; + + uint32_t ScanFile(uint32_t FirstBlockStart, uint32_t HeaderSignature, uint32_t FileSize); + + template + BlockType * ReadBlock(uint32_t BlockID, uint32_t & Size, uint32_t & Signature) + { + return reinterpret_cast(_ReadBlock(BlockID, Size, Signature)); + }; + + template + BlockType * CreateBlock(uint32_t & BlockID, const uint32_t Signature, uint32_t Size = sizeof(BlockType)) + { + return reinterpret_cast(_CreateBlock(BlockID, Signature, Size)); + }; + + template + BlockType * CreateBlockVirtual(uint32_t & BlockID, const uint32_t Signature, uint32_t Size = sizeof(BlockType)) + { + return reinterpret_cast(_CreateBlockVirtual(BlockID, Signature, Size)); + }; + + template + uint32_t ResizeBlock(uint32_t BlockID, BlockType * & Buffer, uint32_t Size) + { + void * tmp = Buffer; + uint32_t res = _ResizeBlock(BlockID, tmp, Size); + Buffer = reinterpret_cast(tmp); + return res; + }; + + bool UpdateBlock(uint32_t BlockID, uint32_t Signature = 0); + bool DeleteBlock(uint32_t BlockID); + + bool IsForcedVirtual(uint32_t BlockID); + bool WriteBlockToDisk(uint32_t BlockID); + bool MakeBlockVirtual(uint32_t BlockID); +}; diff --git a/dbx_tree/Compatibility.cpp b/dbx_tree/Compatibility.cpp new file mode 100644 index 0000000..38b8f92 --- /dev/null +++ b/dbx_tree/Compatibility.cpp @@ -0,0 +1,866 @@ +/* + +dbx_tree: tree database driver for Miranda IM + +Copyright 2007-2010 Michael "Protogenes" Kunz, + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "Compatibility.h" +#include "Logger.h" +#define DB_NOHELPERFUNCTIONS + #include "m_database.h" +#undef DB_NOHELPERFUNCTIONS +#ifndef _MSC_VER +#include "savestrings_gcc.h" +#endif + +HANDLE gCompServices[31] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +HANDLE gEvents[6] = {0,0,0,0,0,0}; + +HANDLE hEventDeletedEvent, + hEventAddedEvent, + hEventFilterAddedEvent, + hSettingChangeEvent, + hContactDeletedEvent, + hContactAddedEvent; + +INT_PTR CompAddContact(WPARAM wParam, LPARAM lParam) +{ + TDBTEntity entity = {0,0,0,0}; + entity.hParentEntity = DBEntityGetRoot(0, 0); + entity.hAccountEntity = entity.hParentEntity; + + TDBTEntityHandle res = gDataBase->getEntities().CreateEntity(entity); + if (res == DBT_INVALIDPARAM) + return 1; + + NotifyEventHooks(hContactAddedEvent, res, 0); + return res; +} +INT_PTR CompDeleteContact(WPARAM hContact, LPARAM lParam) +{ + NotifyEventHooks(hContactDeletedEvent, hContact, 0); + + int res = DBEntityDelete(hContact, 0); + if (res == DBT_INVALIDPARAM) + return 1; + + return res; +} +INT_PTR CompIsDbContact(WPARAM hContact, LPARAM lParam) +{ + int flags = DBEntityGetFlags(hContact, 0); + return (flags != DBT_INVALIDPARAM) && + ((flags & DBT_NFM_SpecialEntity) == 0); +} +INT_PTR CompGetContactCount(WPARAM wParam, LPARAM lParam) +{ + TDBTEntityIterFilter f = {0,0,0,0}; + f.cbSize = sizeof(f); + f.fDontHasFlags = DBT_NF_IsGroup | DBT_NF_IsVirtual | DBT_NF_IsAccount | DBT_NF_IsRoot; + f.Options = DBT_NIFO_OSC_AC | DBT_NIFO_OC_AC; + + TDBTEntityIterationHandle hiter = DBEntityIterInit((WPARAM)&f, gDataBase->getEntities().getRootEntity()); + int c = 0; + if ((hiter != 0) && (hiter != DBT_INVALIDPARAM)) + { + TDBTEntityHandle con = DBEntityIterNext(hiter, 0); + + while ((con != DBT_INVALIDPARAM) && (con != 0)) + { + if ((con != 0) && (con != DBT_INVALIDPARAM)) + c++; + + con = DBEntityIterNext(hiter, 0); + } + DBEntityIterClose(hiter, 0); + } + return c; +} +INT_PTR CompFindFirstContact(WPARAM wParam, LPARAM lParam) +{ + return gDataBase->getEntities().compFirstContact(); +} +INT_PTR CompFindNextContact(WPARAM hContact, LPARAM lParam) +{ + return gDataBase->getEntities().compNextContact(hContact); +} + +INT_PTR CompGetContactSetting(WPARAM hContact, LPARAM pSetting) +{ + DBCONTACTGETSETTING * dbcgs = reinterpret_cast(pSetting); + dbcgs->pValue->type = 0; + + char namebuf[512]; + namebuf[0] = 0; + + if (!(dbcgs->szModule || dbcgs->szSetting)) + return -1; + + if (dbcgs->szModule) + strcpy_s(namebuf, dbcgs->szModule); + strcat_s(namebuf, "/"); + if (dbcgs->szSetting) + strcat_s(namebuf, dbcgs->szSetting); + + TDBTSettingDescriptor desc = {0,0,0,0,0,0,0,0}; + TDBTSetting set = {0,0,0,0}; + desc.cbSize = sizeof(desc); + desc.Entity = hContact; + desc.pszSettingName = namebuf; + + set.cbSize = sizeof(set); + set.Descriptor = &desc; + + if (DBSettingRead(reinterpret_cast(&set), 0) == DBT_INVALIDPARAM) + return -1; + + switch (set.Type) + { + case DBT_ST_ANSI: + { + dbcgs->pValue->type = DBVT_ASCIIZ; + dbcgs->pValue->pszVal = set.Value.pAnsi; + dbcgs->pValue->cchVal = set.Value.Length - 1; + } break; + case DBT_ST_UTF8: + { + dbcgs->pValue->type = DBVT_WCHAR; + dbcgs->pValue->pwszVal = mir_utf8decodeW(set.Value.pUTF8); + if (dbcgs->pValue->pwszVal) + dbcgs->pValue->cchVal = static_cast(wcslen(dbcgs->pValue->pwszVal)); + else + dbcgs->pValue->cchVal = 0; + mir_free(set.Value.pUTF8); + } break; + case DBT_ST_WCHAR: + { + dbcgs->pValue->type = DBVT_WCHAR; + dbcgs->pValue->pwszVal = set.Value.pWide; + dbcgs->pValue->cchVal = set.Value.Length - 1; + } break; + case DBT_ST_BLOB: + { + dbcgs->pValue->type = DBVT_BLOB; + dbcgs->pValue->pbVal = set.Value.pBlob; + dbcgs->pValue->cpbVal = set.Value.Length; + } break; + case DBT_ST_BOOL: + { + dbcgs->pValue->type = DBVT_BYTE; + dbcgs->pValue->bVal = (uint8_t)set.Value.Bool; + } break; + case DBT_ST_BYTE: case DBT_ST_CHAR: + { + dbcgs->pValue->type = DBVT_BYTE; + dbcgs->pValue->bVal = set.Value.Byte; + } break; + case DBT_ST_SHORT: case DBT_ST_WORD: + { + dbcgs->pValue->type = DBVT_WORD; + dbcgs->pValue->wVal = set.Value.Word; + } break; + case DBT_ST_INT: case DBT_ST_DWORD: + { + dbcgs->pValue->type = DBVT_DWORD; + dbcgs->pValue->dVal = set.Value.DWord; + } break; + case DBT_ST_INT64: case DBT_ST_QWORD: + case DBT_ST_DOUBLE: case DBT_ST_FLOAT: + { + dbcgs->pValue->type = DBVT_BLOB; + dbcgs->pValue->cpbVal = sizeof(set.Value); + dbcgs->pValue->pbVal = reinterpret_cast(mir_alloc(sizeof(set.Value))); + memcpy(dbcgs->pValue->pbVal, &set.Value, sizeof(set.Value)); + } break; + default: + { + return -1; + } + } + + return 0; +} +INT_PTR CompGetContactSettingStr(WPARAM hContact, LPARAM pSetting) +{ + DBCONTACTGETSETTING * dbcgs = reinterpret_cast(pSetting); + + if ((dbcgs->pValue->type & DBVTF_VARIABLELENGTH) == 0) + { + CompFreeVariant(0, reinterpret_cast(dbcgs->pValue)); + dbcgs->pValue->type = 0; + } + + char namebuf[512]; + namebuf[0] = 0; + if (dbcgs->szModule) + strcpy_s(namebuf, dbcgs->szModule); + strcat_s(namebuf, "/"); + if (dbcgs->szSetting) + strcat_s(namebuf, dbcgs->szSetting); + + TDBTSettingDescriptor desc = {0,0,0,0,0,0,0,0}; + TDBTSetting set = {0,0,0,0}; + desc.cbSize = sizeof(desc); + desc.Entity = hContact; + desc.pszSettingName = namebuf; + + set.cbSize = sizeof(set); + set.Descriptor = &desc; + + + switch (dbcgs->pValue->type) + { + case DBVT_ASCIIZ: set.Type = DBT_ST_ANSI; break; + case DBVT_BLOB: set.Type = DBT_ST_BLOB; break; + case DBVT_UTF8: set.Type = DBT_ST_UTF8; break; + case DBVT_WCHAR: set.Type = DBT_ST_WCHAR; break; + } + + if (DBSettingRead(reinterpret_cast(&set), 0) == DBT_INVALIDPARAM) + return -1; + + switch (set.Type) + { + case DBT_ST_ANSI: + { + dbcgs->pValue->type = DBVT_ASCIIZ; + dbcgs->pValue->pszVal = set.Value.pAnsi; + dbcgs->pValue->cchVal = set.Value.Length - 1; + } break; + case DBT_ST_UTF8: + { + dbcgs->pValue->type = DBVT_UTF8; + dbcgs->pValue->pszVal = set.Value.pUTF8; + dbcgs->pValue->cchVal = set.Value.Length - 1; + } break; + case DBT_ST_WCHAR: + { + if (dbcgs->pValue->type == DBVT_WCHAR) + { + dbcgs->pValue->pwszVal = set.Value.pWide; + dbcgs->pValue->cchVal = set.Value.Length - 1; + } else { + dbcgs->pValue->type = DBVT_UTF8; + dbcgs->pValue->pszVal = mir_utf8encodeW(set.Value.pWide); + dbcgs->pValue->cchVal = static_cast(strlen(dbcgs->pValue->pszVal)); + mir_free(set.Value.pWide); + } + } break; + case DBT_ST_BLOB: + { + dbcgs->pValue->type = DBVT_BLOB; + dbcgs->pValue->pbVal = set.Value.pBlob; + dbcgs->pValue->cpbVal = set.Value.Length; + } break; + case DBT_ST_BOOL: + { + dbcgs->pValue->type = DBVT_BYTE; + dbcgs->pValue->bVal = (uint8_t)set.Value.Bool; + } break; + case DBT_ST_BYTE: case DBT_ST_CHAR: + { + dbcgs->pValue->type = DBVT_BYTE; + dbcgs->pValue->bVal = set.Value.Byte; + } break; + case DBT_ST_SHORT: case DBT_ST_WORD: + { + dbcgs->pValue->type = DBVT_WORD; + dbcgs->pValue->wVal = set.Value.Word; + } break; + case DBT_ST_INT: case DBT_ST_DWORD: + { + dbcgs->pValue->type = DBVT_DWORD; + dbcgs->pValue->dVal = set.Value.DWord; + } break; + case DBT_ST_INT64: case DBT_ST_QWORD: + case DBT_ST_DOUBLE: case DBT_ST_FLOAT: + { + dbcgs->pValue->type = DBVT_BLOB; + dbcgs->pValue->cpbVal = sizeof(set.Value); + dbcgs->pValue->pbVal = reinterpret_cast(mir_alloc(sizeof(set.Value))); + memcpy(dbcgs->pValue->pbVal, &set.Value, sizeof(set.Value)); + } break; + default: + { + return -1; + } + } + + return 0; +} +INT_PTR CompGetContactSettingStatic(WPARAM hContact, LPARAM pSetting) +{ + DBCONTACTGETSETTING * dbcgs = reinterpret_cast(pSetting); + + char namebuf[512]; + namebuf[0] = 0; + if (dbcgs->szModule) + strcpy_s(namebuf, dbcgs->szModule); + strcat_s(namebuf, "/"); + if (dbcgs->szSetting) + strcat_s(namebuf, dbcgs->szSetting); + + TDBTSettingDescriptor desc = {0,0,0,0,0,0,0,0}; + TDBTSetting set = {0,0,0,0}; + desc.cbSize = sizeof(desc); + desc.Entity = hContact; + desc.pszSettingName = namebuf; + + set.cbSize = sizeof(set); + set.Descriptor = &desc; + + if (DBSettingRead(reinterpret_cast(&set), 0) == DBT_INVALIDPARAM) + return -1; + + if ((set.Type & DBT_STF_VariableLength) ^ (dbcgs->pValue->type & DBVTF_VARIABLELENGTH)) + { + if (set.Type & DBT_STF_VariableLength) + mir_free(set.Value.pBlob); + return -1; + } + + switch (set.Type) + { + case DBT_ST_ANSI: + { + if (dbcgs->pValue->cchVal < set.Value.Length) + { + memcpy(dbcgs->pValue->pszVal, set.Value.pAnsi, dbcgs->pValue->cchVal); + dbcgs->pValue->pszVal[dbcgs->pValue->cchVal - 1] = 0; + } else { + memcpy(dbcgs->pValue->pszVal, set.Value.pAnsi, set.Value.Length); + } + dbcgs->pValue->type = DBVT_ASCIIZ; + dbcgs->pValue->cchVal = set.Value.Length - 1; + + mir_free(set.Value.pAnsi); + } break; + case DBT_ST_UTF8: + { + set.Value.pUTF8 = mir_utf8decode(set.Value.pUTF8, NULL); + set.Value.Length = static_cast(strlen(set.Value.pUTF8)); + + if (dbcgs->pValue->cchVal < set.Value.Length) + { + memcpy(dbcgs->pValue->pszVal, set.Value.pUTF8, dbcgs->pValue->cchVal); + dbcgs->pValue->pszVal[dbcgs->pValue->cchVal - 1] = 0; + } else { + memcpy(dbcgs->pValue->pszVal, set.Value.pUTF8, set.Value.Length); + } + dbcgs->pValue->type = DBVT_ASCIIZ; + dbcgs->pValue->cchVal = set.Value.Length - 1; + + mir_free(set.Value.pUTF8); + } break; + case DBT_ST_WCHAR: + { + char * tmp = mir_u2a(set.Value.pWide); + WORD l = static_cast(strlen(tmp)); + mir_free(set.Value.pWide); + + if (dbcgs->pValue->cchVal < l + 1) + { + memcpy(dbcgs->pValue->pszVal, tmp, dbcgs->pValue->cchVal); + dbcgs->pValue->pszVal[l] = 0; + } else { + memcpy(dbcgs->pValue->pszVal, tmp, l + 1); + } + dbcgs->pValue->type = DBVT_ASCIIZ; + dbcgs->pValue->cchVal = l; + + mir_free(tmp); + } break; + case DBT_ST_BLOB: + { + if (dbcgs->pValue->cchVal < set.Value.Length) + { + memcpy(dbcgs->pValue->pbVal, set.Value.pBlob, dbcgs->pValue->cchVal); + } else { + memcpy(dbcgs->pValue->pbVal, set.Value.pBlob, set.Value.Length); + } + dbcgs->pValue->type = DBVT_BLOB; + dbcgs->pValue->cchVal = set.Value.Length; + + mir_free(set.Value.pBlob); + } break; + case DBT_ST_BOOL: + { + dbcgs->pValue->type = DBVT_BYTE; + dbcgs->pValue->bVal = set.Value.Bool ? TRUE : FALSE; + } break; + case DBT_ST_BYTE: case DBT_ST_CHAR: + { + dbcgs->pValue->type = DBVT_BYTE; + dbcgs->pValue->bVal = set.Value.Byte; + } break; + case DBT_ST_SHORT: case DBT_ST_WORD: + { + dbcgs->pValue->type = DBVT_WORD; + dbcgs->pValue->wVal = set.Value.Word; + } break; + case DBT_ST_INT: case DBT_ST_DWORD: + { + dbcgs->pValue->type = DBVT_DWORD; + dbcgs->pValue->dVal = set.Value.DWord; + } break; + default: + { + return -1; + } + } + + return 0; +} +INT_PTR CompFreeVariant(WPARAM wParam, LPARAM pSetting) +{ + DBVARIANT * dbv = reinterpret_cast(pSetting); + + if ((dbv->type == DBVT_BLOB) && (dbv->pbVal)) + { + mir_free(dbv->pbVal); + dbv->pbVal = 0; + } else if ((dbv->type & DBVTF_VARIABLELENGTH) && (dbv->pszVal)) + { + mir_free(dbv->pszVal); + dbv->pszVal = NULL; + } + dbv->type = 0; + return 0; +} +INT_PTR CompWriteContactSetting(WPARAM hContact, LPARAM pSetting) +{ + DBCONTACTWRITESETTING * dbcws = reinterpret_cast(pSetting); + + char namebuf[512]; + namebuf[0] = 0; + if (dbcws->szModule) + strcpy_s(namebuf, dbcws->szModule); + strcat_s(namebuf, "/"); + if (dbcws->szSetting) + strcat_s(namebuf, dbcws->szSetting); + + TDBTSettingDescriptor desc = {0,0,0,0,0,0,0,0}; + TDBTSetting set = {0,0,0,0}; + desc.cbSize = sizeof(desc); + desc.Entity = hContact; + desc.pszSettingName = namebuf; + + set.cbSize = sizeof(set); + set.Descriptor = &desc; + + switch (dbcws->value.type) + { + case DBVT_ASCIIZ: + { + set.Type = DBT_ST_ANSI; + set.Value.pAnsi = dbcws->value.pszVal; + } break; + case DBVT_UTF8: + { + wchar_t * tmp = mir_utf8decodeW(dbcws->value.pszVal); + if (tmp == 0) + { + if (IsDebuggerPresent()) + { + DebugBreak(); +#ifdef _DEBUG + } else { + LOG(logWARNING, _T("Trying to write malformed UTF8 setting \"%hs\" in module \"%hs\""), dbcws->szSetting, dbcws->szModule); + CLogger::Instance().ShowMessage(); +#endif + } + return -1; + } else { + mir_free(tmp); + } + + set.Type = DBT_ST_UTF8; + set.Value.pUTF8 = dbcws->value.pszVal; + } break; + case DBVT_WCHAR: + { + set.Type = DBT_ST_WCHAR; + set.Value.pWide = dbcws->value.pwszVal; + } break; + case DBVT_BLOB: + { + set.Type = DBT_ST_BLOB; + set.Value.pBlob = dbcws->value.pbVal; + set.Value.Length = dbcws->value.cpbVal; + } break; + case DBVT_BYTE: + { + set.Type = DBT_ST_BYTE; + set.Value.Byte = dbcws->value.bVal; + } break; + case DBVT_WORD: + { + set.Type = DBT_ST_WORD; + set.Value.Word = dbcws->value.wVal; + } break; + case DBVT_DWORD: + { + set.Type = DBT_ST_DWORD; + set.Value.DWord = dbcws->value.dVal; + } break; + default: + { + return -1; + } + } + + if (DBSettingWrite(reinterpret_cast(&set), 0) == DBT_INVALIDPARAM) + return -1; + + if (dbcws->value.type == DBVT_WCHAR) + { + dbcws->value.type = DBVT_UTF8; + wchar_t * tmp = dbcws->value.pwszVal; + dbcws->value.pszVal = mir_utf8encodeW(dbcws->value.pwszVal); + NotifyEventHooks(hSettingChangeEvent, hContact, pSetting); + mir_free(dbcws->value.pszVal); + dbcws->value.type = DBVT_WCHAR; + dbcws->value.pwszVal = tmp; + } else { + NotifyEventHooks(hSettingChangeEvent, hContact, pSetting); + } + + return 0; +} + +INT_PTR CompDeleteContactSetting(WPARAM hContact, LPARAM pSetting) +{ + DBCONTACTGETSETTING * dbcgs = reinterpret_cast(pSetting); + + char namebuf[512]; + namebuf[0] = 0; + if (dbcgs->szModule) + strcpy_s(namebuf, dbcgs->szModule); + strcat_s(namebuf, "/"); + if (dbcgs->szSetting) + strcat_s(namebuf, dbcgs->szSetting); + + TDBTSettingDescriptor desc = {0,0,0,0,0,0,0,0}; + desc.cbSize = sizeof(desc); + desc.Entity = hContact; + desc.pszSettingName = namebuf; + + if (DBSettingDelete(reinterpret_cast(&desc), 0) == DBT_INVALIDPARAM) + return -1; + + { + DBCONTACTWRITESETTING tmp = {0,0,0,0}; + tmp.szModule = dbcgs->szModule; + tmp.szSetting = dbcgs->szSetting; + tmp.value.type = 0; + NotifyEventHooks(hSettingChangeEvent, hContact, reinterpret_cast(&tmp)); + } + + return 0; +} +INT_PTR CompEnumContactSettings(WPARAM hContact, LPARAM pEnum) +{ + DBCONTACTENUMSETTINGS * pces = reinterpret_cast(pEnum); + + TDBTSettingDescriptor desc = {0,0,0,0,0,0,0,0}; + desc.cbSize = sizeof(desc); + desc.Entity = hContact; + + char namebuf[512]; + namebuf[0] = 0; + if (pces->szModule) + strcpy_s(namebuf, pces->szModule); + strcat_s(namebuf, "/"); + + TDBTSettingIterFilter filter = {0,0,0,0,0,0,0,0}; + filter.cbSize = sizeof(filter); + filter.Descriptor = &desc; + filter.hEntity = hContact; + filter.NameStart = namebuf; + + TDBTSettingIterationHandle hiter = DBSettingIterInit(reinterpret_cast(&filter), 0); + if ((hiter == 0) || (hiter == DBT_INVALIDPARAM)) + return -1; + + int res = 0; + TDBTSettingHandle hset = DBSettingIterNext(hiter, 0); + while (hset != 0) + { + char * p = strchr(desc.pszSettingName, '/'); + if (p) { + ++p; + } else { + p = desc.pszSettingName; + } + + res = pces->pfnEnumProc(p, pces->lParam); + if (res == 0) + { + hset = DBSettingIterNext(hiter, 0); + } else { + hset = 0; + } + } + + DBSettingIterClose(hiter, 0); + + if (desc.pszSettingName) + mir_free(desc.pszSettingName); + + return res; +} + + +INT_PTR CompGetEventCount(WPARAM hContact, LPARAM lParam) +{ + if (hContact == 0) + hContact = gDataBase->getEntities().getRootEntity(); + + return DBEventGetCount(hContact, 0); +} +INT_PTR CompAddEvent(WPARAM hContact, LPARAM pEventInfo) +{ + DBEVENTINFO * dbei = reinterpret_cast(pEventInfo); + if (dbei->cbSize < sizeof(DBEVENTINFO)) + return -1; + + int tmp = NotifyEventHooks(hEventFilterAddedEvent, hContact, pEventInfo); + if (tmp != 0) + return tmp; + + if (hContact == 0) + hContact = gDataBase->getEntities().getRootEntity(); + + + TDBTEvent ev = {0,0,0,0,0,0,0}; + ev.cbSize = sizeof(ev); + ev.ModuleName = dbei->szModule; + ev.Timestamp = dbei->timestamp; + ev.Flags = dbei->flags; + if (ev.Flags & DBEF_SENT) + ev.Flags = ev.Flags | DBEF_READ; + ev.EventType = dbei->eventType; + ev.cbBlob = dbei->cbBlob; + ev.pBlob = dbei->pBlob; + + int res = DBEventAdd(hContact, reinterpret_cast(&ev)); + if (res != DBT_INVALIDPARAM) + { + NotifyEventHooks(hEventAddedEvent, hContact, res); + return res; + } + return 0; +} +INT_PTR CompDeleteEvent(WPARAM hContact, LPARAM hEvent) +{ + int res = NotifyEventHooks(hEventDeletedEvent, hContact, hEvent); + + if (hContact == 0) + hContact = gDataBase->getEntities().getRootEntity(); + + if (res == 0) + return DBEventDelete(hEvent, 0); + + return res; +} +INT_PTR CompGetBlobSize(WPARAM hEvent, LPARAM lParam) +{ + int res = DBEventGetBlobSize(hEvent, 0); + if (res == DBT_INVALIDPARAM) + return -1; + + return res; +} +INT_PTR CompGetEvent(WPARAM hEvent, LPARAM pEventInfo) +{ + DBEVENTINFO * dbei = reinterpret_cast(pEventInfo); + if (dbei->cbSize < sizeof(DBEVENTINFO)) + return -1; + + TDBTEvent ev = {0,0,0,0,0,0,0}; + ev.cbSize = sizeof(ev); + ev.cbBlob = 0; + ev.pBlob = NULL; + + int res = DBEventGet(hEvent, reinterpret_cast(&ev)); + + dbei->szModule = ev.ModuleName; + dbei->timestamp = ev.Timestamp; + dbei->flags = ev.Flags; + if (dbei->flags & DBEF_SENT) + dbei->flags = dbei->flags & ~DBEF_READ; + dbei->eventType = ev.EventType; + + if (dbei->cbBlob && dbei->pBlob) + { + if (dbei->cbBlob >= ev.cbBlob) + memcpy(dbei->pBlob, ev.pBlob, ev.cbBlob); + else + memcpy(dbei->pBlob, ev.pBlob, dbei->cbBlob); + } + mir_free(ev.pBlob); + dbei->cbBlob = ev.cbBlob; + + if (res == DBT_INVALIDPARAM) + return 1; + + return res; +} +INT_PTR CompMarkEventRead(WPARAM hContact, LPARAM hEvent) +{ + int res = DBEventMarkRead(hEvent, 0); + if ((res != DBT_INVALIDPARAM) && (res & DBEF_SENT)) + res = res & ~DBEF_READ; + return res; +} +INT_PTR CompGetEventContact(WPARAM hEvent, LPARAM lParam) +{ + TDBTEntityHandle res = DBEventGetEntity(hEvent, 0); + if (res == gDataBase->getEntities().getRootEntity()) + res = 0; + + return res; +} +INT_PTR CompFindFirstEvent(WPARAM hContact, LPARAM lParam) +{ + if (hContact == 0) + hContact = gDataBase->getEntities().getRootEntity(); + + return gDataBase->getEvents().compFirstEvent(hContact); +} +INT_PTR CompFindFirstUnreadEvent(WPARAM hContact, LPARAM lParam) +{ + if (hContact == 0) + hContact = gDataBase->getEntities().getRootEntity(); + return gDataBase->getEvents().compFirstUnreadEvent(hContact); +} +INT_PTR CompFindLastEvent(WPARAM hContact, LPARAM lParam) +{ + if (hContact == 0) + hContact = gDataBase->getEntities().getRootEntity(); + return gDataBase->getEvents().compLastEvent(hContact); +} +INT_PTR CompFindNextEvent(WPARAM hEvent, LPARAM lParam) +{ + return gDataBase->getEvents().compNextEvent(hEvent); +} +INT_PTR CompFindPrevEvent(WPARAM hEvent, LPARAM lParam) +{ + return gDataBase->getEvents().compPrevEvent(hEvent); +} + +INT_PTR CompEnumModules(WPARAM wParam, LPARAM pCallback) +{ + if (!pCallback) + return -1; + + return gDataBase->getSettings().CompEnumModules(reinterpret_cast(pCallback), wParam); +} + +void Encrypt(char* msg, BOOL up) +{ + int i; + const int jump = up ? 5 : -5; + + for (i=0; msg[i]; i++) + { + msg[i] = msg[i] + jump; + } + +} + +INT_PTR CompEncodeString(WPARAM wParam, LPARAM lParam) +{ + Encrypt(reinterpret_cast(lParam),TRUE); + return 0; +} + +INT_PTR CompDecodeString(WPARAM wParam, LPARAM lParam) +{ + Encrypt(reinterpret_cast(lParam),FALSE); + return 0; +} + +INT_PTR CompGetProfileName(WPARAM cbBytes, LPARAM pszName) +{ + return gDataBase->getProfileName(cbBytes, reinterpret_cast(pszName)); +} + +INT_PTR CompGetProfilePath(WPARAM cbBytes, LPARAM pszName) +{ + return gDataBase->getProfilePath(cbBytes, reinterpret_cast(pszName)); +} + +bool CompatibilityRegister() +{ + gCompServices[ 0] = CreateServiceFunction(MS_DB_CONTACT_GETCOUNT, CompGetContactCount); + gCompServices[ 1] = CreateServiceFunction(MS_DB_CONTACT_FINDFIRST, CompFindFirstContact); + gCompServices[ 2] = CreateServiceFunction(MS_DB_CONTACT_FINDNEXT, CompFindNextContact); + gCompServices[ 3] = CreateServiceFunction(MS_DB_CONTACT_DELETE, CompDeleteContact); + gCompServices[ 4] = CreateServiceFunction(MS_DB_CONTACT_ADD, CompAddContact); + gCompServices[ 5] = CreateServiceFunction(MS_DB_CONTACT_IS, CompIsDbContact); + + gCompServices[ 6] = CreateServiceFunction(MS_DB_CONTACT_GETSETTING, CompGetContactSetting); + gCompServices[ 7] = CreateServiceFunction(MS_DB_CONTACT_GETSETTING_STR, CompGetContactSettingStr); + gCompServices[ 8] = CreateServiceFunction(MS_DB_CONTACT_GETSETTINGSTATIC, CompGetContactSettingStatic); + gCompServices[ 9] = CreateServiceFunction(MS_DB_CONTACT_FREEVARIANT, CompFreeVariant); + gCompServices[10] = CreateServiceFunction(MS_DB_CONTACT_WRITESETTING, CompWriteContactSetting); + gCompServices[11] = CreateServiceFunction(MS_DB_CONTACT_DELETESETTING, CompDeleteContactSetting); + gCompServices[12] = CreateServiceFunction(MS_DB_CONTACT_ENUMSETTINGS, CompEnumContactSettings); + //gCompServices[13] = CreateServiceFunction(MS_DB_SETSETTINGRESIDENT, CompSetSettingResident); + + gCompServices[14] = CreateServiceFunction(MS_DB_EVENT_GETCOUNT, CompGetEventCount); + gCompServices[15] = CreateServiceFunction(MS_DB_EVENT_ADD, CompAddEvent); + gCompServices[16] = CreateServiceFunction(MS_DB_EVENT_DELETE, CompDeleteEvent); + gCompServices[17] = CreateServiceFunction(MS_DB_EVENT_GETBLOBSIZE, CompGetBlobSize); + gCompServices[18] = CreateServiceFunction(MS_DB_EVENT_GET, CompGetEvent); + gCompServices[19] = CreateServiceFunction(MS_DB_EVENT_MARKREAD, CompMarkEventRead); + gCompServices[20] = CreateServiceFunction(MS_DB_EVENT_GETCONTACT, CompGetEventContact); + gCompServices[21] = CreateServiceFunction(MS_DB_EVENT_FINDFIRST, CompFindFirstEvent); + gCompServices[22] = CreateServiceFunction(MS_DB_EVENT_FINDFIRSTUNREAD, CompFindFirstUnreadEvent); + gCompServices[23] = CreateServiceFunction(MS_DB_EVENT_FINDLAST, CompFindLastEvent); + gCompServices[24] = CreateServiceFunction(MS_DB_EVENT_FINDNEXT, CompFindNextEvent); + gCompServices[25] = CreateServiceFunction(MS_DB_EVENT_FINDPREV, CompFindPrevEvent); + + gCompServices[26] = CreateServiceFunction(MS_DB_MODULES_ENUM, CompEnumModules); + + gCompServices[27] = CreateServiceFunction(MS_DB_CRYPT_ENCODESTRING, CompEncodeString); + gCompServices[28] = CreateServiceFunction(MS_DB_CRYPT_DECODESTRING, CompDecodeString); + + gCompServices[29] = CreateServiceFunction(MS_DB_GETPROFILENAME, CompGetProfileName); + gCompServices[30] = CreateServiceFunction(MS_DB_GETPROFILEPATH, CompGetProfilePath); + + + hEventDeletedEvent = CreateHookableEvent(ME_DB_EVENT_DELETED); + hEventAddedEvent = CreateHookableEvent(ME_DB_EVENT_ADDED); + hEventFilterAddedEvent = CreateHookableEvent(ME_DB_EVENT_FILTER_ADD); + hSettingChangeEvent = CreateHookableEvent(ME_DB_CONTACT_SETTINGCHANGED); + hContactDeletedEvent = CreateHookableEvent(ME_DB_CONTACT_DELETED); + hContactAddedEvent = CreateHookableEvent(ME_DB_CONTACT_ADDED); + return true; +} +bool CompatibilityUnRegister() +{ + int i; + for (i = 0; i < sizeof(gCompServices) / sizeof(gCompServices[0]); ++i) + { + DestroyServiceFunction(gCompServices[i]); + } + return true; +} diff --git a/dbx_tree/Compatibility.h b/dbx_tree/Compatibility.h new file mode 100644 index 0000000..b6b6c16 --- /dev/null +++ b/dbx_tree/Compatibility.h @@ -0,0 +1,65 @@ +/* + +dbx_tree: tree database driver for Miranda IM + +Copyright 2007-2010 Michael "Protogenes" Kunz, + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#pragma once + +#include "Interface.h" +#include "DataBase.h" +#include "Services.h" + +bool CompatibilityRegister(); +bool CompatibilityUnRegister(); + +INT_PTR CompGetContactCount(WPARAM wParam,LPARAM lParam); +INT_PTR CompFindFirstContact(WPARAM wParam,LPARAM lParam); +INT_PTR CompFindNextContact(WPARAM hContact,LPARAM lParam); +INT_PTR CompDeleteContact(WPARAM hContact,LPARAM lParam); +INT_PTR CompAddContact(WPARAM wParam,LPARAM lParam); +INT_PTR CompIsDbContact(WPARAM hContact,LPARAM lParam); + +INT_PTR CompGetContactSetting(WPARAM hContact, LPARAM pSetting); +INT_PTR CompGetContactSettingStr(WPARAM hContact, LPARAM pSetting); +INT_PTR CompGetContactSettingStatic(WPARAM hContact, LPARAM pSetting); +INT_PTR CompFreeVariant(WPARAM wParam, LPARAM pSetting); +INT_PTR CompWriteContactSetting(WPARAM hContact, LPARAM pSetting); +INT_PTR CompDeleteContactSetting(WPARAM hContact, LPARAM pSetting); +INT_PTR CompEnumContactSettings(WPARAM hContact, LPARAM pEnum); + +INT_PTR CompGetEventCount(WPARAM wParam, LPARAM lParam); +INT_PTR CompAddEvent(WPARAM hContact, LPARAM pEventInfo); +INT_PTR CompDeleteEvent(WPARAM hContact, LPARAM hEvent); +INT_PTR CompGetBlobSize(WPARAM hEvent, LPARAM lParam); +INT_PTR CompGetEvent(WPARAM hEvent, LPARAM pEventInfo); +INT_PTR CompMarkEventRead(WPARAM hContact, LPARAM hEvent); +INT_PTR CompGetEventContact(WPARAM hEvent, LPARAM lParam); +INT_PTR CompFindFirstEvent(WPARAM hContact, LPARAM lParam); +INT_PTR CompFindFirstUnreadEvent(WPARAM hContact, LPARAM lParam); +INT_PTR CompFindLastEvent(WPARAM hContact, LPARAM lParam); +INT_PTR CompFindNextEvent(WPARAM hEvent, LPARAM lParam); +INT_PTR CompFindPrevEvent(WPARAM hEvent, LPARAM lParam); + + +INT_PTR CompEncodeString(WPARAM wParam, LPARAM lParam); +INT_PTR CompDecodeString(WPARAM wParam, LPARAM lParam); + +INT_PTR CompGetProfileName(WPARAM cbBytes, LPARAM pszName); +INT_PTR CompGetProfilePath(WPARAM cbBytes, LPARAM pszName); diff --git a/dbx_tree/DataBase.cpp b/dbx_tree/DataBase.cpp new file mode 100644 index 0000000..85a9d67 --- /dev/null +++ b/dbx_tree/DataBase.cpp @@ -0,0 +1,374 @@ +/* + +dbx_tree: tree database driver for Miranda IM + +Copyright 2007-2010 Michael "Protogenes" Kunz, + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "DataBase.h" +#include "newpluginapi.h" +#ifndef _MSC_VER +#include "savestrings_gcc.h" +#endif +#include "Logger.h" + +CDataBase *gDataBase = NULL; + +CDataBase::CDataBase(const char* FileName) +{ + int len; +#ifdef UNICODE + len = MultiByteToWideChar(CP_ACP, 0, FileName, -1, NULL, 0); + m_FileName[0] = new TCHAR[len + 1]; + MultiByteToWideChar(CP_ACP, 0, FileName, -1, m_FileName[0], len + 1); + m_FileName[0][len] = 0; +#else + len = strlen(FileName); + m_FileName[0] = new TCHAR[len + 1]; + strcpy_s(m_FileName[0], len + 1, FileName); +#endif + + TCHAR * tmp = _tcsrchr(m_FileName[0], '.'); + if (tmp) + { + m_FileName[1] = new TCHAR[len + 1]; + _tcsncpy_s(m_FileName[1], len + 1, m_FileName[0], tmp - m_FileName[0]); + _tcscat_s(m_FileName[1], len + 1, _T(".pri")); + } else { + m_FileName[1] = new TCHAR[len + 5]; + _tcscpy_s(m_FileName[1], len + 5, m_FileName[0]); + _tcscat_s(m_FileName[1], len + 5, _T(".pri")); + } + + m_Opened = false; + + for (int i = 0; i < DBFileMax; ++i) + { + m_BlockManager[i] = NULL; + m_FileAccess[i] = NULL; + m_EncryptionManager[i] = NULL; + m_HeaderBlock[i] = 0; + } + + m_Entities = NULL; + m_Settings = NULL; + m_Events = NULL; +} +CDataBase::~CDataBase() +{ + if (m_Events) delete m_Events; + if (m_Settings) delete m_Settings; + if (m_Entities) delete m_Entities; + + m_Entities = NULL; + m_Settings = NULL; + m_Events = NULL; + + for (int i = DBFileMax - 1; i >= 0; --i) + { + if (m_BlockManager[i]) delete m_BlockManager[i]; + if (m_FileAccess[i]) delete m_FileAccess[i]; + if (m_EncryptionManager[i]) delete m_EncryptionManager[i]; + + m_BlockManager[i] = NULL; + m_FileAccess[i] = NULL; + m_EncryptionManager[i] = NULL; + + delete [] (m_FileName[i]); + } + +} +int CDataBase::CreateDB() +{ + /// TODO: create and show wizard + if (!CreateNewFile(DBFileSetting) || + !CreateNewFile(DBFilePrivate)) + return EMKPRF_CREATEFAILED; + + return 0; +} + + +int CDataBase::CheckFile(TDBFileType Index) +{ + TGenericFileHeader h; + memset(&h, 0, sizeof(h)); + DWORD r = 0; + HANDLE htmp = CreateFile(m_FileName[Index], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); + if (htmp != INVALID_HANDLE_VALUE) + { + SetFilePointer(htmp, 0, NULL, FILE_BEGIN); + if (ReadFile(htmp, &h, sizeof(h), &r, NULL)) + { + if (0 != memcmp(h.Gen.Signature, cFileSignature[Index], sizeof(cFileSignature[Index]))) + { + CloseHandle(htmp); + return EGROKPRF_UNKHEADER; + } + + if (cDBVersion < h.Gen.Version) + { + CloseHandle(htmp); + return EGROKPRF_VERNEWER; + } + + CloseHandle(htmp); + return EGROKPRF_NOERROR; + } + CloseHandle(htmp); + } + + return EGROKPRF_CANTREAD; +} + +int CDataBase::CheckDB() +{ + int res = CheckFile(DBFileSetting); + + if (res != EGROKPRF_NOERROR) + return res; + + if (PrivateFileExists()) + res = CheckFile(DBFilePrivate); + + return res; +} + +int CDataBase::LoadFile(TDBFileType Index) +{ + TGenericFileHeader h; + m_EncryptionManager[Index] = new CEncryptionManager; + + if (CMappedMemory::InitMMAP()) + m_FileAccess[Index] = new CMappedMemory(m_FileName[Index]); + else + m_FileAccess[Index] = new CDirectAccess(m_FileName[Index]); + + m_FileAccess[Index]->Read(&h, 0, sizeof(h)); + m_EncryptionManager[Index]->InitEncryption(h.Gen.FileEncryption); + + m_FileAccess[Index]->Size(h.Gen.FileSize); + m_FileAccess[Index]->sigFileSizeChanged().connect(this, &CDataBase::onFileSizeChanged); + + m_BlockManager[Index] = new CBlockManager(*m_FileAccess[Index], *m_EncryptionManager[Index]); + + CBlockManager::WriteTransaction trans(*m_BlockManager[Index]); // don't fire size event until header is loaded + + m_HeaderBlock[Index] = m_BlockManager[Index]->ScanFile(sizeof(h), cHeaderBlockSignature, h.Gen.FileSize); + + if (m_HeaderBlock[Index] == 0) + { + LOG(logCRITICAL, _T("Header Block not found! File damaged: \"%s\""), m_FileName[Index]); + return -1; + } + + uint32_t size = sizeof(h); + uint32_t sig = -1; + m_Header[Index] = m_BlockManager[Index]->ReadBlock(0, size, sig); + + sig = cHeaderBlockSignature; + TGenericFileHeader * buf = m_BlockManager[Index]->ReadBlock(m_HeaderBlock[Index], size, sig); + if (!buf) + { + LOG(logCRITICAL, _T("Header Block cannot be read! File damaged: \"%s\""), m_FileName[Index]); + return -1; + } + + buf->Gen.Obscure = 0; + + if (memcmp(m_Header[Index], buf, size)) + { + LOG(logCRITICAL, _T("Header Block in \"%s\" damaged!"), m_FileName[Index]); + return -1; + } + + return 0; +} + +int CDataBase::OpenDB() +{ + if (!PrivateFileExists()) + { + // TODO WIZARD + if (!CreateNewFile(DBFilePrivate)) + return -1; + } + + int res = LoadFile(DBFileSetting); + if ((res != 0) && (CLogger::logERROR <= CLogger::Instance().ShowMessage())) + { + return res; + } + + res = LoadFile(DBFilePrivate); + + if ((res != 0) && (CLogger::logERROR <= CLogger::Instance().ShowMessage())) + { + return res; + } + if (CLogger::logERROR <= CLogger::Instance().ShowMessage()) + return -1; + + m_Entities = new CEntities(*m_BlockManager[DBFilePrivate], + m_Header[DBFilePrivate]->Pri.RootEntity, + m_Header[DBFilePrivate]->Pri.Entities, + m_Header[DBFilePrivate]->Pri.Virtuals); + + m_Entities->sigRootChanged().connect(this, &CDataBase::onEntitiesRootChanged); + m_Entities->sigVirtualRootChanged().connect(this, &CDataBase::onVirtualsRootChanged); + + if (m_Entities->getRootEntity() != m_Header[DBFilePrivate]->Pri.RootEntity) + { + m_Header[DBFilePrivate]->Pri.RootEntity = m_Entities->getRootEntity(); + ReWriteHeader(DBFilePrivate); + } + + m_Settings = new CSettings(*m_BlockManager[DBFileSetting], + *m_BlockManager[DBFilePrivate], + m_Header[DBFileSetting]->Set.Settings, + *m_Entities); + + m_Settings->sigRootChanged().connect(this, &CDataBase::onSettingsRootChanged); + + m_Events = new CEvents(*m_BlockManager[DBFilePrivate], + *m_EncryptionManager[DBFilePrivate], + *m_Entities, + *m_Settings); + + return 0; +} + +bool CDataBase::PrivateFileExists() +{ + HANDLE htmp = CreateFile(m_FileName[DBFilePrivate], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); + if (htmp != INVALID_HANDLE_VALUE) + { + CloseHandle(htmp); + return true; + } + + return false; +} + + +bool CDataBase::CreateNewFile(TDBFileType File) +{ + CEncryptionManager enc; + CDirectAccess fa(m_FileName[File]); + fa.Size(sizeof(TGenericFileHeader)); + CBlockManager bm(fa, enc); + bm.ScanFile(sizeof(TGenericFileHeader), 0, sizeof(TGenericFileHeader)); + + CBlockManager::WriteTransaction trans(bm); + + uint32_t block; + TGenericFileHeader * buf = bm.CreateBlock(block, cHeaderBlockSignature); + uint32_t size = 0; + uint32_t sig = -1; + TGenericFileHeader * h = bm.ReadBlock(0, size, sig); + + memset(h, 0, sizeof(TGenericFileHeader)); + memcpy(&h->Gen.Signature, &cFileSignature[File], sizeof(h->Gen.Signature)); + h->Gen.Version = cDBVersion; + h->Gen.FileSize = fa.Size(); + + memcpy(buf, h, sizeof(TGenericFileHeader)); + bm.UpdateBlock(block, 0); + bm.UpdateBlock(0, -1); + + return true; +} + +inline void CDataBase::ReWriteHeader(TDBFileType Index) +{ + m_BlockManager[Index]->UpdateBlock(0, -1); + uint32_t size = 0, sig = 0; + TGenericFileHeader * h = m_BlockManager[Index]->ReadBlock(m_HeaderBlock[Index], size, sig); + + *h = *m_Header[Index]; + h->Gen.Obscure = GetTickCount(); + m_BlockManager[Index]->UpdateBlock(m_HeaderBlock[Index], 0); +} + + +void CDataBase::onSettingsRootChanged(CSettings* Settings, CSettingsTree::TNodeRef NewRoot) +{ + m_Header[DBFileSetting]->Set.Settings = NewRoot; + ReWriteHeader(DBFileSetting); +} +void CDataBase::onVirtualsRootChanged(void* Virtuals, CVirtuals::TNodeRef NewRoot) +{ + m_Header[DBFilePrivate]->Pri.Virtuals = NewRoot; + ReWriteHeader(DBFilePrivate); +} +void CDataBase::onEntitiesRootChanged(void* Entities, CEntities::TNodeRef NewRoot) +{ + m_Header[DBFilePrivate]->Pri.Entities = NewRoot; + ReWriteHeader(DBFilePrivate); +} +void CDataBase::onFileSizeChanged(CFileAccess * File, uint32_t Size) +{ + if (File == m_FileAccess[DBFileSetting]) + { + m_Header[DBFileSetting]->Gen.FileSize = Size; + ReWriteHeader(DBFileSetting); + } else { + m_Header[DBFilePrivate]->Gen.FileSize = Size; + ReWriteHeader(DBFilePrivate); + } +} + +int CDataBase::getProfileName(int BufferSize, char * Buffer) +{ + TCHAR * slash = _tcsrchr(m_FileName[DBFileSetting], '\\'); + if (slash) + slash++; + else + slash = m_FileName[DBFileSetting]; + + int l = static_cast(_tcslen(slash)); + if (BufferSize < l + 1) + return -1; + + char * tmp = mir_t2a(slash); + strcpy_s(Buffer, BufferSize, tmp); + mir_free(tmp); + + return 0; +} +int CDataBase::getProfilePath(int BufferSize, char * Buffer) +{ + TCHAR * slash = _tcsrchr(m_FileName[DBFileSetting], '\\'); + if (!slash) + return -1; + + int l = slash - m_FileName[DBFileSetting]; + + if (BufferSize < l + 1) + { + return -1; + } + + *slash = 0; + char * tmp = mir_t2a(m_FileName[DBFileSetting]); + strcpy_s(Buffer, BufferSize, tmp); + mir_free(tmp); + *slash = '\\'; + + return 0; +} diff --git a/dbx_tree/DataBase.h b/dbx_tree/DataBase.h new file mode 100644 index 0000000..2577249 --- /dev/null +++ b/dbx_tree/DataBase.h @@ -0,0 +1,157 @@ +/* + +dbx_tree: tree database driver for Miranda IM + +Copyright 2007-2010 Michael "Protogenes" Kunz, + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#pragma once + +#ifndef _MSC_VER +#include +#else +#include "stdint.h" +#endif +#include "MREWSync.h" + +#include "Events.h" +#include "Settings.h" +#include "Entities.h" + +#include "FileAccess.h" +#include "MappedMemory.h" +#include "DirectAccess.h" +#include "Blockmanager.h" + +#include "sigslot.h" + +#include "EncryptionManager.h" + +typedef enum TDBFileType { + DBFileSetting = 0, + DBFilePrivate = 1, + DBFileMax = 2 +} TDBFileType; + +static const uint8_t cFileSignature[DBFileMax][20] = {"Miranda IM Settings", "Miranda IM DataTree"}; +static const uint32_t cDBVersion = 0x00000001; + +static const uint32_t cHeaderBlockSignature = 0x7265491E; + +#pragma pack(push, 1) // push current alignment to stack, set alignment to 1 byte boundary + +typedef struct TSettingsHeader { + uint8_t Signature[20]; /// signature must be cSettingsHeader + uint32_t Version; /// internal DB version cDataBaseVersion + uint32_t Obscure; + TFileEncryption FileEncryption; /// Encryption Method + uint32_t FileStructureBlock; /// Offset of CBlockManager master block + uint32_t FileSize; /// Offset to the last used byte + 1 + uint32_t Settings; /// Offset to the SettingsBTree RootNode + uint8_t Reserved[256 - sizeof(TFileEncryption) - 20 - 5*sizeof(uint32_t)]; /// reserved storage +} TSettingsHeader; + +typedef struct TPrivateHeader { + uint8_t Signature[20]; /// signature must be CDataHeader + uint32_t Version; /// internal DB version cDataBaseVersion + uint32_t Obscure; + TFileEncryption FileEncryption; /// Encryption Method + uint32_t FileStructureBlock; /// Offset of CBlockManager master block + uint32_t FileSize; /// Offset to the last used byte + 1 + uint32_t RootEntity; /// Offset to the Root CList Entity + uint32_t Entities; /// Offset to the EntityBTree RootNode + uint32_t Virtuals; /// Offset to the VirtualsBTree RootNode + uint8_t Reserved[256 - sizeof(TFileEncryption) - 20 - 7*sizeof(uint32_t)]; /// reserved storage +} TPrivateHeader; + + +typedef union TGenericFileHeader { + struct { + uint8_t Signature[20]; /// signature must be cSettingsHeader + uint32_t Version; /// internal DB version cDataBaseVersion + uint32_t Obscure; + TFileEncryption FileEncryption; /// Encryption Method + uint32_t FileStructureBlock; /// Offset of CBlockManager master block + uint32_t FileSize; /// Offset to the last used byte + 1 + uint8_t Reserved[256 - sizeof(TFileEncryption) - 20 - 4*sizeof(uint32_t)]; /// reserved storage + } Gen; + TSettingsHeader Set; + TPrivateHeader Pri; +} TGenericFileHeader; + +#pragma pack(pop) + + +class CDataBase : public sigslot::has_slots<> +{ +private: + TCHAR* m_FileName[DBFileMax]; + bool m_Opened; + + CBlockManager *m_BlockManager[DBFileMax]; + CFileAccess *m_FileAccess[DBFileMax]; + TGenericFileHeader * m_Header[DBFileMax]; + CEncryptionManager *m_EncryptionManager[DBFileMax]; + + uint32_t m_HeaderBlock[DBFileMax]; + + void onSettingsRootChanged(CSettings* Settings, CSettingsTree::TNodeRef NewRoot); + void onVirtualsRootChanged(void* Virtuals, CVirtuals::TNodeRef NewRoot); + void onEntitiesRootChanged(void* Entities, CEntities::TNodeRef NewRoot); + void onFileSizeChanged(CFileAccess * File, uint32_t Size); + + bool PrivateFileExists(); + bool CreateNewFile(TDBFileType File); + + int CheckFile(TDBFileType Index); + int LoadFile(TDBFileType Index); +protected: + CEntities *m_Entities; + CSettings *m_Settings; + CEvents *m_Events; + + void ReWriteHeader(TDBFileType Index); + +public: + CDataBase(const char* FileName); + virtual ~CDataBase(); + + int CreateDB(); + int CheckDB(); + int OpenDB(); + + CEntities & getEntities() + { + return *m_Entities; + } + CSettings & getSettings() + { + return *m_Settings; + } + CEvents & getEvents() + { + return *m_Events; + } + + int getProfileName(int BufferSize, char * Buffer); + int getProfilePath(int BufferSize, char * Buffer); + +}; + + +extern CDataBase *gDataBase; diff --git a/dbx_tree/DatabaseLink.cpp b/dbx_tree/DatabaseLink.cpp new file mode 100644 index 0000000..b6cd91e --- /dev/null +++ b/dbx_tree/DatabaseLink.cpp @@ -0,0 +1,178 @@ +/* + +dbx_tree: tree database driver for Miranda IM + +Copyright 2007-2010 Michael "Protogenes" Kunz, + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "DatabaseLink.h" +#ifndef _MSC_VER +#include "savestrings_gcc.h" +#endif + +static int getCapability(int); +static int getFriendlyName(char*, size_t, int); +static int makeDatabase(char*, int*); +static int grokHeader(char*, int*); +static int Load(char*, void*); +static int Unload(int); + +DATABASELINK gDBLink = { + sizeof(DATABASELINK), + getCapability, + getFriendlyName, + makeDatabase, + grokHeader, + Load, + Unload, +}; + +PLUGINLINK *pluginLink = NULL; +MM_INTERFACE mmi = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +UTF8_INTERFACE utfi = {0,0,0,0,0,0,0}; +HANDLE hSystemModulesLoaded = 0; + + +static int SystemModulesLoaded(WPARAM wParam, LPARAM lParam) +{ + Update upd = {0,0,0,0,0,0,0,0,0,0,0,0,0}; + + upd.cbSize = sizeof(upd); + upd.szComponentName = gInternalName; + upd.szBetaVersionURL = "http://www-user.tu-chemnitz.de/~kunmi/?dbx_tree"; +#ifdef _M_X64 + upd.pbBetaVersionPrefix = (BYTE *)" =(HYAMNPROTOPLUGIN)= ---> =(HYAMNPROTOPLUGIN)= ---> =(HYAMNPROTOPLUGIN)= ---> NULL + | | | | | | | | | + | . | | | . | | | . | | + | . | | | . | | | . | | + | . | | | . | | | . | | + -------------------- | |------------------| | |------------------| | + | Next |--| | Next |--| | Next |--| + ==================== ==================== ==================== + + This structure is not needed if you only create protocol plugin for YAMN. YAMN plugin does + not see and it is not important for it how YAMN works with plugins and how it stores plugins + data. For plugin is important only handle for its own plugin, returned from + MS_YAMN_REGISTERPLUGIN service. + + +2.2. Structure of accounts + + Every account in YAMN belongs to exact plugin and its members are allocated with + MS_YAMN_CREATEPLUGINACCOUNT service. This service cooperates with your function, which is + defined in your function import table. In your function (if you have defined it), you should + create the whole account. It is because YAMN cannot know which members in structure did you + add. So you create the whole derived structure. If your fcn is not implemented (NULL in + import table), YAMN creates standard account structure. + + This structure contains information (members) related to YAMN, to plugin and members shared + between both (plugin and YAMN). Therefore it is needed to synchronize access to members (see + Ch. 3). Standard YAMN account is defined in m_account.h header file. There's also + description for every member how it is synchronised. YAMN creates two synchronizing objects + (SO) to synchronise access to members. In m_synchro.h file, there are definitions for easy + work with these SO. + + Accounts are queued in plugin: + + =(HYAMNPLUGIN)= ---> ===(HACCOUNT)=== ---> ===(HACCOUNT)=== ---> ===(HACCOUNT)=== ---> NULL + | | | | | | | | | | | | + | | | | | | | | | | | | + | . | | | | | | | | | | | + | . | | | | | | | | | | | + | . | | | | | | | | | | | + | | | |--------------| | |--------------| | |--------------| | + | (HACCOUNT) | | | Next |--| | Next |--| | Next |--| + | FirstAccount|--| ================ ================ ================ + |-------------| + | | + =============== + + Every account has its own back pointer to (HYAMNPLUGIN) in Plugin member, so you can easy + look at first account, when you have any other account (see m_account.h). + + +2.3. Structure of mails + + Account has a pointer to mails. Account's pointer to mails is pointer to first mail in fact + and mails are queued too: + + ==(HACCOUNT)== ---> ==(HYAMNMAIL)== ---> ==(HYAMNMAIL)== ---> ==(HYAMNMAIL)== ---> NULL + | | | | | | | | | | | | + | . | | | | | | | | | | | + | . | | | | | | | | | | | + | . | | | | | | | | | | | + | | | |-------------| | |-------------| | |-------------| | + | (HYAMNMAIL)| | | Next |--| | Next |--| | Next |--| + | Mails|--| =============== =============== =============== + |------------| + | | + ============== + + Standard MIME mail is defined in mails/m_mails.h file. + + Plugin can work with accounts in its own way, but note it is needed to synchronize access. + For better work, YAMN offers you some services and exports functions. Description of + exported functions is in its declartation; for accounts functions see account.cpp, for mails + functions see mails/mails.cpp and so on. + + +3. YAMN thread synchronization + --------------------------- + + Because YAMN is multithreaded, more than one thread can access to any member of account + structure. Therefore access to these members should be synchronised. YAMN offers two types + of synchronization objects (SO): SCOUNTER (Synchronized Counter) and SWMRG (Single + Writer/Multiple Readers Guard). To use these objects, you can use exported functions: + + SWMRG: WaitToWriteSO, WaitToWriteSOEx, WriteDoneSO, WaitToReadSO, WaitToReadSOEx, ReadDoneSO + SCOUNTER: SCGetNumber, SCInc, SCDec + + To see description for these functions, see m_synchro.h header file and synchro.cpp. Note + that in HACCOUNT structure, there are 3 synchronizing members, which you have to use if you + want to access to any member of account structure. All access techniques (writing to members + and read from members) are used in POP3 protocol plugin. Now, it is important what we have + to do when we want to make our plugin be synchronized with YAMN (in POP3 protocol it is + described too). + + 1. We have to use ThreadRunningEV event when YAMN calls our checking/deleting function. This + parameter is to stop YAMN called thread until we do not have copied datas from stack. After + that, we SetEvent(ThreadRunningEvent) to unblock YAMN to continue in its work. + + 2. We have to use UsingThreads account's member. This is only for YAMN account deleting + prevention. We use this counter to set number of threads using account. If no thread is just + using account, account is signaled, that it can be deleted (and is deleted when needed). + This leads us to do some things: We use SCInc(UsingThreads) as the first thing we can do. We + cannot omit, that called thread finished before we call this function. UsingThreads should + have "continuous" value greater than zero when using account. E.g. if YAMN creates thread + for plugin that checks account for new mail, YAMN waits until we set ThreadRunningEV (see + point 1). After setting this event to signal, that YAMN can continue in its work, we + increase SCInc(UsingThreads), so we ensure that another thread uses account before YAMN + thread, that uses this account ends. And SCDec(UsingThreads) should be the last thing we do + in our thread. If we run another thread in our thread, we should wait until it does not + SCInc(UsingThreads) and after that we should continue (just like YAMN creates and calls our + thread). + + 3. If we use account's SWMRG (AccountAccessSO, MessagesAccessSO), we should test what our + function returned. Use the same methods as POP3 protocol does while testing and accessing + critical section. Note that we cannot use WaitToWriteSO(MyAccount->AccountAccessSO), but in + easy way we can WaitToWrite(AccountAccess) and for mails + WaitToWriteSO(MyAccount->MessagesAccessSO) use MsgsWaitToWrite(AccountAccess) and so on. See + export.h file for these definitions. + + 4. Deleting account is quite easy, but in YAMN, it is very problematic operation. If you use + MS_YAMN_DELETEACCOUNT service, it is the best way to avoid any problem. These problems raise + from the facts desribed in the point 2. + + 5. You should use ctritical sections only for short time not to block other threads. You can + imagine that users can't browse through mails, because account is blocked by your thread... + + All needed infos in POP3 internal protocol plugin (see proto/pop3/pop3comm.cpp), are + described. + + +4. What do you need to make your filter plugin cooperating with YAMN + ----------------------------------------------------------------- + + Filter plugins are very easy to write in its own way, it much more easier than protocol + plugin. But some things are common: you have to register your plugin and insert to YAMN + (these are 2 steps, see sources of some filter plugin), You have to import to YAMN your + filter function. Filter function can do anything with mails, but the most important is, that + it can set Flags member of mail (see mails/m_mails.h file) to one of YAMN_MSG_SPAMLx. + Note Mail is in write-access, so your plugin can do anything with mail and avoid the + synchronization problem. + + Now YAMN recognizes 4 spam levels: + 1. Notifies about this mail, but shows it in mailbrowser with other color than normally + 2. Does not notify about this mail, shows it in mailbrowser with other color than normally + 3. Deletes mail from server (depends on protocol), does not notify and shows "this spam was + deleted" + 4. Deletes mail from server (depends on protocol), does not notify, does not show in + mailbrowser + + Your plugin can set data for mail in the TranslatedHeader structure, inserting it to the + queue. This information is stored, so it is reloaded after protocol read mails from book + file. diff --git a/yamn/docs/YAMN-Readme.txt b/yamn/docs/YAMN-Readme.txt new file mode 100644 index 0000000..901ad22 --- /dev/null +++ b/yamn/docs/YAMN-Readme.txt @@ -0,0 +1,79 @@ +========================================================= += YAMN plugin for Miranda readme = +========================================================= +Yet Another Mail Notifier +Checks pop3 accounts for new mail + +Advantages: +- quite small +- structured in two parts: notifier and protocols +- unlimited number of accounts +- international support in Unicode +- open-source (GNU-GPL) +POP3: +- many switches for each account +- support for MIME standard +- support for Base64 and Quoted-Printable +- 100% detection of new mail based on unique message ID +- multithreaded checking (also with hotkey) +- deleting mail from server +- connecting through Miranda proxy +- secure password authentification +- SSL support through OpenSSL + +WIN9X SUPPORT +------------- +Win9x users, use unicows.dll library, download it at: +http://libunicows.sf.net (whole package) +or just visit http://www.majvan.host.sk/Projekty/YAMN +and download zip-ed unicows.dll +All you need is to copy unicows.dll to Windows system32 +directory (or to Miranda home directory). Use Win9x +version of YAMN, not WinNT version. + +SSL SUPPORT +----------- +If you want to use SSL features, you have to download +OpenSSL libraries on YAMN homepage +http://www.majvan.host.sk/Projekty/YAMN +or the latest (stable) version with installer on +http://www.slproweb.com/products/Win32OpenSSL.html +Copy *.dll files to Windows system32 directory (or to +Miranda home directory). + +LATEST STABLE +------------- +Version of YAMN has following structure: w.x.y.z +z- only some bug fixed or some changes +y- some new feature added +x- big feature added +w- if this changes, YAMN becomes better than Outlook ;-) +Latest stable plugin is always present to download from YAMN +homepage. + +BETA +---- +* YAMN-beta version is intended only for testing purposes. +* Author waits for stability reports. Sometimes author waits not +only for crash reports, but also for success reports (you are +informed by message box on startup, if success reports are also +needed). This is because he has no resources for testing. +* Please do not send reports if newer beta version is available. +* Please do not send reports without describing problem detailed. +* Beta version produces debug files (yamn-debug.*.log) located +in Miranda home directory (like every YAMN debug release). These +files are usefull for author to locate the bug (although not +100%). After Miranda restart, log files are rewritten. Log files +can become very large (more than 10MB). Sometimes they can be +cut at the end (contact author). +IMPORTANT FOR BETA: yamn-debug.comm.log file contains your plain +password. You should rewrite it. +Thank you for comprehension. + +========================================================= + Do you want some FAQ? Visit HOMEPAGE: + http://www.majvan.host.sk/Projekty/YAMN + Still don't know answer? Write question to guestbook. + + majvan +========================================================= diff --git a/yamn/docs/language.pop3.txt b/yamn/docs/language.pop3.txt new file mode 100644 index 0000000..03fb78e --- /dev/null +++ b/yamn/docs/language.pop3.txt @@ -0,0 +1,118 @@ +; +; YAMN-POP3 0.2.4.7 translation file +; +;-------------------------------- +; NEW in 0.2.4.7 +;-------------------------------- + +;-------------------------------- +; CHANGED in 0.2.4.7 +;-------------------------------- + +;-------------------------------- +; OLD in 0.2.4.7 +;-------------------------------- +; +; Main +; +[Found new version of account book, not compatible with this version of YAMN.] +[Error reading account file. Account file corrupted.] +[Memory allocation error while data reading] +[Reading file error. File already in use?] +[Error while copying data to disk occured. File in use?] +[YAMN (internal POP3) read error] +[POP3 plugin- write file error] +[Error %d-%d-%d-%d:] +[Memory allocation error.] +[Account is about to be stopped.] +[Cannot connect to POP3 server.] +[Cannot allocate memory for received data.] +[Cannot login to POP3 server.] +[Bad user or password.] +[Server does not support APOP authorization.] +[Error while executing POP3 command.] +[Cannot connect to server with NetLib.] +[Cannot send data.] +[Cannot receive data.] +[Cannot allocate memory for received data.] +[OpenSSL not loaded.] +[Windows socket 2.0 init failed.] +[DNS lookup error.] +[Error while creating base socket.] +[Error connecting to server with socket.] +[Error while creating SSL structure.] +[Error connecting socket with SSL.] +[Server rejected connection with SSL.] +[Cannot write SSL data.] +[Cannot read SSL data.] +[Cannot allocate memory for received data.] + +; +; Options +; +[Please wait while account is in use.] +[Please wait while no account is in use.] +[Time left to next check [s]: %d] +[Select executable used for notification] +[Input error] +[This is not a valid number value] +[At least one mail notification event must be checked] +[Please select application to run] +[Delete] +[Check this account] +[Server:] +[Port:] +[User:] +[Password:] +[APOP auth] +[Check interval [min]:] +[Sound notification] +[Message notification] +[Tray icon notification] +[Application execution:] +[Persistant message] +[Sound notification if failed] +[Message notification if failed] +[Tray icon notification if failed] +[Default codepage:] +[Check while:] +;[Offline] +;[Online] +;[Away] +;[N/A] +;[Occupied] +;[DND] +;[Free for chat] +;[Invisible] +;[On the phone] +;[Out to lunch] +[Startup check] +[Default] +[Reset counter] +[Account Test] +[Account Test (failed)] +[Account Test] +[You have N new mails] +[Connection failed message] +[Popup notification] +[Popup if no mail] +[Single popup] +[Multi popup] +[Popup notification if failed] +[Check from menu] +[New mail notifications] +[No new mail notifications] +[Connection failure notifications] +[Connecting to server] +[Reading new mails (%d%% done)] +[Disconnected] +[Entering POP3 account] +[Searching for new mail] +[Deleting requested mails] +[Deleting spam] +[Delete account confirmation] +[Do you really want to delete this account?] + +;-------------------------------- +; REMOVED in 0.2.4.7 +;-------------------------------- \ No newline at end of file diff --git a/yamn/docs/language.txt b/yamn/docs/language.txt new file mode 100644 index 0000000..72d1fcd --- /dev/null +++ b/yamn/docs/language.txt @@ -0,0 +1,75 @@ +; +; YAMN 0.2.4.7 translation file +; +;-------------------------------- +; NEW in 0.2.4.7 +;-------------------------------- + +;-------------------------------- +; CHANGED in 0.2.4.7 +;-------------------------------- + +;-------------------------------- +; OLD in 0.2.4.7 +;-------------------------------- +; +; Main +; +[YAMN: new mail] +[YAMN: connect failed] +[No new mail, %d spam(s)] +[No new mail] +[YAMN uninstalling] +[Do you also want to remove native YAMN plugins settings?] + +; +; Menu +; +[Check &mail (YAMN)] +[Check mail] ;for TopToolBar plugin + +; +; Options +; +[Hotkey for mail check:] +[TopToolBar button "Check mail"] +[Installed plugins] +[Version:] +[Description:] +[Copyright:] +[Contact:] +[WWW:] + +; +; Mail browser +; +[%s - %d new mails, %d total] +[ - new mail(s)] +[From] +[Subject] +[Size] +[Run application] +[Delete selected] +[Delete confirmation] +[Do you really want to delete %d selected mails?] + +; +; Bad connection dialog +; +[ - connection error] +[Cannot allocate memory for received data] +[Bad user name or error while logging] +[Bad user or password or error while logging] +[Cannot get number of messages] +[Cannot resolve message signatures] +[Cannot get sizes of messages] +[Cannot find server] +[Cannot connect to server] +[System error occured] +[Cannot send data] +[Cannot receive data] +[Unknown error] + +;-------------------------------- +; REMOVED in 0.2.4.7 +;-------------------------------- \ No newline at end of file diff --git a/yamn/filter/Base/AggressiveOptimize.h b/yamn/filter/Base/AggressiveOptimize.h new file mode 100644 index 0000000..1bf0e19 --- /dev/null +++ b/yamn/filter/Base/AggressiveOptimize.h @@ -0,0 +1,168 @@ + +////////////////////////////// +// Version 1.40 +// October 22nd, 2002 - .NET (VC7, _MSC_VER=1300) support! +// Version 1.30 +// Nov 24th, 2000 +// Version 1.20 +// Jun 9th, 2000 +// Version 1.10 +// Jan 23rd, 2000 +// Version 1.00 +// May 20th, 1999 +// Todd C. Wilson, Fresh Ground Software +// (todd@nopcode.com) +// This header file will kick in settings for Visual C++ 5 and 6 that will (usually) +// result in smaller exe's. +// The "trick" is to tell the compiler to not pad out the function calls; this is done +// by not using the /O1 or /O2 option - if you do, you implicitly use /Gy, which pads +// out each and every function call. In one single 500k dll, I managed to cut out 120k +// by this alone! +// The other two "tricks" are telling the Linker to merge all data-type segments together +// in the exe file. The relocation, read-only (constants) data, and code section (.text) +// sections can almost always be merged. Each section merged can save 4k in exe space, +// since each section is padded out to 4k chunks. This is very noticeable with smaller +// exes, since you could have only 700 bytes of data, 300 bytes of code, 94 bytes of +// strings - padded out, this could be 12k of runtime, for 1094 bytes of stuff! For larger +// programs, this is less overall, but can save at least 4k. +// Note that if you're using MFC static or some other 3rd party libs, you may get poor +// results with merging the readonly (.rdata) section - the exe may grow larger. +// To use this feature, define _MERGE_DATA_ in your project or before this header is used. +// With Visual C++ 5, the program uses a file alignment of 512 bytes, which results +// in a small exe. Under VC6, the program instead uses 4k, which is the same as the +// section size. The reason (from what I understand) is that 4k is the chunk size of +// the virtual memory manager, and that WinAlign (an end-user tuning tool for Win98) +// will re-align the programs on this boundary. The problem with this is that all of +// Microsoft's system exes and dlls are *NOT* tuned like this, and using 4k causes serious +// exe bloat. This is very noticeable for smaller programs. +// The "trick" for this is to use the undocumented FILEALIGN linker parm to change the +// padding from 4k to 1/2k, which results in a much smaller exe - anywhere from 20%-75% +// depending on the size. Note that this is the same as using /OPT:NOWIN98, which *is* +// a previously documented switch, but was left out of the docs for some reason in VC6 and +// all of the current MSDN's - see KB:Q235956 for more information. +// Microsoft does say that using the 4k alignment will "speed up process loading", +// but I've been unable to notice a difference, even on my P180, with a very large (4meg) exe. +// Please note, however, that this will probably not change the size of the COMPRESSED +// file (either in a .zip file or in an install archive), since this 4k is all zeroes and +// gets compressed away. +// Also, the /ALIGN:4096 switch will "magically" do the same thing, even though this is the +// default setting for this switch. Apparently this sets the same values as the above two +// switches do. We do not use this in this header, since it smacks of a bug and not a feature. +// Thanks to Michael Geary for some additional tips! +// +// Notes about using this header in .NET +// First off, VC7 does not allow a lot of the linker command options in pragma's. There is no +// honest or good reason why Microsoft decided to make this change, it just doesn't. +// So that is why there are a lot of <1300 #if's in the header. +// If you want to take full advantage of the VC7 linker options, you will need to do it on a +// PER PROJECT BASIS; you can no longer use a global header file like this to make it better. +// Items I strongly suggest putting in all your VC7 project linker options command line settings: +// /ignore:4078 /RELEASE +// Compiler options: +// /GL (Whole Program Optimization) +// If you're making an .EXE and not a .DLL, consider adding in: +// /GA (Optimize for Windows Application) +// Some items to consider using in your VC7 projects (not VC6): +// Link-time Code Generation - whole code optimization. Put this in your exe/dll project link settings. +// /LTCG:NOSTATUS +// The classic no-padding and no-bloat compiler C/C++ switch: +// /opt:nowin98 +// +// (C++ command line options: /GL /opt:nowin98 and /GA for .exe files) +// (Link command line options: /ignore:4078 /RELEASE /LTCG:NOSTATUS) +// +// Now, notes on using these options in VC7 vs VC6. +// VC6 consistently, for me, produces smaller code from C++ the exact same sources, +// with or without this header. On average, VC6 produces 5% smaller binaries compared +// to VC7 compiling the exact same project, *without* this header. With this header, VC6 +// will make a 13k file, while VC7 will make a 64k one. VC7 is just bloaty, pure and +// simple - all that managed/unmanaged C++ runtimes, and the CLR stuff must be getting +// in the way of code generation. However, template support is better, so there. +// Both VC6 and VC7 show the same end kind of end result savings - larger binary output +// will shave about 2% off, where as smaller projects (support DLL's, cpl's, +// activex controls, ATL libs, etc) get the best result, since the padding is usually +// more than the actual usable code. But again, VC7 does not compile down as small as VC6. +// +// The argument can be made that doing this is a waste of time, since the "zero bytes" +// will be compressed out in a zip file or install archive. Not really - it doesn't matter +// if the data is a string of zeroes or ones or 85858585 - it will still take room (20 bytes +// in a zip file, 29 bytes if only *4* of them 4k bytes are not the same) and time to +// compress that data and decompress it. Also, 20k of zeros is NOT 20k on disk - it's the +// size of the cluster slop- for Fat32 systems, 20k can be 32k, NTFS could make it 24k if you're +// just 1 byte over (round up). Most end users do not have the dual P4 Xeon systems with +// two gigs of RDram and a Raid 0+1 of Western Digital 120meg Special Editions that all +// worthy developers have (all six of us), so they will need any space and LOADING TIME +// savings they will need; taking an extra 32k or more out of your end user's 64megs of +// ram on Windows 98 is Not a Good Thing. +// +// Now, as a ADDED BONUS at NO EXTRA COST TO YOU! Under VC6, using the /merge:.text=.data +// pragma will cause the output file to be un-disassembleable! (is that a word?) At least, +// with the normal tools - WinDisam, DumpBin, and the like will not work. Try it - use the +// header, compile release, and then use DUMPBIN /DISASM filename.exe - no code! +// Thanks to Gëzim Pani for discovering this gem - for a full writeup on +// this issue and the ramifactions of it, visit www.nopcode.com for the Aggressive Optimize +// article. + +#ifndef _AGGRESSIVEOPTIMIZE_H_ +#define _AGGRESSIVEOPTIMIZE_H_ + +#pragma warning(disable:4711) + +#ifdef NDEBUG +// /Og (global optimizations), /Os (favor small code), /Oy (no frame pointers) +#pragma optimize("gsy",on) + +#if (_MSC_VER<1300) + #pragma comment(linker,"/RELEASE") +#endif + +/* +// Note that merging the .rdata section will result in LARGER exe's if you using +// MFC (esp. static link). If this is desirable, define _MERGE_RDATA_ in your project. +#ifdef _MERGE_RDATA_ +#pragma comment(linker,"/merge:.rdata=.data") +#endif // _MERGE_RDATA_ + +#pragma comment(linker,"/merge:.text=.data") +#if (_MSC_VER<1300) + // In VC7, this causes problems with the relocation and data tables, so best to not merge them + #pragma comment(linker,"/merge:.reloc=.data") +#endif +*/ + +// Merging sections with different attributes causes a linker warning, so +// turn off the warning. From Michael Geary. Undocumented, as usual! +#if (_MSC_VER<1300) + // In VC7, you will need to put this in your project settings + #pragma comment(linker,"/ignore:4078") +#endif + +// With Visual C++ 5, you already get the 512-byte alignment, so you will only need +// it for VC6, and maybe later. +#if _MSC_VER >= 1000 + +// Option #1: use /filealign +// Totally undocumented! And if you set it lower than 512 bytes, the program crashes. +// Either leave at 0x200 or 0x1000 +//#pragma comment(linker,"/FILEALIGN:0x200") + +// Option #2: use /opt:nowin98 +// See KB:Q235956 or the READMEVC.htm in your VC directory for info on this one. +// This is our currently preferred option, since it is fully documented and unlikely +// to break in service packs and updates. +#if (_MSC_VER<1300) + // In VC7, you will need to put this in your project settings + #pragma comment(linker,"/opt:nowin98") +#else + +// Option #3: use /align:4096 +// A side effect of using the default align value is that it turns on the above switch. +// Does nothing under Vc7 that /opt:nowin98 doesn't already give you +// #pragma comment(linker,"/ALIGN:512") +#endif + +#endif // _MSC_VER >= 1000 + +#endif // NDEBUG + +#endif // _AGGRESSIVEOPTIMIZE_H_ diff --git a/yamn/filter/Base/Base.dsp b/yamn/filter/Base/Base.dsp new file mode 100644 index 0000000..7231712 --- /dev/null +++ b/yamn/filter/Base/Base.dsp @@ -0,0 +1,108 @@ +# Microsoft Developer Studio Project File - Name="Base" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=Base - Win32 Release +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "Base.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "Base.mak" CFG="Base - Win32 Release" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "Base - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Base - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Base - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Ignore_Export_Lib 1 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /G4 /Zp4 /MD /W3 /GX /O1 /Ob0 /I "../../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /G4 /Zp4 /MD /W3 /GX /Zi /O1 /Ob0 /I "../../../../include" /I "../../../../include/msapi" /I "../../../../include_API" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE RSC /l 0x417 /d "NDEBUG" +# ADD RSC /l 0x417 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib /nologo /dll /machine:I386 /out:"../../../../bin/release/plugins/YAMN-filter/Base.dll" /filealign:512 +# ADD LINK32 kernel32.lib user32.lib /nologo /dll /pdb:"../../../../bin/Release/plugins/YAMN/base.pdb" /debug /machine:I386 /out:"../../../../bin/Release/plugins/YAMN/base.dll" /filealign:512 + +!ELSEIF "$(CFG)" == "Base - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /G4 /Zp4 /MDd /W3 /Gm /Gi /GX /ZI /Od /I "../../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /GZ /c +# ADD CPP /nologo /G4 /Zp4 /MDd /W3 /Gm /Gi /GX /ZI /Od /I "../../../../include" /I "../../../../include/msapi" /I "../../../../include_API" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /GZ /c +# ADD BASE RSC /l 0x417 /d "_DEBUG" +# ADD RSC /l 0x417 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib /nologo /dll /debug /machine:I386 /out:"../../../../bin/Debug/plugins/YAMN-filter/Base.dll" +# ADD LINK32 kernel32.lib user32.lib /nologo /dll /pdb:"../../../../bin/Debug/plugins/YAMN/base.pdb" /debug /machine:I386 /out:"../../../../bin/Debug/plugins/YAMN/base.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "Base - Win32 Release" +# Name "Base - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\debug.cpp +# End Source File +# Begin Source File + +SOURCE=.\maindll.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/yamn/filter/Base/Base.mak b/yamn/filter/Base/Base.mak new file mode 100644 index 0000000..75ec59d --- /dev/null +++ b/yamn/filter/Base/Base.mak @@ -0,0 +1,229 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on Base.dsp +!IF "$(CFG)" == "" +CFG=Base - Win32 Release +!MESSAGE No configuration specified. Defaulting to Base - Win32 Release. +!ENDIF + +!IF "$(CFG)" != "Base - Win32 Release" && "$(CFG)" != "Base - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Base.mak" CFG="Base - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Base - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Base - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "Base - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release + +ALL : "..\..\..\..\bin\release\plugins\YAMN-filter\base.dll" + + +CLEAN : + -@erase "$(INTDIR)\debug.obj" + -@erase "$(INTDIR)\maindll.obj" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(OUTDIR)\base.exp" + -@erase "..\..\..\..\bin\release\plugins\YAMN-filter\base.dll" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /G4 /Zp4 /MD /W3 /GX /O1 /Ob0 /I "../../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Fp"$(INTDIR)\Base.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ= +RSC=rc.exe +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\Base.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\base.pdb" /machine:I386 /out:"../../../../bin/release/plugins/YAMN-filter/base.dll" /implib:"$(OUTDIR)\base.lib" /filealign:512 +LINK32_OBJS= \ + "$(INTDIR)\debug.obj" \ + "$(INTDIR)\maindll.obj" + +"..\..\..\..\bin\release\plugins\YAMN-filter\base.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Base - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +ALL : "..\..\..\..\bin\Debug\plugins\YAMN-filter\Base.dll" "$(OUTDIR)\Base.bsc" + + +CLEAN : + -@erase "$(INTDIR)\debug.obj" + -@erase "$(INTDIR)\debug.sbr" + -@erase "$(INTDIR)\maindll.obj" + -@erase "$(INTDIR)\maindll.sbr" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(INTDIR)\vc60.pdb" + -@erase "$(OUTDIR)\Base.bsc" + -@erase "$(OUTDIR)\Base.exp" + -@erase "$(OUTDIR)\Base.pdb" + -@erase "..\..\..\..\bin\Debug\plugins\YAMN-filter\Base.dll" + -@erase "..\..\..\..\bin\Debug\plugins\YAMN-filter\Base.ilk" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /G4 /Zp4 /MDd /W3 /Gm /Gi /GX /ZI /Od /I "../../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\Base.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ= +RSC=rc.exe +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\Base.bsc" +BSC32_SBRS= \ + "$(INTDIR)\debug.sbr" \ + "$(INTDIR)\maindll.sbr" + +"$(OUTDIR)\Base.bsc" : "$(OUTDIR)" $(BSC32_SBRS) + $(BSC32) @<< + $(BSC32_FLAGS) $(BSC32_SBRS) +<< + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\Base.pdb" /debug /machine:I386 /out:"../../../../bin/Debug/plugins/YAMN-filter/Base.dll" /implib:"$(OUTDIR)\Base.lib" +LINK32_OBJS= \ + "$(INTDIR)\debug.obj" \ + "$(INTDIR)\maindll.obj" + +"..\..\..\..\bin\Debug\plugins\YAMN-filter\Base.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("Base.dep") +!INCLUDE "Base.dep" +!ELSE +!MESSAGE Warning: cannot find "Base.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "Base - Win32 Release" || "$(CFG)" == "Base - Win32 Debug" +SOURCE=.\debug.cpp + +!IF "$(CFG)" == "Base - Win32 Release" + + +"$(INTDIR)\debug.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Base - Win32 Debug" + + +"$(INTDIR)\debug.obj" "$(INTDIR)\debug.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\maindll.cpp + +!IF "$(CFG)" == "Base - Win32 Release" + + +"$(INTDIR)\maindll.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Base - Win32 Debug" + + +"$(INTDIR)\maindll.obj" "$(INTDIR)\maindll.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + + +!ENDIF + diff --git a/yamn/filter/Base/debug.cpp b/yamn/filter/Base/debug.cpp new file mode 100644 index 0000000..654ece7 --- /dev/null +++ b/yamn/filter/Base/debug.cpp @@ -0,0 +1,73 @@ +/* + * Copied from YAMN plugin + * + * (c) majvan 2002-2004 + */ +#ifdef DEBUG_FILTER + +#include +#include +#include + + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +TCHAR DebugUserDirectory[MAX_PATH]="."; +LPCRITICAL_SECTION FileAccessCS; + +void DebugLog(HANDLE File,const char *fmt,...); + +#ifdef DEBUG_FILTER +TCHAR DebugFilterFileName2[]=_T("%s\\yamn-debug.basefilter.log"); +HANDLE FilterFile=INVALID_HANDLE_VALUE; +#endif + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +void InitDebug() +{ + TCHAR DebugFileName[MAX_PATH]; + + if(FileAccessCS==NULL) + { + FileAccessCS=new CRITICAL_SECTION; + InitializeCriticalSection(FileAccessCS); + } + + _stprintf(DebugFileName,DebugFilterFileName2,DebugUserDirectory); + + FilterFile=CreateFile(DebugFileName,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,0,NULL); + + DebugLog(FilterFile,"Base filter plugin for YAMN - debug file\n"); +} + +void UnInitDebug() +{ + DebugLog(FilterFile,"File is being closed normally."); + CloseHandle(FilterFile); +} + +void DebugLog(HANDLE File,const char *fmt,...) +{ + char *str; + char tids[32]; + va_list vararg; + int strsize; + DWORD Written; + + va_start(vararg,fmt); + str=(char *)malloc(strsize=65536); + _stprintf(tids,_T("[%x]"),GetCurrentThreadId()); + while(_vsnprintf(str,strsize,fmt,vararg)==-1) + str=(char *)realloc(str,strsize+=65536); + va_end(vararg); + EnterCriticalSection(FileAccessCS); + WriteFile(File,tids,(DWORD)strlen(tids),&Written,NULL); + WriteFile(File,str,(DWORD)strlen(str),&Written,NULL); + LeaveCriticalSection(FileAccessCS); + free(str); +} + +#endif //ifdef DEBUG \ No newline at end of file diff --git a/yamn/filter/Base/docs/base-readme.txt b/yamn/filter/Base/docs/base-readme.txt new file mode 100644 index 0000000..2e79bbb --- /dev/null +++ b/yamn/filter/Base/docs/base-readme.txt @@ -0,0 +1,63 @@ +======================== += Base Filter for YAMN = +======================== + +Q: What??? +A: YAMN filter to classify incoming email. + +Q: How? +A: Finding occurency of defiend MIME header item and its value from blacklist file. + +Q: Blacklist file? +A: Yes. It is created by yourself and located in Miranda directory with name 'basefilterdeny.txt' + +Q: Created by myself? +A: Just create the file and write there your header MIME items and its values. + +Q: What do you mean "header MIME items" and "its values"? +A: Every mail has header consisting of MIME items like "Subject" or "Return-Path". + +Q: So I need to understand how the header looks like... +A: Yes, if you want to use this filter, you should. Header MIME is defined in RFC822 standard. + +Q: Ok, I've just studied it. So how to set filter (write some rules to the blacklist file)? +A: Each line is one rule: write the exact item, press , press the substring of value needed to be found, press , define spamlevel and then press . + +Q: Spamlevel? +A: Yes. + 0=do not notify + 1=notify, display with another color in mailbrowser + 2=do not notify, display with another color in mailbrowser + 3=delete, display in mailbrowser about deleted mail + 4=delete, do not display (mail's quick death, hehe) + +Q: So the rule has 3 parameters, that's it? +A: Yes. This is the example: +<------ start of file ------> +From CrazyMail 1 +X-Importance low 0 +Subject LinuxMailList 0 +Return-Path cheapsoftware@junkmails.net 2 +X-TextClassification spam 3 +<------ end of file -------> + +Q: Wait while. Ok, but it does not work. +A: Check if you have this plugin listed in Miranda/Options/Plugins/YAMN item + +Q: No, it is not listed in YAMN plugins. +A: Then check if the dll residents in Plugins/YAMN direcotry. + +Q: This directory does not exists. +A: Create it and put the dll there. Restart Miranda. + +Q: Hmmm, ok. But it is not still listed. +A: Your version of YAMN and filter does not match. + +Q: And? +A: Try to look to http://www.majvan.host.sk/Projekty/YAMN for updates. + +Q: Now, it is listed, but does not work anyway. +A: Try to download debug version from YAMN homepage, if you are not using it (the name of filter must contain the word "debug") + +Q: What does debug version do? +A: It creates debug log file in Miranda home directory where you can browse how does filter mark mails. \ No newline at end of file diff --git a/yamn/filter/Base/maindll.cpp b/yamn/filter/Base/maindll.cpp new file mode 100644 index 0000000..6affd00 --- /dev/null +++ b/yamn/filter/Base/maindll.cpp @@ -0,0 +1,238 @@ +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../m_filterplugin.h" +#if !defined(_WIN64) + #include "aggressiveoptimize.h" +#endif + +typedef INT_PTR(* MIRANDASERVICE)(WPARAM,LPARAM); + +DWORD WINAPI FilterMail(HACCOUNT Account,DWORD AccountVer,HYAMNMAIL Mail,DWORD MailVer);//Function marks mail as spam when it is spam... +DWORD WINAPI UnLoadFilter(LPVOID); + +int LoadRules(); //Load rules from file +int findsubstr(char *original,char *pattern); //finds if original contains substring + +YAMN_FILTERIMPORTFCN FilterFunctions= //we set for YAMN which is our filter function +{ + FilterMail, + UnLoadFilter, +}; + +struct cFilterTable +{ + char account[256]; + char name[256]; + char value[256]; + unsigned char sl; +} *ft=NULL; +int fts=0; + +YAMN_FILTERREGISTRATION FilterRegistration= //classical YAMN registration +{ +#ifdef DEBUG_FILTER + "Base filter plugin for YAMN (debug)", +#else + "Base filter plugin for YAMN", +#endif + __DATE__, + "© majvan", + "Classifies mails using the rules stored in file", + "om3tn@psg.sk", + "http://www.majvan.host.sk/Projekty/YAMN?fm=soft", +}; + +char *FilterPath=NULL; + +struct YAMNExportedFcn +{ + YAMN_SETFILTERPLUGINFCNIMPORTFCN SetFilterPluginFcnImportFcn; + MIRANDASERVICE RegisterFilterPlugin; +} YAMNFcn,*pYAMNFcn; //exported functions from YAMN we will use + +HYAMNFILTERPLUGIN POPFilePlugin; //handle of this plugin for YAMN +HINSTANCE hInst; //handle of this DLL for Windows + +#ifdef DEBUG_FILTER +extern void InitDebug(); +extern void UnInitDebug(); +extern void DebugLog(HANDLE File,const char *fmt,...); +extern HANDLE FilterFile; +#endif + +extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved) +{ + hInst=hinstDLL; + return true; +} + +extern "C" int __declspec(dllexport) LoadFilter(MIRANDASERVICE GetYAMNFcnPtr) +{ + FilterPath=new char[MAX_PATH]; + char *delim; + pYAMNFcn=&YAMNFcn; + + GetModuleFileName(GetModuleHandle(NULL),FilterPath,MAX_PATH); + if(NULL!=(delim=strrchr(FilterPath,'\\'))) + *delim=0; + lstrcat(FilterPath,"\\basefilterdeny.txt"); +#ifdef DEBUG_FILTER + InitDebug(); +#endif + + if(!LoadRules()) + return 0; + + pYAMNFcn->RegisterFilterPlugin=(MIRANDASERVICE)GetYAMNFcnPtr((WPARAM)MS_YAMN_REGISTERFILTERPLUGIN,(LPARAM)0); + pYAMNFcn->SetFilterPluginFcnImportFcn=(YAMN_SETFILTERPLUGINFCNIMPORTFCN)GetYAMNFcnPtr((WPARAM)YAMN_SETFILTERPLUGINFCNIMPORTID,(LPARAM)0); +//Register our filter plugin to YAMN + if(NULL==(POPFilePlugin=(HYAMNFILTERPLUGIN)pYAMNFcn->RegisterFilterPlugin((WPARAM)&FilterRegistration,(LPARAM)YAMN_FILTERREGISTRATIONVERSION))) + return 0; +//And add our imported functions for YAMN + if(!pYAMNFcn->SetFilterPluginFcnImportFcn(POPFilePlugin,0xb0000000,&FilterFunctions,YAMN_FILTERIMPORTFCNVERSION)) + return 0; + return 1; //Load luccess +} + +DWORD WINAPI UnLoadFilter(LPVOID) +{ +#ifdef DEBUG_FILTER + UnInitDebug(); +#endif + if(FilterPath!=NULL) + delete[] FilterPath; + FilterPath=NULL; + + return 0; +} + +extern "C" int __declspec(dllexport) UninstallFilter() +{ + if(FilterPath==NULL) + MessageBox(NULL,"Cannot delete blacklist file when Base Filter is not loaded. Please do it manually.","Base Filter uninstalling",MB_OK|MB_ICONWARNING); + else + DeleteFile(FilterPath); + return 0; +} + + +//And this is main filter function. +DWORD WINAPI FilterMail(HACCOUNT Account,DWORD AccountVer,HYAMNMAIL Mail,DWORD MailVer) +{ + struct CMimeItem *Browser; + + if(MailVer!=YAMN_MAILVERSION) //we test if we work with the right YAMNMAIL + return 0; + if(Mail->MailData==NULL) //MailData should be available + return 0; + +#ifdef DEBUG_FILTER + DebugLog(FilterFile,"\n"); +#endif + if(!(Mail->Flags & YAMN_MSG_VIRTUAL)) + for(Browser=Mail->MailData->TranslatedHeader;Browser!=NULL;Browser=Browser->Next) //we browse all header stored in Mail->TranslatedHeader + { +#ifdef DEBUG_FILTER + DebugLog(FilterFile,"\n",Browser->name,Browser->value); +#endif + for(int i=0;iname,ft[i].name)) + { +#ifdef DEBUG_FILTER + DebugLog(FilterFile,"\t\t\n",Browser->name); +#endif + if(findsubstr(Browser->value,ft[i].value)) //and if we find + { + if((ft[i].sl==0) && ((Mail->Flags & YAMN_MSG_SPAMMASK)==0)) + { + Mail->Flags&=~(YAMN_MSG_POPUP | YAMN_MSG_SYSTRAY | YAMN_MSG_BROWSER | YAMN_MSG_SOUND | YAMN_MSG_APP | YAMN_MSG_NEVENT); +#ifdef DEBUG_FILTER + DebugLog(FilterFile,"\t\tSetting individual flags not to notify mail, but does not consider as spam."); +#endif + } + else if((Mail->Flags & YAMN_MSG_SPAMMASK) < ft[i].sl) //if some filter plugin set higher level of spam, we do nothing + { + Mail->Flags=(Mail->Flags & ~YAMN_MSG_SPAMMASK)+ft[i].sl; //else we set spam level 2 (clearing spam bits and then settting them to level 2 +#ifdef DEBUG_FILTER + DebugLog(FilterFile,"\t\tMail marked to be spam #%d\n",Mail->Flags & YAMN_MSG_SPAMMASK); +#endif + } + } +#ifdef DEBUG_FILTER + DebugLog(FilterFile,"\t\t\n"); +#endif + } +#ifdef DEBUG_FILTER + DebugLog(FilterFile,"\n"); +#endif + } +#ifdef DEBUG_FILTER + DebugLog(FilterFile,"\n\n"); +#endif + return 1; +} + +int LoadRules() +{ + char *account=NULL; + char name[256]; + char value[256]; + char BadCompiler[512+5]; + unsigned char sl; + FILE *fp; + +#ifdef DEBUG_FILTER + DebugLog(FilterFile,"\n",FilterPath); +#endif + + fp=fopen(FilterPath,"rt"); + if(fp==NULL) + return 0; + + while(!feof(fp)) + { + if(fscanf(fp,"%255s",name) && !feof(fp) && (name[0]!=0)) + { + if(fscanf(fp,"%255s",value) && !feof(fp) && (value[0]!=0)) + { + if(fscanf(fp,"%d",&sl)) + { + fts++; + ft=(struct cFilterTable *)realloc((void *)ft,sizeof(cFilterTable)*fts); + lstrcpy(ft[fts-1].name,name); + lstrcpy(ft[fts-1].value,value); + ft[fts-1].sl=sl; + + sprintf(BadCompiler,"%s %s %d",name,value,sl); +#ifdef DEBUG_FILTER + DebugLog(FilterFile,"\t%s%s%d\n",name,value,sl); +#endif + } + } + } + } + + fclose(fp); +#ifdef DEBUG_FILTER + DebugLog(FilterFile,"\n"); +#endif + return 1; +} + +int findsubstr(char *original,char *pattern) +{ + int ol=lstrlen(original); + int pl=lstrlen(pattern); + + for(int i=0;(i+pl)<=ol;i++) + if(!_strnicmp(original+i,pattern,pl)) + return 1; + return 0; +} \ No newline at end of file diff --git a/yamn/filter/Simple/AggressiveOptimize.h b/yamn/filter/Simple/AggressiveOptimize.h new file mode 100644 index 0000000..1bf0e19 --- /dev/null +++ b/yamn/filter/Simple/AggressiveOptimize.h @@ -0,0 +1,168 @@ + +////////////////////////////// +// Version 1.40 +// October 22nd, 2002 - .NET (VC7, _MSC_VER=1300) support! +// Version 1.30 +// Nov 24th, 2000 +// Version 1.20 +// Jun 9th, 2000 +// Version 1.10 +// Jan 23rd, 2000 +// Version 1.00 +// May 20th, 1999 +// Todd C. Wilson, Fresh Ground Software +// (todd@nopcode.com) +// This header file will kick in settings for Visual C++ 5 and 6 that will (usually) +// result in smaller exe's. +// The "trick" is to tell the compiler to not pad out the function calls; this is done +// by not using the /O1 or /O2 option - if you do, you implicitly use /Gy, which pads +// out each and every function call. In one single 500k dll, I managed to cut out 120k +// by this alone! +// The other two "tricks" are telling the Linker to merge all data-type segments together +// in the exe file. The relocation, read-only (constants) data, and code section (.text) +// sections can almost always be merged. Each section merged can save 4k in exe space, +// since each section is padded out to 4k chunks. This is very noticeable with smaller +// exes, since you could have only 700 bytes of data, 300 bytes of code, 94 bytes of +// strings - padded out, this could be 12k of runtime, for 1094 bytes of stuff! For larger +// programs, this is less overall, but can save at least 4k. +// Note that if you're using MFC static or some other 3rd party libs, you may get poor +// results with merging the readonly (.rdata) section - the exe may grow larger. +// To use this feature, define _MERGE_DATA_ in your project or before this header is used. +// With Visual C++ 5, the program uses a file alignment of 512 bytes, which results +// in a small exe. Under VC6, the program instead uses 4k, which is the same as the +// section size. The reason (from what I understand) is that 4k is the chunk size of +// the virtual memory manager, and that WinAlign (an end-user tuning tool for Win98) +// will re-align the programs on this boundary. The problem with this is that all of +// Microsoft's system exes and dlls are *NOT* tuned like this, and using 4k causes serious +// exe bloat. This is very noticeable for smaller programs. +// The "trick" for this is to use the undocumented FILEALIGN linker parm to change the +// padding from 4k to 1/2k, which results in a much smaller exe - anywhere from 20%-75% +// depending on the size. Note that this is the same as using /OPT:NOWIN98, which *is* +// a previously documented switch, but was left out of the docs for some reason in VC6 and +// all of the current MSDN's - see KB:Q235956 for more information. +// Microsoft does say that using the 4k alignment will "speed up process loading", +// but I've been unable to notice a difference, even on my P180, with a very large (4meg) exe. +// Please note, however, that this will probably not change the size of the COMPRESSED +// file (either in a .zip file or in an install archive), since this 4k is all zeroes and +// gets compressed away. +// Also, the /ALIGN:4096 switch will "magically" do the same thing, even though this is the +// default setting for this switch. Apparently this sets the same values as the above two +// switches do. We do not use this in this header, since it smacks of a bug and not a feature. +// Thanks to Michael Geary for some additional tips! +// +// Notes about using this header in .NET +// First off, VC7 does not allow a lot of the linker command options in pragma's. There is no +// honest or good reason why Microsoft decided to make this change, it just doesn't. +// So that is why there are a lot of <1300 #if's in the header. +// If you want to take full advantage of the VC7 linker options, you will need to do it on a +// PER PROJECT BASIS; you can no longer use a global header file like this to make it better. +// Items I strongly suggest putting in all your VC7 project linker options command line settings: +// /ignore:4078 /RELEASE +// Compiler options: +// /GL (Whole Program Optimization) +// If you're making an .EXE and not a .DLL, consider adding in: +// /GA (Optimize for Windows Application) +// Some items to consider using in your VC7 projects (not VC6): +// Link-time Code Generation - whole code optimization. Put this in your exe/dll project link settings. +// /LTCG:NOSTATUS +// The classic no-padding and no-bloat compiler C/C++ switch: +// /opt:nowin98 +// +// (C++ command line options: /GL /opt:nowin98 and /GA for .exe files) +// (Link command line options: /ignore:4078 /RELEASE /LTCG:NOSTATUS) +// +// Now, notes on using these options in VC7 vs VC6. +// VC6 consistently, for me, produces smaller code from C++ the exact same sources, +// with or without this header. On average, VC6 produces 5% smaller binaries compared +// to VC7 compiling the exact same project, *without* this header. With this header, VC6 +// will make a 13k file, while VC7 will make a 64k one. VC7 is just bloaty, pure and +// simple - all that managed/unmanaged C++ runtimes, and the CLR stuff must be getting +// in the way of code generation. However, template support is better, so there. +// Both VC6 and VC7 show the same end kind of end result savings - larger binary output +// will shave about 2% off, where as smaller projects (support DLL's, cpl's, +// activex controls, ATL libs, etc) get the best result, since the padding is usually +// more than the actual usable code. But again, VC7 does not compile down as small as VC6. +// +// The argument can be made that doing this is a waste of time, since the "zero bytes" +// will be compressed out in a zip file or install archive. Not really - it doesn't matter +// if the data is a string of zeroes or ones or 85858585 - it will still take room (20 bytes +// in a zip file, 29 bytes if only *4* of them 4k bytes are not the same) and time to +// compress that data and decompress it. Also, 20k of zeros is NOT 20k on disk - it's the +// size of the cluster slop- for Fat32 systems, 20k can be 32k, NTFS could make it 24k if you're +// just 1 byte over (round up). Most end users do not have the dual P4 Xeon systems with +// two gigs of RDram and a Raid 0+1 of Western Digital 120meg Special Editions that all +// worthy developers have (all six of us), so they will need any space and LOADING TIME +// savings they will need; taking an extra 32k or more out of your end user's 64megs of +// ram on Windows 98 is Not a Good Thing. +// +// Now, as a ADDED BONUS at NO EXTRA COST TO YOU! Under VC6, using the /merge:.text=.data +// pragma will cause the output file to be un-disassembleable! (is that a word?) At least, +// with the normal tools - WinDisam, DumpBin, and the like will not work. Try it - use the +// header, compile release, and then use DUMPBIN /DISASM filename.exe - no code! +// Thanks to Gëzim Pani for discovering this gem - for a full writeup on +// this issue and the ramifactions of it, visit www.nopcode.com for the Aggressive Optimize +// article. + +#ifndef _AGGRESSIVEOPTIMIZE_H_ +#define _AGGRESSIVEOPTIMIZE_H_ + +#pragma warning(disable:4711) + +#ifdef NDEBUG +// /Og (global optimizations), /Os (favor small code), /Oy (no frame pointers) +#pragma optimize("gsy",on) + +#if (_MSC_VER<1300) + #pragma comment(linker,"/RELEASE") +#endif + +/* +// Note that merging the .rdata section will result in LARGER exe's if you using +// MFC (esp. static link). If this is desirable, define _MERGE_RDATA_ in your project. +#ifdef _MERGE_RDATA_ +#pragma comment(linker,"/merge:.rdata=.data") +#endif // _MERGE_RDATA_ + +#pragma comment(linker,"/merge:.text=.data") +#if (_MSC_VER<1300) + // In VC7, this causes problems with the relocation and data tables, so best to not merge them + #pragma comment(linker,"/merge:.reloc=.data") +#endif +*/ + +// Merging sections with different attributes causes a linker warning, so +// turn off the warning. From Michael Geary. Undocumented, as usual! +#if (_MSC_VER<1300) + // In VC7, you will need to put this in your project settings + #pragma comment(linker,"/ignore:4078") +#endif + +// With Visual C++ 5, you already get the 512-byte alignment, so you will only need +// it for VC6, and maybe later. +#if _MSC_VER >= 1000 + +// Option #1: use /filealign +// Totally undocumented! And if you set it lower than 512 bytes, the program crashes. +// Either leave at 0x200 or 0x1000 +//#pragma comment(linker,"/FILEALIGN:0x200") + +// Option #2: use /opt:nowin98 +// See KB:Q235956 or the READMEVC.htm in your VC directory for info on this one. +// This is our currently preferred option, since it is fully documented and unlikely +// to break in service packs and updates. +#if (_MSC_VER<1300) + // In VC7, you will need to put this in your project settings + #pragma comment(linker,"/opt:nowin98") +#else + +// Option #3: use /align:4096 +// A side effect of using the default align value is that it turns on the above switch. +// Does nothing under Vc7 that /opt:nowin98 doesn't already give you +// #pragma comment(linker,"/ALIGN:512") +#endif + +#endif // _MSC_VER >= 1000 + +#endif // NDEBUG + +#endif // _AGGRESSIVEOPTIMIZE_H_ diff --git a/yamn/filter/Simple/docs/simple-readme.txt b/yamn/filter/Simple/docs/simple-readme.txt new file mode 100644 index 0000000..34c0842 --- /dev/null +++ b/yamn/filter/Simple/docs/simple-readme.txt @@ -0,0 +1,51 @@ +========================== += Simple Filter for YAMN = +========================== + +Q: What??? +A: YAMN filter to classify incoming email. + +Q: How? +A: Regarding what the email is from and finding it in the blacklist email file. + +Q: Blacklist email file? +A: Yes. It is created by yourself and located in Miranda directory with name 'simplefilterdeny.txt' + +Q: Created by myself? +A: Just create the file and write there your blacklist mails in every line. + +Q: That's all? +A: Yes and no. You can specify spamlevel for each mail. + +Q: Spamlevel? +A: Yes. + 1=notify, display with another color in mailbrowser + 2=do not notify, display with another color in mailbrowser + 3=delete, display in mailbrowser about deleted mail + 4=delete, do not display (mail's quick death, hehe) + +Q: How to specify it? +A: After email press and write number 1-4. Note this is optional. If not defined, level 2 is default. + +Q: Ok, that's easy. +A: Yes, this is the example: +<------ start of file ------> +nigeria@spamserver.com 2 +cheapsoftware@junkmails.net 3 +learnenglish@commercial.org +<------ end of file -------> + +Q: Wait while. Ok, but it does not work. +A: Check if you have this plugin listed in Miranda/Options/Plugins/YAMN item as YAMN plugin. + +Q: No, it is not listed in YAMN plugins. +A: Then check if the dll residents in Plugins/YAMN direcotry. + +Q: This directory does not exists. +A: Create it and put the dll there. Restart Miranda. + +Q: Hmmm, ok. But it is not still listed. +A: Your version of YAMN and filter does not match. + +Q: And? +A: Try to look to http://www.majvan.host.sk/Projekty/YAMN for updates. \ No newline at end of file diff --git a/yamn/filter/Simple/maindll.cpp b/yamn/filter/Simple/maindll.cpp new file mode 100644 index 0000000..7748835 --- /dev/null +++ b/yamn/filter/Simple/maindll.cpp @@ -0,0 +1,132 @@ +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../m_filterplugin.h" +#if !defined(_WIN64) + #include "aggressiveoptimize.h" +#endif + +typedef INT_PTR(* MIRANDASERVICE)(WPARAM,LPARAM); + +DWORD WINAPI FilterMail(HACCOUNT Account,DWORD AccountVer,HYAMNMAIL Mail,DWORD MailVer);//Function marks mail as spam when it is spam... +DWORD WINAPI UnLoadFilter(LPVOID); + +YAMN_FILTERIMPORTFCN FilterFunctions= //we set for YAMN which is our filter function +{ + FilterMail, + UnLoadFilter, //No unloading +}; + +YAMN_FILTERREGISTRATION FilterRegistration= //classical YAMN registration +{ + "Simple filter plugin for YAMN", + __DATE__, + "© porter+ majvan", + "Classifies mails using the blacklist emails stored in file", + "porterbox@hotmail.com", + "http://www.majvan.host.sk/Projekty/YAMN?fm=soft", +}; + +char *FilterPath=NULL; + +struct YAMNExportedFcn +{ + YAMN_SETFILTERPLUGINFCNIMPORTFCN SetFilterPluginFcnImportFcn; + MIRANDASERVICE RegisterFilterPlugin; +} YAMNFcn,*pYAMNFcn; //exported functions from YAMN we will use + +HYAMNFILTERPLUGIN POPFilePlugin; //handle of this plugin for YAMN +HINSTANCE hInst; //handle of this DLL for Windows + +extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved) +{ + hInst=hinstDLL; + return true; +} + +extern "C" int __declspec(dllexport) LoadFilter(MIRANDASERVICE GetYAMNFcnPtr) +{ + FilterPath=new char[MAX_PATH]; + char *delim; + pYAMNFcn=&YAMNFcn; + + GetModuleFileName(GetModuleHandle(NULL),FilterPath,MAX_PATH); + if(NULL!=(delim=strrchr(FilterPath,'\\'))) + *delim=0; + lstrcat(FilterPath,"\\simplefilterdeny.txt"); + + pYAMNFcn->RegisterFilterPlugin=(MIRANDASERVICE)GetYAMNFcnPtr((WPARAM)MS_YAMN_REGISTERFILTERPLUGIN,(LPARAM)0); + pYAMNFcn->SetFilterPluginFcnImportFcn=(YAMN_SETFILTERPLUGINFCNIMPORTFCN)GetYAMNFcnPtr((WPARAM)YAMN_SETFILTERPLUGINFCNIMPORTID,(LPARAM)0); +//Register our filter plugin to YAMN + if(NULL==(POPFilePlugin=(HYAMNFILTERPLUGIN)pYAMNFcn->RegisterFilterPlugin((WPARAM)&FilterRegistration,(LPARAM)YAMN_FILTERREGISTRATIONVERSION))) + return 0; +//And add our imported functions for YAMN + if(!pYAMNFcn->SetFilterPluginFcnImportFcn(POPFilePlugin,0xb0000000,&FilterFunctions,YAMN_FILTERIMPORTFCNVERSION)) + return 0; + return 1; //Load luccess +} + +DWORD WINAPI UnLoadFilter(LPVOID) +{ + if(FilterPath!=NULL) + delete[] FilterPath; + FilterPath=NULL; + + return 0; +} + +extern "C" int __declspec(dllexport) UninstallFilter() +{ + if(FilterPath==NULL) + MessageBox(NULL,"Cannot delete blacklist file when Simple Filter is not loaded. Please do it manually.","Simple Filter uninstalling",MB_OK|MB_ICONWARNING); + else + DeleteFile(FilterPath); + return 0; +} + + +//And this is main filter function. +DWORD WINAPI FilterMail(HACCOUNT Account,DWORD AccountVer,HYAMNMAIL Mail,DWORD MailVer) +{ + FILE *fp; + char EmailSpam[256]; + unsigned char spamLevel; + struct CMimeItem *Browser; + + if(MailVer!=YAMN_MAILVERSION) //we test if we work with the right YAMNMAIL + return 0; + if(Mail->MailData==NULL) //MailData should be available + return 0; + fp=fopen(FilterPath,"rt"); + if(fp != NULL) { + if(!(Mail->Flags & YAMN_MSG_VIRTUAL)) + for(Browser=Mail->MailData->TranslatedHeader;Browser!=NULL;Browser=Browser->Next) { //we browse all header stored in Mail->TranslatedHeader + if((!lstrcmp(Browser->name,"Return-Path")) || (!lstrcmp(Browser->name,"From"))) { //and if we find + fseek(fp, 0L, SEEK_SET); + while(!feof(fp)) { + if(fscanf(fp, "%255s", EmailSpam) != 0) { + if(!feof(fp)) + if(fscanf(fp, "%d", &spamLevel)==0) + spamLevel=2; + if(spamLevel>4) + spamLevel=2; + if(strstr(Browser->value,EmailSpam)!=NULL) { + if((Mail->Flags & (YAMN_MSG_SPAMMASK==0)) && (spamLevel==0)) + Mail->Flags&=~(YAMN_MSG_SOUND | YAMN_MSG_APP | YAMN_MSG_POPUP | YAMN_MSG_SYSTRAY | YAMN_MSG_BROWSER); + else if((Mail->Flags & YAMN_MSG_SPAMMASK) < spamLevel) //if some filter plugin set higher level of spam, we do nothing + Mail->Flags=(Mail->Flags & ~YAMN_MSG_SPAMMASK)+spamLevel; //else we set spam level 2 (clearing spam bits and then settting them to level 2 + } + } + } + } + } + fclose(fp); + } + return 1; +} diff --git a/yamn/filter/Simple/simple.dsp b/yamn/filter/Simple/simple.dsp new file mode 100644 index 0000000..dc6d52e --- /dev/null +++ b/yamn/filter/Simple/simple.dsp @@ -0,0 +1,105 @@ +# Microsoft Developer Studio Project File - Name="simple" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=simple - Win32 Release +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "simple.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "simple.mak" CFG="simple - Win32 Release" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "simple - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE "simple - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "simple - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Ignore_Export_Lib 1 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /G4 /Zp4 /MD /W3 /GX /O1 /Ob0 /I "../../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /G4 /Zp4 /MD /W3 /GX /Zi /O1 /Ob0 /I "../../../../include" /I "../../../../include/msapi" /I "../../../../include_API" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE RSC /l 0x417 /d "NDEBUG" +# ADD RSC /l 0x417 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib /nologo /dll /machine:I386 /out:"../../../../bin/release/plugins/YAMN-filter/simple.dll" /filealign:512 +# ADD LINK32 kernel32.lib user32.lib /nologo /dll /pdb:"../../../../bin/Release/plugins/YAMN/simple.pdb" /debug /machine:I386 /out:"../../../../bin/Release/plugins/YAMN/simple.dll" /filealign:512 + +!ELSEIF "$(CFG)" == "simple - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Ignore_Export_Lib 1 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /G4 /Zp4 /MDd /W3 /Gm /Gi /GX /ZI /Od /I "../../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /GZ /c +# ADD CPP /nologo /G4 /Zp4 /MDd /W3 /Gm /Gi /GX /ZI /Od /I "../../../../include" /I "../../../../include/msapi" /I "../../../../include_API" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /GZ /c +# ADD BASE RSC /l 0x417 /d "_DEBUG" +# ADD RSC /l 0x417 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib /nologo /dll /debug /machine:I386 /out:"../../../../bin/Debug/plugins/YAMN-filter/simple.dll" +# ADD LINK32 kernel32.lib user32.lib /nologo /dll /pdb:"../../../../bin/Debug/plugins/YAMN/simple.pdb" /debug /machine:I386 /out:"../../../../bin/Debug/plugins/YAMN/simple.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "simple - Win32 Release" +# Name "simple - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\maindll.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/yamn/filter/Simple/simple.mak b/yamn/filter/Simple/simple.mak new file mode 100644 index 0000000..085dc22 --- /dev/null +++ b/yamn/filter/Simple/simple.mak @@ -0,0 +1,207 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on simple.dsp +!IF "$(CFG)" == "" +CFG=simple - Win32 Release +!MESSAGE No configuration specified. Defaulting to simple - Win32 Release. +!ENDIF + +!IF "$(CFG)" != "simple - Win32 Release" && "$(CFG)" != "simple - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "simple.mak" CFG="simple - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "simple - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "simple - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "simple - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release + +ALL : "..\..\..\..\bin\release\plugins\YAMN-filter\simple.dll" + + +CLEAN : + -@erase "$(INTDIR)\maindll.obj" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(OUTDIR)\simple.exp" + -@erase "..\..\..\..\bin\release\plugins\YAMN-filter\simple.dll" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /G4 /Zp4 /MD /W3 /GX /O1 /Ob0 /I "../../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Fp"$(INTDIR)\simple.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ= +RSC=rc.exe +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\simple.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\simple.pdb" /machine:I386 /out:"../../../../bin/release/plugins/YAMN-filter/simple.dll" /implib:"$(OUTDIR)\simple.lib" /filealign:512 +LINK32_OBJS= \ + "$(INTDIR)\maindll.obj" + +"..\..\..\..\bin\release\plugins\YAMN-filter\simple.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "simple - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +ALL : "..\..\..\..\bin\Debug\plugins\YAMN-filter\simple.dll" "$(OUTDIR)\simple.bsc" + + +CLEAN : + -@erase "$(INTDIR)\maindll.obj" + -@erase "$(INTDIR)\maindll.sbr" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(INTDIR)\vc60.pdb" + -@erase "$(OUTDIR)\simple.bsc" + -@erase "$(OUTDIR)\simple.exp" + -@erase "$(OUTDIR)\simple.pdb" + -@erase "..\..\..\..\bin\Debug\plugins\YAMN-filter\simple.dll" + -@erase "..\..\..\..\bin\Debug\plugins\YAMN-filter\simple.ilk" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /G4 /Zp4 /MDd /W3 /Gm /Gi /GX /ZI /Od /I "../../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\simple.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ= +RSC=rc.exe +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\simple.bsc" +BSC32_SBRS= \ + "$(INTDIR)\maindll.sbr" + +"$(OUTDIR)\simple.bsc" : "$(OUTDIR)" $(BSC32_SBRS) + $(BSC32) @<< + $(BSC32_FLAGS) $(BSC32_SBRS) +<< + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\simple.pdb" /debug /machine:I386 /out:"../../../../bin/Debug/plugins/YAMN-filter/simple.dll" /implib:"$(OUTDIR)\simple.lib" +LINK32_OBJS= \ + "$(INTDIR)\maindll.obj" + +"..\..\..\..\bin\Debug\plugins\YAMN-filter\simple.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("simple.dep") +!INCLUDE "simple.dep" +!ELSE +!MESSAGE Warning: cannot find "simple.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "simple - Win32 Release" || "$(CFG)" == "simple - Win32 Debug" +SOURCE=.\maindll.cpp + +!IF "$(CFG)" == "simple - Win32 Release" + + +"$(INTDIR)\maindll.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "simple - Win32 Debug" + + +"$(INTDIR)\maindll.obj" "$(INTDIR)\maindll.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + + +!ENDIF + diff --git a/yamn/filter/readme.txt b/yamn/filter/readme.txt new file mode 100644 index 0000000..a46db02 --- /dev/null +++ b/yamn/filter/readme.txt @@ -0,0 +1 @@ +This folder contains filter plugin sources for YAMN. \ No newline at end of file diff --git a/yamn/filterplugin.cpp b/yamn/filterplugin.cpp new file mode 100644 index 0000000..cf7252d --- /dev/null +++ b/yamn/filterplugin.cpp @@ -0,0 +1,226 @@ +/* + * YAMN plugin export functions for filtering + * + * (c) majvan 2002-2004 + */ + +#include +#include +#include +#include +#include +#include "m_yamn.h" +#include "m_filterplugin.h" +#include "mails/m_mails.h" +#include "debug.h" + +//- imported --------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +//From main.cpp +extern LPCRITICAL_SECTION PluginRegCS; +extern YAMN_VARIABLES YAMNVar; +//From synchro.cpp +extern DWORD WINAPI WaitToWriteFcn(PSWMRG SObject,PSCOUNTER=NULL); +extern void WINAPI WriteDoneFcn(PSWMRG SObject,PSCOUNTER=NULL); +//From maild.cpp +extern INT_PTR LoadMailDataSvc(WPARAM wParam,LPARAM lParam); +extern INT_PTR UnloadMailDataSvc(WPARAM wParam,LPARAM); +extern INT_PTR SaveMailDataSvc(WPARAM wParam,LPARAM lParam); + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +PYAMN_FILTERPLUGINQUEUE FirstFilterPlugin=NULL; + +INT_PTR RegisterFilterPluginSvc(WPARAM,LPARAM); + +//Removes plugin from queue and deletes its structures +INT_PTR UnregisterFilterPlugin(HYAMNFILTERPLUGIN Plugin); + +INT_PTR UnregisterFilterPluginSvc(WPARAM wParam,LPARAM lParam); + +//Removes all filter plugins +INT_PTR UnregisterFilterPlugins(); + +INT_PTR FilterMailSvc(WPARAM,LPARAM); + +//Sets imported functions for an plugin and therefore it starts plugin to be registered and running +// Plugin- plugin, which wants to set its functions +// Importance- importance of plugin (see m_filterplugin.h) +// YAMNFilterFcn- pointer to imported functions +// YAMNfilterFcnVer- version of YAMN_FILTERIMPORTFCN, use YAMN_FILTERIMPORTFCNVERSION +// returns nonzero if success +int WINAPI SetFilterPluginFcnImportFcn(HYAMNFILTERPLUGIN Plugin,DWORD Importance,PYAMN_FILTERIMPORTFCN YAMNFilterFcn,DWORD YAMNFilterFcnVer); + +struct CExportedFunctions FilterPluginExportedFcn[]= +{ + {YAMN_SETFILTERPLUGINFCNIMPORTID,(void *)SetFilterPluginFcnImportFcn}, +}; + +struct CExportedServices FilterPluginExportedSvc[]= +{ + {MS_YAMN_REGISTERFILTERPLUGIN,RegisterFilterPluginSvc}, + {MS_YAMN_UNREGISTERFILTERPLUGIN,UnregisterFilterPluginSvc}, +}; + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +INT_PTR RegisterFilterPluginSvc(WPARAM wParam,LPARAM lParam) +{ + PYAMN_FILTERREGISTRATION Registration=(PYAMN_FILTERREGISTRATION)wParam; + HYAMNFILTERPLUGIN Plugin; + + if(lParam!=YAMN_FILTERREGISTRATIONVERSION) + return 0; + if((Registration->Name==NULL) || (Registration->Ver==NULL)) + return NULL; + if(NULL==(Plugin=new YAMN_FILTERPLUGIN)) + return NULL; + + Plugin->PluginInfo=Registration; + + Plugin->FilterFcn=NULL; + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"::: YAMN- new filter registered: %0x (%s) :::\n",Plugin,Registration->Name); +#endif + return (INT_PTR)Plugin; +} + +INT_PTR UnregisterFilterPlugin(HYAMNFILTERPLUGIN Plugin) +{ + PYAMN_FILTERPLUGINQUEUE Parser,Found; + + if(FirstFilterPlugin->Plugin==Plugin) + { + Found=FirstFilterPlugin; + FirstFilterPlugin=FirstFilterPlugin->Next; + } + else + { + for(Parser=FirstFilterPlugin;(Parser->Next!=NULL) && (Plugin!=Parser->Next->Plugin);Parser=Parser->Next); + if(Parser->Next!=NULL) + { + Found=Parser->Next; + Parser->Next=Parser->Next->Next; + } + else + Found=NULL; + } + if(Found!=NULL) + { + if(Plugin->FilterFcn->UnLoadFcn!=NULL) + Plugin->FilterFcn->UnLoadFcn((void *)0); + + delete Found->Plugin; + delete Found; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"::: YAMN- filter %0x unregistered :::\n",Plugin); +#endif + } + else + return 0; + return 1; +} + +INT_PTR UnregisterFilterPluginSvc(WPARAM wParam,LPARAM lParam) +{ + HYAMNFILTERPLUGIN Plugin=(HYAMNFILTERPLUGIN)wParam; + + EnterCriticalSection(PluginRegCS); + UnregisterFilterPlugin(Plugin); + LeaveCriticalSection(PluginRegCS); + return 1; +} + +INT_PTR UnregisterFilterPlugins() +{ + EnterCriticalSection(PluginRegCS); +//We remove protocols from the protocol list + while(FirstFilterPlugin!=NULL) + UnregisterFilterPlugin(FirstFilterPlugin->Plugin); + LeaveCriticalSection(PluginRegCS); + return 1; +} + +int WINAPI SetFilterPluginFcnImportFcn(HYAMNFILTERPLUGIN Plugin,DWORD Importance,PYAMN_FILTERIMPORTFCN YAMNFilterFcn,DWORD YAMNFilterFcnVer) +{ + PYAMN_FILTERPLUGINQUEUE Parser,Previous; + + if(YAMNFilterFcnVer!=YAMN_FILTERIMPORTFCNVERSION) + return 0; + if(YAMNFilterFcn==NULL) + return 0; + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"::: YAMN- filter %0x import succeed :::\n",Plugin); +#endif + Plugin->Importance=Importance; + Plugin->FilterFcn=YAMNFilterFcn; + + EnterCriticalSection(PluginRegCS); +//We add protocol to the protocol list + for(Previous=NULL,Parser=FirstFilterPlugin;Parser!=NULL && Parser->Next!=NULL && Parser->Plugin->Importance<=Importance;Previous=Parser,Parser=Parser->Next); + if(Previous==NULL) //insert to the beginnig of queue + { + FirstFilterPlugin=new YAMN_FILTERPLUGINQUEUE; + FirstFilterPlugin->Plugin=Plugin; + FirstFilterPlugin->Next=Parser; + } + else + { + Previous->Next=new YAMN_FILTERPLUGINQUEUE; + Previous=Previous->Next; //leave previous, go to actual plugin + Previous->Plugin=Plugin; + Previous->Next=Parser; //and in actual plugin set, that next plugin is the one we insert in front of + } + + LeaveCriticalSection(PluginRegCS); + return 1; +} + +INT_PTR FilterMailSvc(WPARAM wParam,LPARAM lParam) +{ + HACCOUNT Account=(HACCOUNT)wParam; + HYAMNMAIL Mail=(HYAMNMAIL)lParam; + PYAMN_FILTERPLUGINQUEUE ActualPlugin; + + EnterCriticalSection(PluginRegCS); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"FilterMail:ActualAccountMsgsSO-write wait\n"); +#endif + WaitToWriteFcn(Account->MessagesAccessSO); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"FilterMail:ActualAccountMsgsSO-write enter\n"); +#endif + for(ActualPlugin=FirstFilterPlugin;ActualPlugin!=NULL;ActualPlugin=ActualPlugin->Next) + { + if(ActualPlugin->Plugin->FilterFcn->FilterMailFcnPtr!=NULL) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tFiltering Mail, running plugin %0x to filter mail\n",ActualPlugin->Plugin); +#endif + ActualPlugin->Plugin->FilterFcn->FilterMailFcnPtr(Account,YAMN_ACCOUNTVERSION,Mail,YAMN_MAILVERSION); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tFiltering Mail done\n"); +#endif + } + } + Mail->Flags|=YAMN_MSG_FILTERED; + +//Set mail flags according to spamlevel settings + if((Mail->Flags & YAMN_MSG_SPAMMASK) > YAMN_MSG_SPAML1) + Mail->Flags=Mail->Flags & ~(YAMN_MSG_BROWSER | YAMN_MSG_POPUP | YAMN_MSG_SYSTRAY | YAMN_MSG_SOUND | YAMN_MSG_APP | YAMN_MSG_NEVENT); + if(YAMN_MSG_SPAML(Mail->Flags,YAMN_MSG_SPAML3) || YAMN_MSG_SPAML(Mail->Flags,YAMN_MSG_SPAML4)) + Mail->Flags=Mail->Flags | (YAMN_MSG_AUTODELETE | YAMN_MSG_DELETEOK); //set message to delete + if(YAMN_MSG_SPAML(Mail->Flags,YAMN_MSG_SPAML3)) + Mail->Flags=Mail->Flags & ~(YAMN_MSG_MEMDELETE); //set message not to delete it immidiatelly from memory +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"FilterMail:ActualAccountMsgsSO-write done\n"); +#endif + WriteDoneFcn(Account->MessagesAccessSO); + LeaveCriticalSection(PluginRegCS); + return 1; +} diff --git a/yamn/icons/iconttbup.ico b/yamn/icons/iconttbup.ico new file mode 100644 index 0000000..ad18c56 Binary files /dev/null and b/yamn/icons/iconttbup.ico differ diff --git a/yamn/icons/icoyamn1.ico b/yamn/icons/icoyamn1.ico new file mode 100644 index 0000000..d3959b4 Binary files /dev/null and b/yamn/icons/icoyamn1.ico differ diff --git a/yamn/icons/icoyamn2.ico b/yamn/icons/icoyamn2.ico new file mode 100644 index 0000000..dfada56 Binary files /dev/null and b/yamn/icons/icoyamn2.ico differ diff --git a/yamn/icons/proto_YAMN.dsp b/yamn/icons/proto_YAMN.dsp new file mode 100644 index 0000000..93652ba --- /dev/null +++ b/yamn/icons/proto_YAMN.dsp @@ -0,0 +1,91 @@ +# Microsoft Developer Studio Project File - Name="proto_YAMN" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=proto_YAMN - Win32 Release +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "proto_YAMN.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "proto_YAMN.mak" CFG="proto_YAMN - Win32 Release" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "proto_YAMN - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo +# ADD CPP /nologo +# ADD BASE RSC /l 0x417 /d "NDEBUG" +# ADD RSC /l 0x417 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 /nologo /subsystem:windows /dll /pdb:none /machine:I386 /nodefaultlib /out:"../../../bin/release/icons/proto_YAMN.dll" /filealign:512 /noentry +# ADD LINK32 /nologo /subsystem:windows /dll /pdb:none /machine:I386 /nodefaultlib /out:"../../../bin/Release/Icons/proto_YAMN.dll" /filealign:512 /noentry +# Begin Target + +# Name "proto_YAMN - Win32 Release" +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=..\resources\iconeutral.ico +# End Source File +# Begin Source File + +SOURCE=..\resources\iconttbdown.ico +# End Source File +# Begin Source File + +SOURCE=iconttbup.ico +# End Source File +# Begin Source File + +SOURCE=..\resources\icooffline.ico +# End Source File +# Begin Source File + +SOURCE=icoyamn1.ico +# End Source File +# Begin Source File + +SOURCE=icoyamn2.ico +# End Source File +# Begin Source File + +SOURCE=..\resources\icoyamn3.ico +# End Source File +# Begin Source File + +SOURCE=proto_YAMN.rc +# End Source File +# End Group +# End Target +# End Project diff --git a/yamn/icons/proto_YAMN.mak b/yamn/icons/proto_YAMN.mak new file mode 100644 index 0000000..94c25d7 --- /dev/null +++ b/yamn/icons/proto_YAMN.mak @@ -0,0 +1,112 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on proto_YAMN.dsp +!IF "$(CFG)" == "" +CFG=proto_YAMN - Win32 Release +!MESSAGE No configuration specified. Defaulting to proto_YAMN - Win32 Release. +!ENDIF + +!IF "$(CFG)" != "proto_YAMN - Win32 Release" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "proto_YAMN.mak" CFG="proto_YAMN - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "proto_YAMN - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +OUTDIR=.\Release +INTDIR=.\Release + +ALL : "..\..\..\bin\release\icons\proto_YAMN.dll" + + +CLEAN : + -@erase "$(INTDIR)\proto_YAMN.res" + -@erase "$(OUTDIR)\proto_YAMN.exp" + -@erase "$(OUTDIR)\proto_YAMN.lib" + -@erase "..\..\..\bin\release\icons\proto_YAMN.dll" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /ML /Fo"$(INTDIR)\\" + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ= +RSC=rc.exe +RSC_PROJ=/l 0x417 /fo"$(INTDIR)\proto_YAMN.res" /d "NDEBUG" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\proto_YAMN.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=/nologo /subsystem:windows /dll /pdb:none /machine:I386 /nodefaultlib /out:"../../../bin/release/icons/proto_YAMN.dll" /implib:"$(OUTDIR)\proto_YAMN.lib" /filealign:512 /noentry +LINK32_OBJS= \ + "$(INTDIR)\proto_YAMN.res" + +"..\..\..\bin\release\icons\proto_YAMN.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("proto_YAMN.dep") +!INCLUDE "proto_YAMN.dep" +!ELSE +!MESSAGE Warning: cannot find "proto_YAMN.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "proto_YAMN - Win32 Release" +SOURCE=proto_YAMN.rc + +"$(INTDIR)\proto_YAMN.res" : $(SOURCE) "$(INTDIR)" + $(RSC) $(RSC_PROJ) $(SOURCE) + + + +!ENDIF + diff --git a/yamn/icons/proto_YAMN.rc b/yamn/icons/proto_YAMN.rc new file mode 100644 index 0000000..e20bd50 --- /dev/null +++ b/yamn/icons/proto_YAMN.rc @@ -0,0 +1,19 @@ +#include "resource.h" + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. + +IDI_ONLINE ICON DISCARDABLE "../resources/iconeutral.ico" +IDI_ICOYAMN1 ICON DISCARDABLE "icoyamn1.ico" +IDI_ICOYAMN2 ICON DISCARDABLE "icoyamn2.ico" +IDI_ICOTTBUP ICON DISCARDABLE "iconttbup.ico" + +IDI_OFFLINE ICON DISCARDABLE "../resources/icooffline.ico" +IDI_NA ICON DISCARDABLE "../resources/icoyamn3.ico" +IDI_OCCUPIED ICON DISCARDABLE "../resources/iconttbdown.ico" diff --git a/yamn/icons/resource.h b/yamn/icons/resource.h new file mode 100644 index 0000000..af36adf --- /dev/null +++ b/yamn/icons/resource.h @@ -0,0 +1,2 @@ +#include "../resources/resource.h" + diff --git a/yamn/include/IcoLib.h b/yamn/include/IcoLib.h new file mode 100644 index 0000000..a911ba5 --- /dev/null +++ b/yamn/include/IcoLib.h @@ -0,0 +1,26 @@ +typedef struct { + int cbSize; + char *pszSection; //section name used to group icons + char *pszDescription; //description for options dialog + char *pszName; //name to refer to icon when playing and in db + char *pszDefaultFile; //default icon file to use + int iDefaultIndex; +} SKINICONDESC; + +// +// Add a icon into options UI +// NB! pszName should be unique, e.g.: clistmw_apply, tabsrmm_history +// +// wParam = (WPARAM)0 +// lParam = (LPARAM)(SKINICONDESC*)sid; +// +#define MS_SKIN2_ADDICON "Skin2/Icons/AddIcon" +// +// Retrieve HICON with name specified in lParam +// Returned HICON SHOULDN'T be destroyed, it managed by IcoLib +// +#define MS_SKIN2_GETICON "Skin2/Icons/GetIcon" +// +// Icons change notification +// +#define ME_SKIN2_ICONSCHANGED "Skin2/IconsChanged" diff --git a/yamn/include/m_icolib.h b/yamn/include/m_icolib.h new file mode 100644 index 0000000..a31abe2 --- /dev/null +++ b/yamn/include/m_icolib.h @@ -0,0 +1,75 @@ +// ---------------------------------------------------------------------------80 +// Icons Library Manager plugin for Miranda Instant Messenger +// __________________________________________________________ +// +// Copyright © 2005 Denis Stanishevskiy // StDenis +// Copyright © 2006 Joe Kucera +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ----------------------------------------------------------------------------- + +#define SKINICONDESC_SIZE sizeof(SKINICONDESC) +#define SKINICONDESC_SIZE_V1 0x18 +#define SKINICONDESC_SIZE_V2 0x1C +#define SKINICONDESC_SIZE_V3 0x24 + +typedef struct { + int cbSize; + union { + char *pszSection; // section name used to group icons + TCHAR *ptszSection; + wchar_t *pwszSection; + }; + union { + char *pszDescription; // description for options dialog + TCHAR *ptszDescription; + wchar_t *pwszDescription; + }; + char *pszName; // name to refer to icon when playing and in db + char *pszDefaultFile; // default icon file to use + int iDefaultIndex; // index of icon in default file + HICON hDefaultIcon; // handle to default icon + int cx,cy; // dimensions of icon + int flags; +} SKINICONDESC; + +#define SIDF_UNICODE 0x100 // Section and Description are in UCS-2 + +#if defined(_UNICODE) + #define SIDF_TCHAR SIDF_UNICODE +#else + #define SIDF_TCHAR 0 +#endif + +// +// Add a icon into options UI +// +// wParam = (WPARAM)0 +// lParam = (LPARAM)(SKINICONDESC*)sid; +// +#define MS_SKIN2_ADDICON "Skin2/Icons/AddIcon" + +// +// Retrieve HICON with name specified in lParam +// Returned HICON SHOULDN'T be destroyed, it is managed by IcoLib +// + +#define MS_SKIN2_GETICON "Skin2/Icons/GetIcon" + +// +// Icons change notification +// +#define ME_SKIN2_ICONSCHANGED "Skin2/IconsChanged" diff --git a/yamn/include/m_kbdnotify.h b/yamn/include/m_kbdnotify.h new file mode 100644 index 0000000..256c009 --- /dev/null +++ b/yamn/include/m_kbdnotify.h @@ -0,0 +1,64 @@ +/* + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef _KBDNOTIFY_ +#define _KBDNOTIFY_ + +//Enables all notifications (for use by BossKey) +//wParam=0 +//lParam=0 +//returns 0 +#define MS_KBDNOTIFY_ENABLE "KeyboardNotify/Enable" + + +//Disables all notifications (for use by BossKey) +//wParam=0 +//lParam=0 +//returns 0 +#define MS_KBDNOTIFY_DISABLE "KeyboardNotify/Disable" + + +//Makes the flashing begin +//wParam=(unsigned int)eventCount +//lParam=(char *)szFlashingSequence or NULL if you want the plugin to use current settings +//returns 0 +#define MS_KBDNOTIFY_STARTBLINK "KeyboardNotify/StartBlinking" + + +//Receives the number of events that were opened (usuful for the 'until events opened' setting) +//wParam=(unsigned int)eventCount +//lParam=0 +//returns 0 +#define MS_KBDNOTIFY_EVENTSOPENED "KeyboardNotify/EventsWereOpened" + + +//Informs if the flashing is active +//wParam=0 +//lParam=0 +//returns 0 if the flashing is inactive or a pointer to the string representing the sequence being used +#define MS_KBDNOTIFY_FLASHINGACTIVE "KeyboardNotify/IsFlashingActive" + + +//Normalizes the flashing sequence informed +//wParam=0 +//lParam=(char *)szFlashingSequence <- it is rewritten +//returns a pointer to the string representing the sequence normalized (which is in fact lParam) +#define MS_KBDNOTIFY_NORMALSEQUENCE "KeyboardNotify/NormalizeSequence" + + +#endif diff --git a/yamn/include/m_popup.h b/yamn/include/m_popup.h new file mode 100644 index 0000000..9e5f179 --- /dev/null +++ b/yamn/include/m_popup.h @@ -0,0 +1,318 @@ +/* +=============================================================================== + PopUp plugin +Plugin Name: PopUp +Plugin authors: Luca Santarelli aka hrk (hrk@users.sourceforge.net) + Victor Pavlychko aka zazoo (nullbie@gmail.com) +=============================================================================== +The purpose of this plugin is to give developers a common "platform/interface" +to show PopUps. It is born from the source code of NewStatusNotify, another +plugin I've made. + +Remember that users *must* have this plugin enabled, or they won't get any +popup. Write this in the requirements, do whatever you wish ;-)... but tell +them! +=============================================================================== +*/ +#ifndef M_POPUP_H +#define M_POPUP_H + +/* +NOTE! Since Popup 1.0.1.2 there is a main meun group called "PopUps" where I +have put a "Enable/Disable" item. You can add your own "enable/disable" items +by adding these lines before you call MS_CLIST_ADDMAINMENUITEM: +mi.pszPopUpName = Translate("PopUps"); +mi.position = 0; //You don't need it and it's better if you put it to zero. +*/ + +//#define MAX_CONTACTNAME 32 +//#define MAX_SECONDLINE 40 +#define MAX_CONTACTNAME 2048 +#define MAX_SECONDLINE 2048 + +#define POPUP_USE_SKINNED_BG 0xffffffff + +//This is the basic data you'll need to fill and pass to the service function. +typedef struct { + HANDLE lchContact; //Handle to the contact, can be NULL (main contact). + HICON lchIcon; //Handle to a icon to be shown. Cannot be NULL. + char lpzContactName[MAX_CONTACTNAME]; //This is the contact name or the first line in the plugin. Cannot be NULL. + char lpzText[MAX_SECONDLINE]; //This is the second line text. Users can choose to hide it. Cannot be NULL. + COLORREF colorBack; //COLORREF to be used for the background. Can be NULL, default will be used. + COLORREF colorText; //COLORREF to be used for the text. Can be NULL, default will be used. + WNDPROC PluginWindowProc; //Read below. Can be NULL; default will be used. + void * PluginData; //Read below. Can be NULL. +} POPUPDATA, * LPPOPUPDATA; + +typedef struct { + HANDLE lchContact; + HICON lchIcon; + char lpzContactName[MAX_CONTACTNAME]; + char lpzText[MAX_SECONDLINE]; + COLORREF colorBack; //Set background to POPUP_USE_SKINNED_BG to turn on skinning + COLORREF colorText; + WNDPROC PluginWindowProc; + void * PluginData; + int iSeconds; //Custom delay time in seconds. -1 means "forever", 0 means "default time". +// char cZero[16]; + LPCTSTR lpzClass; //PopUp class. Used with skinning. See PopUp/AddClass for details + COLORREF skinBack; //Background color for colorizable skins + char cZero[16 - sizeof(LPCTSTR) - sizeof(COLORREF)]; + //some unused bytes which may come useful in the future. +} POPUPDATAEX, *LPPOPUPDATAEX; + +/* +When you call MS_POPUP_ADDPOPUP, my plugin will check if the given POPUPDATA structure is filled with acceptable values. If not, the data will be rejected and no popup will be shown. + +- lpzText should be given, because it's really bad if a user chooses to have the second line displayed +and it's empty :-) Just write it and let the user choose if it will be displayed or not. + +- PluginWindowProc is a WNDPROC address you have to give me. Why? What? Where? Calm down 8) +My plugin will take care of the creation of the popup, of the destruction of the popup, of the come into +view and the hiding of the popup. Transparency, animations... all this stuff. +My plugin will not (as example) open the MessageWindow when you left click on a popup. +Why? Because I don't know if your popup desires to open the MessageWindow :)))) +This means that you need to make a WNDPROC which takes care of the WM_messages you need. +For example, WM_COMMAND or WM_CONTEXTMENU or WM_LMOUSEUP or whatever. +At the end of your WNDPROC remember to "return DefWindowProc(hwnd, msg, wParam, lParam);" +When you process a message that needs a return value (an example could be WM_CTLCOLORSTATIC, +but you don't need to catch it 'cause it's my plugin's job), simply return the nedeed value. :) +The default WNDPROC does nothing. + +- PluginData is a pointer to a void, which means a pointer to anything. You can make your own structure +to store the data you need (example: a status information, a date, your name, whatever) and give me a +pointer to that struct. +You will need to destroy that structure and free the memory when the PopUp is going to be destroyed. You'll know this when you receive a UM_FREEPLUGINDATA. The name tells it all: free your own plugin data. + +Appendix A: Messages my plugin will handle and your WNDPROC will never see. +WM_CREATE, WM_DESTROY, WM_TIMER, WM_ERASEBKGND +WM_CTLCOLOR* [whatever it may be: WM_CTLCOLORDLG, WM_CTLCOLORSTATIC...] +WM_PAINT, WM_PRINT, WM_PRINTCLIENT + +Appendix B: "What do I need to do?!?". +Here is an example in C. + +//Your plugin is in /plugins/myPlugin/ or in miranda32/something/ +#include "../../plugins/PopUp/m_popup.h" + +Define your own plugin data if you need it. In this example, we need it and we'll use NewStatusNotify as example: thsi plugin shows a popup when someone in your contact list changes his/hers status. We'll need to know his status, both current and old one. +typedef struct { + WORD oldStatus; + WORD newStatus; +} MY_PLUGIN_DATA; + +When we need to show the popup, we do: +{ + POPUPDATA ppd; + hContact = A_VALID_HANDLE_YOU_GOT_FROM_SOMEWHERE; + hIcon = A_VALID_HANDLE_YOU_GOT_SOMEWHERE; + char * lpzContactName = (char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)lhContact,0); + //99% of the times you'll just copy this line. + //1% of the times you may wish to change the contact's name. I don't know why you should, but you can. + char * lpzText; + //The text for the second line. You could even make something like: char lpzText[128]; lstrcpy(lpzText, "Hello world!"); It's your choice. + COLORREF colorBack = GetSysColor(COLOR_BTNFACE); //The colour of Miranda's option Pages (and many other windows...) + COLORREF colorText = RGB(255,255,255); //White. + MY_PLUGIN_DATA * mpd = (MY_PLUGIN_DATA*)malloc(sizeof(MY_PLUGIN_DATA)); + + ZeroMemory(ppd, sizeof(ppd)); //This is always a good thing to do. + ppd.lchContact = (HANDLE)hContact; //Be sure to use a GOOD handle, since this will not be checked. + ppd.lchIcon = hIcon; + lstrcpy(ppd.lpzContactName, lpzContactName); + lstrcpy(ppd.lpzText, lpzText); + ppd.colorBack = colorBack; + ppd.colorText = colorText; + ppd.PluginWindowProc = (WNDPROC)PopupDlgProc; + + //Now the "additional" data. + mpd->oldStatus = ID_STATUS_OFFLINE; + mpd->newStatus = ID_STATUS_ONLINE; + + //Now that the plugin data has been filled, we add it to the PopUpData. + ppd.PluginData = mpd; + + //Now that every field has been filled, we want to see the popup. + CallService(MS_POPUP_ADDPOPUP, (WPARAM)&ppd, 0); +} + +Obviously, you have previously declared some: +static int CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) { + case WM_COMMAND: + if ((HIWORD)wParam == STN_CLICKED) { //It was a click on the Popup. + PUDeletePopUp(hWnd); + return TRUE; + } + break; + case UM_FREEPLUGINDATA: { + MY_PLUGIN_DATA * mpd = NULL; + mpd = (MY_PLUGIN_DATA*)CallService(MS_POPUP_GETPLUGINDATA, (WPARAM)hWnd,(LPARAM)mpd); + if (mdp > 0) free(mpd); + return TRUE; //TRUE or FALSE is the same, it gets ignored. + } + default: + break; + } + return DefWindowProc(hWnd, message, wParam, lParam); +} +*/ + +/* +Creates, adds and shows a popup, given a (valid) POPUPDATA structure pointer. +wParam = (WPARAM)(*POPUPDATA)PopUpDataAddress +lParam = 0 +Returns: > 0 on success, 0 if creation went bad, -1 if the PopUpData contained unacceptable values. +NOTE: it returns -1 if the PopUpData was not valid, if there were already too many popups, if the module was disabled. +Otherwise, it can return anything else... +*/ +#define MS_POPUP_ADDPOPUP "PopUp/AddPopUp" +static int __inline PUAddPopUp(POPUPDATA* ppdp) { + return CallService(MS_POPUP_ADDPOPUP, (WPARAM)ppdp,0); +} + +#define MS_POPUP_ADDPOPUPEX "PopUp/AddPopUpEx" +static int __inline PUAddPopUpEx(POPUPDATAEX* ppdp) { + return CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)ppdp,0); +} + +/* +Returns the handle to the contact associated to the specified PopUpWindow. +You will probably need to know this handle inside your WNDPROC. Exampole: you want to open the MessageWindow. :-) +Call MS_POPUP_GETCONTACT on the hWnd you were given in the WNDPROC. +wParam = (WPARAM)(HWND)hPopUpWindow +lParam = 0; +Returns: the HANDLE of the contact. Can return NULL, meaning it's the main contact. -1 means failure. +*/ +#define MS_POPUP_GETCONTACT "PopUp/GetContact" +static HANDLE __inline PUGetContact(HWND hPopUpWindow) { + return (HANDLE)CallService(MS_POPUP_GETCONTACT, (WPARAM)hPopUpWindow,0); +} + +/* +wParam = (WPARAM)(HWND)hPopUpWindow +lParam = (LPARAM)(PLUGINDATA*)PluginDataAddress; +Returns: the address of the PLUGINDATA structure. Can return NULL, meaning nothing was given. -1 means failure. +IMPORTANT NOTE: it doesn't seem to work if you do: +CallService(..., (LPARAM)aPointerToAStruct); +and then use that struct. +Do this, instead: +aPointerToStruct = CallService(..., (LPARAM)aPointerToAStruct); +and it will work. Just look at the example I've written above (PopUpDlgProc). +*/ +#define MS_POPUP_GETPLUGINDATA "PopUp/GetPluginData" +static void __inline * PUGetPluginData(HWND hPopUpWindow) { + long * uselessPointer = NULL; + return (void*)CallService(MS_POPUP_GETPLUGINDATA,(WPARAM)hPopUpWindow,(LPARAM)uselessPointer); +} + +/* +wParam = 0 +lParam = 0 +Returns: 0 if the user has chosen not to have the second line, 1 if he choose to have the second line. +*/ +#define MS_POPUP_ISSECONDLINESHOWN "PopUp/IsSecondLineShown" +static BOOL __inline PUIsSecondLineShown() { + return (BOOL)CallService(MS_POPUP_ISSECONDLINESHOWN,0,0); +} + +/* +Requests an action or an answer from PopUp module. +wParam = (WPARAM)wpQuery +returns 0 on success, -1 on error, 1 on stupid calls ;-) +*/ +#define PUQS_ENABLEPOPUPS 1 //returns 0 if state was changed, 1 if state wasn't changed +#define PUQS_DISABLEPOPUPS 2 // " " +#define PUQS_GETSTATUS 3 //Returns 1 (TRUE) if popups are enabled, 0 (FALSE) if popups are disabled. + +#define MS_POPUP_QUERY "PopUp/Query" + +/* +UM_FREEPLUGINDATA +wParam = lParam = 0. Process this message if you have allocated your own memory. (i.e.: POPUPDATA.PluginData != NULL) +*/ +#define UM_FREEPLUGINDATA (WM_USER + 0x0200) + +/* +UM_DESTROYPOPUP +wParam = lParam = 0. Send this message when you want to destroy the popup, or use the function below. +*/ +#define UM_DESTROYPOPUP (WM_USER + 0x0201) +static int __inline PUDeletePopUp(HWND hWndPopUp) { + return (int)SendMessage(hWndPopUp, UM_DESTROYPOPUP,0,0); +} + +/* +UM_INITPOPUP +wParam = (WPARAM)(HWND)hPopUpWindow (but this is useless, since I'll directly send it to your hPopUpWindow +lParam = 0. +This message is sent to the PopUp when its creation has been finished, so POPUPDATA (and thus your PluginData) is reachable. +Catch it if you needed to catch WM_CREATE or WM_INITDIALOG, which you'll never ever get in your entire popup-life. +Return value: if you process this message, return 0. If you don't process it, return 0. Do whatever you like ;-) +*/ +#define UM_INITPOPUP (WM_USER + 0x0202) + +/* +wParam = (WPARAM)(HWND)hPopUpWindow +lParam = (LPARAM)(char*)lpzNewText +returns: > 0 for success, -1 for failure, 0 if the failure is due to second line not being shown. (but you could call PUIsSecondLineShown() before changing the text...) +Changes the text displayed in the second line of the popup. +*/ +#define MS_POPUP_CHANGETEXT "PopUp/Changetext" +static int __inline PUChangeText(HWND hWndPopUp, LPCTSTR lpzNewText) { + return (int)CallService(MS_POPUP_CHANGETEXT, (WPARAM)hWndPopUp, (LPARAM)lpzNewText); +} + +/* +wParam = (WPARAM)(HWND)hPopUpWindow +lParam = (LPARAM)(POPUPDATAEX*)newData +Changes the entire popup +*/ +#define MS_POPUP_CHANGE "PopUp/Change" +static int __inline PUChange(HWND hWndPopUp, POPUPDATAEX *newData) { + return (int)CallService(MS_POPUP_CHANGE, (WPARAM)hWndPopUp, (LPARAM)newData); +} + +/* +This is mainly for developers. +Shows a warning message in a PopUp. It's useful if you need a "MessageBox" like function, but you don't want a modal window (which will interfere with a DialogProcedure. MessageBox steals focus and control, this one not. +wParam = (char*) lpzMessage +lParam = 0; +Returns: 0 if the popup was shown, -1 in case of failure. +*/ +#define SM_WARNING 0x01 //Triangle icon. +#define SM_NOTIFY 0x02 //Exclamation mark icon. +#define MS_POPUP_SHOWMESSAGE "PopUp/ShowMessage" + +static int __inline PUShowMessage(char* lpzText, BYTE kind) { + return (int)CallService(MS_POPUP_SHOWMESSAGE, (WPARAM)lpzText,(LPARAM)kind); +} + +/* +Each skinned popup (e.g. with colorBack == POPUP_USE_SKINNED_BG) should have +class set. Then you can choose separate skin for each class (for example, you +can create separate class for your plugin and use it for all ypu popups. User +would became able to choose skin for your popups independently from others) + +You have to register popup class before using it. To do so call "PopUp/AddClass" +with lParam = (LPARAM)(const char *)popUpClassName. + +All class names are translated (via Translate()) before being added to list. You +should use english names for them. + +There are three predefined classes and one for backward compatability. + +Note that you can add clases after popup wal loaded, e.g. you shoul intercept +ME_SYSTEM_MODULESLOADED event +*/ +#define MS_POPUP_ADDCLASS "PopUp/AddClass" +#define POPUP_CLASS_DEFAULT "Default" +#define POPUP_CLASS_WARNING "Warning" +#define POPUP_CLASS_NOTIFY "Notify" +#define POPUP_CLASS_OLDAPI "PopUp 1.0.1.x compatability" // for internal purposes + +static void __inline PUAddClass(const char *lpzClass){ + CallService(MS_POPUP_ADDCLASS, 0, (LPARAM)lpzClass); +} + +#endif diff --git a/yamn/include/m_toptoolbar.h b/yamn/include/m_toptoolbar.h new file mode 100644 index 0000000..5b83100 --- /dev/null +++ b/yamn/include/m_toptoolbar.h @@ -0,0 +1,125 @@ + +#ifndef M_TOPTOOLBAR_H +#define M_TOPTOOLBAR_H + +//button flags +#define TTBBF_DISABLED 1 +#define TTBBF_VISIBLE 2 +#define TTBBF_PUSHED 4 +#define TTBBF_SHOWTOOLTIP 8 +#define TTBBF_DRAWBORDER 16//draw border for bitmap,bitmap must be WxH 16x12 +#define TTBBF_ISSEPARATOR 32 + +//for internal launch buttons +#define TTBBF_ISLBUTTON 64 + +typedef struct { + int cbSize; + HBITMAP hbBitmapUp; + HBITMAP hbBitmapDown; + char *pszServiceUp; + char *pszServiceDown; + DWORD dwFlags; + LPARAM lParamUp; + WPARAM wParamUp; + LPARAM lParamDown; + WPARAM wParamDown; + char *name; + +} TTBButton, * lpTTBButton; + +typedef struct { + int cbSize; + HBITMAP hbBitmapUp; + HBITMAP hbBitmapDown; + char *pszServiceUp; + char *pszServiceDown; + DWORD dwFlags; + LPARAM lParamUp; + WPARAM wParamUp; + LPARAM lParamDown; + WPARAM wParamDown; + char *name; + HICON hIconUp,hIconDn; + char *tooltipUp; + char *tooltipDn; + +} TTBButtonV2, * lpTTBButtonV2; + +//=== EVENTS === +/* +toptoolbar/moduleloaded event +wParam = lParam = 0 +Called when the toolbar services are available + +!!!Warning you may work with TTB services only in this event or later. + +*/ +#define ME_TTB_MODULELOADED "TopToolBar/ModuleLoaded" + + + +//=== SERVICES === +/* +toptoolbar/addbutton service +wparam = (TTBButton*)lpTTBButton +lparam = 0 +returns: hTTBButton - handle of added button on success, -1 on failure. +*/ +#define MS_TTB_ADDBUTTON "TopToolBar/AddButton" + +/* +toptoolbar/removebutton service +wparam = (HANDLE)hTTButton +lparam = 0 +returns: 0 on success, -1 on failure. +*/ +#define MS_TTB_REMOVEBUTTON "TopToolBar/RemoveButton" + +/* +toptoolbar/setstate service +wparam = (HANDLE)hTTButton +lparam = (LPARAM) state +returns: 0 on success, -1 on failure. +*/ +#define TTBST_PUSHED 1 +#define TTBST_RELEASED 2 + +#define MS_TTB_SETBUTTONSTATE "TopToolBar/SetState" + +/* +toptoolbar/getstate service +wparam = (HANDLE)hTTButton +lparam = 0 +returns: state on success, -1 on failure. +*/ +#define MS_TTB_GETBUTTONSTATE "TopToolBar/GetState" + +/* +toptoolbar/getoptions service +(HIWORD)wparam = (HANDLE)hTTButton +(LOWORD)wparam = TTBO_FLAG +lparam = 0,or lparam=lpTTBButton if flag=TTBO_ALLDATA +returns: value on success, -1 on failure. +*/ +#define TTBO_FLAGS 0 //get/set all flags +#define TTBO_POS 1 //position +#define TTBO_WIDTH 2 //not impemented +#define TTBO_HEIGHT 3 //not impemented +#define TTBO_TIPNAME 4 //tool tip name +#define TTBO_ALLDATA 5 //change all data via lparam=lpTTBButton + + +#define MS_TTB_GETBUTTONOPTIONS "TopToolBar/GetOptions" + +/* +toptoolbar/setoptions service +(HIWORD)wparam = (HANDLE)hTTButton +(LOWORD)wparam = TTBO_FLAG +lparam = value +returns: 1 on success, -1 on failure. +*/ +#define MS_TTB_SETBUTTONOPTIONS "TopToolBar/SetOptions" + + +#endif diff --git a/yamn/include/m_uninstaller.h b/yamn/include/m_uninstaller.h new file mode 100644 index 0000000..e26f55c --- /dev/null +++ b/yamn/include/m_uninstaller.h @@ -0,0 +1,700 @@ +/* + + PluginUninstaller 1.1.2.1 for Miranda IM 0.3.3a and + + ------------------------------------------------------------------------ + Developers - C/C++ Header File + + Plugin Info: ---------------------------- + | Version: 1.1.2.1 + | Filename: uninstaller.dll + | Author: H. Herkenrath (hrathh@users.sourceforge.net) + | Description: Extends the plugin options and offers the possibility + | to directly remove plugins and delete all associated + | settings and files. + + Contents: ------------------------------- + | > General Info: + | - Uninstall Example/Template + | - Changing displayed icon + | - Changing displayed docs + | - Message boxes on uninstall + | - Service Accesibility + | - Including this file + | + | > Structs: + | - Uninstall Params (PLUGINUNINSTALLPARAMS) + | + | > Helpers: + | - Macro: Run service while uninstalling (PUICallService) + | - Function: Remove some files in directory (PUIRemoveFilesInDirectory) + | + | > Events: + | - Allow to uninstall a plugin (ME_PLUGINUNINSTALLER_OKTOUNINSTALL) + | - Plugin gets uninstalled (ME_PLUGINUNINSTALLER_UNINSTALL) + | + | > Services: + | - Remove database module (MS_PLUGINUNINSTALLER_REMOVEDBMODULE) + | - Remove a setting globally (MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY) + | - Remove skinned sound (MS_PLUGINUNINSTALLER_REMOVESKINSOUND) + | - Uninstall a plugin (MS_PLUGINUNISTALLER_UNISTALLPLUGIN) + | - Getting handles (MS_PLUGINUNINSTALLER_GETHANDLE) + | + + + This file is only thought for plugin developers. + If you only want to use "PluginUninstaller" and don't want to develop a plugin + or something with it you don't need this file. + + If there are any problems or bugs with or in this file or something else + please mail me. My e-mail address is: hrathh@users.sourceforge.net + For more documentation you can use this address, too. :-) + + If you have any whishes on some plugin uninstalling for your + plugin you can mail me, too. :-) + +*/ +#ifndef M_UNINSTALLER_H +#define M_UNINSTALLER_H + +#ifndef CallService + #pragma message("Mistake Alert!: "m_uninstaller.h" needs to be included after "newpluginapi.h"!\n The following errors are resulting of this mistake.\n") +#endif + + +// | General Info +// ----------------------------- + +// Uninstall Example/Template +// --------------------------- +// Making your plugin uninstallable is very easy. +// Just add the following "Uninstall" function near the "Unload" function +// in your plugin. +// A template plugin is available in the source code package. + +// Old: +// int __declspec(dllexport) Uninstall(BOOL bIsMirandaRunning, BOOL bDoDeleteSettings, char* pszPluginPath); + +// New: +//int __declspec(dllexport) UninstallEx(PLUGINUNINSTALLPARAMS* ppup) +//{ + // Available Variables: + // ----------------------------- + // ppup->bIsMirandaRunning: + // Contains if Miranda is running + // (Currently this is always TRUE). + + // ppup->bDoDeleteSettings: + // Contains if the users selected + // that he wants all settings be deleted. + + // ppup->pszPluginsPath: + // Contains the plugins directory name. + + + // Notes: + // ----------------------------- + + // Run before "Unload" function: + // -> IMPORTANT: Be careful not to write to the database or to files in "Unload" again!!! + // -> Perhaps create a global BOOL variable which is set to TRUE when your plugin gets uninstalled + // or check of a database setting "IsInstalled" in Unload() or sth. like that + + // All Miranda is still loaded + + // Here you can do: + // - Delete settings group in database + // - Delete registry items + // - Delete ini-files and other settings files + // - Delete other files + + // Your plugin dll gets automatically deleted + + // Services to remove are offered: + // MS_PLUGINUNINSTALLER_REMOVEDBMODULE + // MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY + // MS_PLUGINUNINSTALLER_REMOVESKINSOUND + + + // Getting other useful paths: + // ----------------------------- + + // System directory: + + //char szSysPath[MAX_PATH]; + //GetSystemDirectory(szSysPath, MAX_PATH); + + + // Windows directory: + + //char szWinPath[MAX_PATH]; + //GetWindowsDirectory(szWinPath, MAX_PATH); + + + // Other directories: + + // char szPath[MAX_PATH]; + // SHGetSpecialFolderPath(NULL, szPath, CSIDL_* , FALSE); + + // Some available dirs: + // CSIDL_APPDATA CSIDL_SENDTO CSIDL_FAVORITES + // CSIDL_STARTUP CSIDL_PROFILE CSIDL_DESKTOPDIRECTORY + + + // Delete Files + //const char* apszFiles[] = {"MyPlugin_Readme.txt", "MyPlugin_License.txt", "MyPlugin_Developer.txt", "MyPlugin_Translation.txt"}; + //PUIRemoveFilesInPath(ppup->pszPluginsPath, apszFiles); + + // Delete Settings + //if(ppup->bDoDeleteSettings == TRUE) + //{ + //if (ppup->bIsMirandaRunning == TRUE) // Check if it is possible to access services + //{ + // Remove plugin's module + //PUIRemoveDbModule("MyPlugin"); + + // Remove plugin's sounds + //PUIRemoveSkinSound("MySoundSetting1"); + //PUIRemoveSkinSound("MySoundSetting2"); + //} + //} + + // Remember: + // Do not forget to remove your (eventually) created registry items here, too. + + + // The plugin's dll file gets deleted after returning. + + // Remember: + // If your DLL file is additionally in use by another application (eg. Windows) + // you need to free the DLL *here* completely. Otherwise it can't be deleted. + +// return 0; +//} + + + +// Changing displayed icon +// --------------------------- +// The icon that gets displayed on the options page is always the "first" +// icon in your DLL file. +// An icon in your DLL file is the first icon when it has the lowest recource ID. +// If you would like to have an other icon shown in the options please change your +// icon resource IDs so that the icon you would like to have has the lowest one. +// For example if you use MS Visual C++, open "resource.h" and change the resource define +// of your prefered icon to the lowest icon number. + + +// Changing displayed docs +// --------------------------- +// The items "License" and "More Information" on the plugin details page +// are created when the a license and/or a readme file for the plugin exists. +// The files get detected automatically and need a special name +// so that they get detected. +// The text files need to be either placed in the "Plugins" directory or +// in the "Docs" directory. Whereof the last one is the better one :-) +// +// For the license file the following file name formatings are possible: +// PluginName-License.txt (I personally think that this is the best naming solution... :-) ) +// PluginName_License.txt, +// +// For the readme file the following ones are possible: +// PluginName-Readme.txt (Again...I like this one :-D ), +// PluginName_Readme.txt, + +// Message boxes on uninstall +// --------------------------- +// If you would like to ask the user for something to remove/uninstall +// please hook the event ME_PLUGINUNINSTALLER_UNINSTALL and show your +// message box there. Save the action the user chose in a +// global BOOL variable and do the chosen action in "UninstallEx". +// You can get the plugins options window handle with MS_PLUGINUNINSTALLER_GETHANDLE. + + +// Service Accessibility +// --------------------------- +// Remember that you only can use these functions after the event ME_SYSTEM_MODULESLOADED +// or later because "PluginUninstaller" needs to be loaded first. +// Normally you only use them in your "UninstallEx" function. +// +// IMPORTANT!: +// Please make sure that you always use the macro PUICallService +// in the "UninstallEx" function instead of the CallService function. + + +// Including this file +// --------------------------- +// To use some of the uninstalling functionality you have to include this file +// into your project. +// +// IMPORTANT!: +// Please make sure that you include the file "newpluginapi.h" before this one. +// If this isn't the case there may some compile errors come up. + + // -> Example: + // If your plugin is in the directory "Plugins/MyPlugin/" and + // this include file is in the directory "Plugins/PluginUninstaller" + // you can use the following: + + //#include "../PluginUninstaller/m_uninstaller.h" + + // If your plugin is in an directory that is different to that one just + // change the include path to the one you want. + + + + + +// | Structs +// ----------------------------- + +// --------------------------------------------- +// -- Struct: Uninstall Params ----------------- +// --------------------------------------------- + +// Struct: PLUGINUNINSTALLPARAMS +// (Gets passed to "UninstallEx" function) + +typedef int (*HELPERPROC)(const char*, WPARAM, LPARAM); // Used internally (for pHelperProcAddress) + +typedef struct { + BOOL bIsMirandaRunning; // Is TRUE when Miranda is loaded and services are available (Please use PUICallService instead of CallService) + BOOL bDoDeleteSettings; // Is TRUE when user wants to delete settings (If this is FALSE, please only delete your files) + char* pszPluginsPath; // Contains the plugin directory path + char* pszDocsPath; // Contains the document directory for plugins documentation (Added in version 1.1.1.0) + char* pszIconsPath; // Contains the icon directory for icon dlls (Added in version 1.1.2.0) + HELPERPROC pHelperProcAddress; // Used internally (Contains proc address for PUICallService) +} PLUGINUNINSTALLPARAMS; + + + + + +// | Helper +// ----------------------------- + + +// --------------------------------------------- +// -- Macro: Run service while uninstalling ---- +// --------------------------------------------- + +// Macro: PUICallService + +#define PUICallService(service, wParam, lParam) (ppup->pHelperProcAddress) (service, wParam, lParam); + +// Description: +// ------------- +// This service provides the possibility to call a Miranda +// service in the "UninstallEx" function. +// Important!: Use this macro always instead of "CallService", +// because else a crash occurs when the plugin was decativated +// and gets uninstalled + +// Parameters: +// ------------- +// Same parameters as CallService of Miranda Core. + +// Return Values: +// -------------- +// Return values are the same as the CallService function of Miranda Core. +// Additionaly returns CALLSERVICE_NOTFOUND if Miranda is not loaded +// which means the services are not accessable. + + + // Example: + // ---------------------------------- + + //if ( (bIsMirandaRunning == TRUE) && (bDoDeleteSettings == TRUE) ) + //{ + // Remove plugin's module + //PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)"MyPlugin", 0); + //} + + + + +// --------------------------------------------- +// -- Function: Remove some files in directory - +// --------------------------------------------- + +// Function: PUIRemoveFilesInDirectory + +static BOOL __inline PUIRemoveFilesInDirectory(char* pszPath, const char* apszFiles[]); + +// Description: +// ------------- +// This helper provides the possibility to easily +// remove specified files in a specified directory. + +// Note: The last version of this helper (PUIRemoveFilesInPath) +// did not work correctly. +// Please do now always append a NULL slot to the end of your array. + +// Parameters: +// ------------- +// char* pszPath = Path to the files in array +// const LPCSTR apszFiles[] = NULL-terminated array of files to be deleted. + +// Return Values: +// -------------- +// Returns TRUE if the files could be deleted. +// FALSE if the files could not be deleted or did not exist. + + +static BOOL __inline PUIRemoveFilesInDirectory(char* pszPath, const char* apszFiles[]) +{ + char szFile[MAX_PATH]; + BOOL bReturn = FALSE; + int iFile = 0; + + while (apszFiles[iFile] != NULL) + { + strncpy(szFile, pszPath, sizeof(szFile)); + strncat(szFile, apszFiles[iFile], sizeof(szFile)-strlen(szFile)); + + if ((BOOL)DeleteFile(szFile) == TRUE) bReturn = TRUE; + iFile++; + } + + return bReturn; +} + + // Example: + // ---------------------------------- + + //const char* apszFiles[] = {"File1.txt", "File2.txt", "File3.txt", NULL}; + //PUIRemoveFilesInDirectory(ppup->pszPluginsPath, apszFiles); + + + + +// | Events +// ----------------------------- + + +// --------------------------------------------- +// -- Event: Allow to uninstall a plugin ------- +// --------------------------------------------- + +// Event: ME_PLUGINUNINSTALLER_OKTOUNINSTALL + +#define ME_PLUGINUNINSTALLER_OKTOUNINSTALL "PluginUninstaller/OkToUninstall" + +// Submitted Values: +// ----------------- +// wParam = pszPluginName (String containing the translated plugin name) +// lParam = pszPluginFile (String containing the plugin dll file name in lower case) + +// Return Values: +// ----------------- +// Returning 1 on this event causes the "Remove Plugin" button to be disabled. + + + +// --------------------------------------------- +// -- Event: Plugin gets uninstalled ----------- +// --------------------------------------------- + +// Event: ME_PLUGINUNINSTALLER_UNINSTALL + +#define ME_PLUGINUNINSTALLER_UNINSTALL "PluginUninstaller/Uninstall" + +// Submitted Values: +// ----------------- +// wParam = pszPluginName (String containing the translated plugin name) +// lParam = pszPluginFile (String containing the plugin dll file name in lower case) + +// Return Values: +// ----------------- +// Returning 1 on this event causes the uninstall process to be canceled. + +// Notice: +// Hook this event if you would like to ask the user for something to remove/uninstall +// and show your message box on this event. Save the action the user chose in a +// global BOOL variable and do the chosen action in "UninstallEx". +// You can get the plugins options window handle with MS_PLUGINUNINSTALLER_GETHANDLE. + +// Other plugins can use this event to be noticed that another plugin isn't installed anylonger. + + + + +// | Services +// ----------------------------- + + +// --------------------------------------------- +// -- Service: Remove database module ---------- +// --------------------------------------------- + +// Service: MS_PLUGINUNINSTALLER_REMOVEDBMODULE + +#define MS_PLUGINUNINSTALLER_REMOVEDBMODULE "PluginUninstaller/RemoveDbModule" + +// Description: +// ------------- +// This service provides the possibility to delete all database modules +// associated to your plugin. +// The specified database module will be removed in all contacts +// including the NULL contact. +// Remember to call it always with PUICallService in "UninstallEx" function. + +// Parameters: +// ------------- +// wParam = (char*)pszModule // Pointer to a string containd module name. Can't be NULL +// lParam = (const char*)apszIgnoreSettings // NULL terminated array of strings. Can be 0 if no settings should be ignored. + // See example 3 for more details + +// Return Values: +// -------------- +// Returns 0 on success. +// Nonzero if the module was not present in database. + + +#ifndef UNINSTALLER_NOHELPERS + +// Can only be used in "UninstallEx" function +#define PUIRemoveDbModule(pszModule) PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)pszModule, 0); + +#endif + + + // Example 1: + // ---------------------------------- + + //PUIRemoveDbModule("MyPlugin"); + + + // Example 2: + // ---------------------------------- + + //char szModule[] = "MyModule"; + //PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)szModule, 0); + + + // Example 3: + // ---------------------------------- + + // This deletes all settings in the specified module exept + // the specified settings: "Setting1",..."Setting4" + + // char szModule[] = "MyModule"; + // const char* apszIgnoreSettings[] = {"Setting1", "Setting2", "Setting3", "Setting4", NULL}; + // PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)szModule, (LPARAM)&apszIgnoreSettings); + + + +// --------------------------------------------- +// -- Service: Remove a setting globally ------- +// --------------------------------------------- + +// Service: MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY + +#define MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY "PluginUninstaller/RemoveDbSettingGlobally" + +// Description: +// ------------- +// This service provides the possibility to delete a specific +// setting in database in all contacts including the NULL contact. +// Remember to call it always with PUICallService in "UninstallEx" function. + +// Parameters: +// ------------- +// wParam = (char*)pszModule +// lParam = (char*)pszSetting + +// Return Values: +// -------------- +// Returns 0 on success. +// Nonzero if the setting was not present in database. + + +#ifndef UNINSTALLER_NOHELPERS + +// Can only be used in "UninstallEx" function +#define PUIRemoveDbSettingGlobally(pszModule, pszSetting) PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY, (WPARAM)pszModule, (LPARAM)pszSetting); + + +#endif + + + // Example 1: + // ---------------------------------- + + //PUIRemoveDbSettingGlobally("MyPlugin", "MySetting"); + + + // Example 2: + // ---------------------------------- + + //szModule[] = "MyPlugin"; + //szSetting[] = "MySetting"; + //PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY, (WPARAM)szModule, (LPARAM)szSetting); + + + + + + +// --------------------------------------------- +// -- Service: Remove skinned sound ------------ +// --------------------------------------------- + +// Service: MS_PLUGINUNINSTALLER_REMOVESKINSOUND + +#define MS_PLUGINUNINSTALLER_REMOVESKINSOUND "PluginUninstaller/RemoveSkinSound" + +// Description: +// ------------- +// This service provides the possibility to delete all your sound settings +// associated to your plugin. +// The specified sound will be be removed. +// Remember to call it always with PUICallService in "UninstallEx" function. + +// Parameters: +// ------------- +// wParam = (char*)pszSoundSetting +// lParam = 0 + +// Return Values: +// -------------- +// Returns 0 on success. +// Nonzero if the sound was not present in database. + + +#ifndef UNINSTALLER_NOHELPERS + +// Can only be used in "UninstallEx" function +#define PUIRemoveSkinSound(pszSoundSetting) PUICallService(MS_PLUGINUNINSTALLER_REMOVESKINSOUND, (WPARAM)pszSoundSetting, 0); + +#endif + + + // Example 1: + // ---------------------------------- + + //PUIRemoveSkinSound("MySoundSetting"); + + + // Example 2: + // ---------------------------------- + + //szSoundModule[] = "MySoundSetting"; + //PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)szSoundSetting, 0); + + + + + +// --------------------------------------------- +// -- Service: Uninstall a plugin -------------- +// --------------------------------------------- + +// Service: MS_PLUGINUNINSTALLER_UNINSTALLPLUGIN + +#define MS_PLUGINUNINSTALLER_UNINSTALLPLUGIN "PluginUninstaller/UninstallPlugin" + +// Description: +// ------------- +// This service marks a plugin to be uninstalled at next restart of Miranda IM. +// It uses the default value for "Delete all settings". +// You can use this service for example when you want that your sub-plugin gets +// also removed when your main-plugin is uninstalled. +// Note: This service is not needed for the normal uninstalling functionality. + +// Parameters: +// ------------- +// wParam = (char*)pszPluginName // do not translate this! +// lParam = (char*)pszPluginFile // without path, only file name! + +// Return Values: +// -------------- +// Returns always 0. + + +#ifndef UNINSTALLER_NOHELPERS + +int __inline PUIUninstallPlugin(char* pszPluginName, char* pszPluginFile) +{ + return CallService(MS_PLUGINUNINSTALLER_UNINSTALLPLUGIN, (WPARAM)pszPluginName, (LPARAM)pszPluginFile); +} + +#endif + + + // Example 1: + // ---------------------------------- + + //PUIUninstallPlugin("PluginName", "plugin.dll"); + + + // Example 2: + // ---------------------------------- + + // hInst => Handle of a specific (your?) plugin + // char szPluginName[] = "YourPluginName"; + + //char* pFileName; + //char szPath[MAX_PATH]; + + //GetModuleFileName(hInst, szPath, sizeof(szPath)); + //pFileName = strrchr(szPath, '\\'); + //pFileName = pFileName+1; // Pointer arithmetic + + //CallService(MS_PLUGINUNINSTALLER_UNINSTALLPLUGIN, (WPARAM)szPluginName, (LPARAM)pFileName); + + + + +// --------------------------------------------- +// -- Service: Getting handles ----------------- +// --------------------------------------------- + +// Service: MS_PLUGINUNINSTALLER_GETHANDLE + +#define MS_PLUGINUNINSTALLER_GETHANDLE "PluginUninstaller/GetHandle" + +// Description: +// ------------- +// This service gets a specified window/instance handle. + +// Note: This service must not be used in "UninstallEx" function. +// It is mainly thought for being used in ME_PLUGINUNINSTALLER_UNINSTALL event +// to give out a MessageBox or something like that. + +// Parameters: +// ------------- +// wParam = UINT uHandleType; +// lParam = 0 + +// Possible values for wParam: +#define PUIHT_HINST_PLUGIN_INSTANCE 0 // HINSTANCE of the PluginUninstaller plugin +#define PUIHT_HWND_PLUGIN_OPTIONS 1 // HWND of the plugin options dialog (if it is loaded; else NULL) + +// Return Values: +// -------------- +// Returns the specified handle value. +// If no handle type is specified it returns NULL. +// The handle doesn't need to be destroyed. + + +#ifndef UNINSTALLER_NOHELPERS + +HANDLE __inline PUIGetHandle(UINT uHandleType) +{ + return (HANDLE)CallService(MS_PLUGINUNINSTALLER_GETHANDLE, uHandleType, 0); +} + +#endif + + + // Example + // ---------------------------------- + + //HWND hwndDlg; + //hwndDlg = (HWND)PUIGetHandle(PUIHT_HWND_PLUGIN_OPTIONS); + + + + + +#endif // M_UNINSTALLER_H diff --git a/yamn/include/m_updater.h b/yamn/include/m_updater.h new file mode 100644 index 0000000..e10bcb3 --- /dev/null +++ b/yamn/include/m_updater.h @@ -0,0 +1,156 @@ +#ifndef _M_UPDATER_H +#define _M_UPDATER_H + +#include +#include "../../../include/newpluginapi.h" //CallService,UnHookEvent +#include "../../../include/m_utils.h" //window broadcasting +//#include +//#include + +// NOTES: +// - For langpack updates, include a string of the following format in the langpack text file: +// ";FLID: " +// version must be four numbers seperated by '.', in the range 0-255 inclusive +// - Updater will disable plugins that are downloaded but were not active prior to the update (this is so that, if an archive contains e.g. ansi and +// unicode versions, the correct plugin will be the only one active after the new version is installed)...so if you add a support plugin, you may need +// to install an ini file to make the plugin activate when miranda restarts after the update +// - Updater will replace all dlls that have the same internal shortName as a downloaded update dll (this is so that msn1.dll and msn2.dll, for example, +// will both be updated) - so if you have a unicode and a non-unicode version of a plugin in your archive, you should make the internal names different (which will break automatic +// updates from the file listing if there is only one file listing entry for both versions, unless you use the 'MS_UPDATE_REGISTER' service below) +// - Updater will install all files in the root of the archive into the plugins folder, except for langpack files that contain the FLID string which go into the root folder (same +// folder as miranda32.exe)...all folders in the archive will also be copied to miranda's root folder, and their contents transferred into the new folders. The only exception is a +// special folder called 'root_files' - if there is a folder by that name in the archive, it's contents will also be copied into miranda's root folder - this is intended to be used +// to install additional dlls etc that a plugin may require) + +// if you set Update.szUpdateURL to the following value when registering, as well as setting your beta site and version data, +// Updater will ignore szVersionURL and pbVersionPrefix, and attempt to find the file listing URL's from the backend XML data. +// for this to work, the plugin name in pluginInfo.shortName must match the file listing exactly (except for case) +#define UPDATER_AUTOREGISTER "UpdaterAUTOREGISTER" +// Updater will also use the backend xml data if you provide URL's that reference the miranda file listing for updates (so you can use that method +// if e.g. your plugin shortName does not match the file listing) - it will grab the file listing id from the end of these URLs + +typedef struct Update_tag { + int cbSize; + char *szComponentName; // component name as it will appear in the UI (will be translated before displaying) + + char *szVersionURL; // URL where the current version can be found (NULL to disable) + BYTE *pbVersionPrefix; // bytes occuring in VersionURL before the version, used to locate the version information within the URL data + // (note that this URL could point at a binary file - dunno why, but it could :) + int cpbVersionPrefix; // number of bytes pointed to by pbVersionPrefix + char *szUpdateURL; // URL where dll/zip is located + // set to UPDATER_AUTOREGISTER if you want Updater to find the file listing URLs (ensure plugin shortName matches file listing!) + + char *szBetaVersionURL; // URL where the beta version can be found (NULL to disable betas) + BYTE *pbBetaVersionPrefix; // bytes occuring in VersionURL before the version, used to locate the version information within the URL data + int cpbBetaVersionPrefix; // number of bytes pointed to by pbVersionPrefix + char *szBetaUpdateURL; // URL where dll/zip is located + + BYTE *pbVersion; // bytes of current version, used for comparison with those in VersionURL + int cpbVersion; // number of bytes pointed to by pbVersion + + char *szBetaChangelogURL; // url for displaying changelog for beta versions +} Update; + +// register a comonent with Updater +// +// wparam = 0 +// lparam = (LPARAM)&Update +#define MS_UPDATE_REGISTER "Update/Register" + +// utility functions to create a version string from a DWORD or from pluginInfo +// point buf at a buffer at least 16 chars wide - but note the version string returned may be shorter +// +__inline static char *CreateVersionString(DWORD version, char *buf) { + mir_snprintf(buf, 16, "%d.%d.%d.%d", (version >> 24) & 0xFF, (version >> 16) & 0xFF, (version >> 8) & 0xFF, version & 0xFF); + return buf; +} + +__inline static char *CreateVersionStringPlugin(PLUGININFO *pluginInfo, char *buf) { + return CreateVersionString(pluginInfo->version, buf); +} + +__inline static char *CreateVersionStringPluginEx(PLUGININFOEX *pluginInfo, char *buf) { + return CreateVersionString(pluginInfo->version, buf); +} + + +// register the 'easy' way - use this method if you have no beta URL and the plugin is on the miranda file listing +// NOTE: the plugin version string on the file listing must be the string version of the version in pluginInfo (i.e. 0.0.0.1, +// four numbers between 0 and 255 inclusivem, so no letters, brackets, etc.) +// +// wParam = (int)fileID - this is the file ID from the file listing (i.e. the number at the end of the download link) +// lParam = (PLUGININFO*)&pluginInfo +#define MS_UPDATE_REGISTERFL "Update/RegisterFL" + +// this function can be used to 'unregister' components - useful for plugins that register non-plugin/langpack components and +// may need to change those components on the fly +// lParam = (char *)szComponentName +#define MS_UPDATE_UNREGISTER "Update/Unregister" + +// this event is fired when the startup process is complete, but NOT if a restart is imminent +// it is designed for status managment plugins to use as a trigger for beggining their own startup process +// wParam = lParam = 0 (unused) +// (added in version 0.1.6.0) +#define ME_UPDATE_STARTUPDONE "Update/StartupDone" + +// this service can be used to enable/disable Updater's global status control +// it can be called from the StartupDone event handler +// wParam = (BOOL)enable +// lParam = 0 +// (added in version 0.1.6.0) +#define MS_UPDATE_ENABLESTATUSCONTROL "Update/EnableStatusControl" + +// An description of usage of the above service and event: +// Say you are a status control plugin that normally sets protocol or global statuses in your ModulesLoaded event handler. +// In order to make yourself 'Updater compatible', you would move the status control code from ModulesLoaded to another function, +// say DoStartup. Then, in ModulesLoaded you would check for the existence of the MS_UPDATE_ENABLESTATUSCONTROL service. +// If it does not exist, call DoStartup. If it does exist, hook the ME_UPDATE_STARTUPDONE event and call DoStartup from there. You may +// also wish to call MS_UPDATE_ENABLESTATUSCONTROL with wParam == FALSE at this time, to disable Updater's own status control feature. + +// this service can be used to determine whether updates are possible for a component with the given name +// wParam = 0 +// lParam = (char *)szComponentName +// returns TRUE if updates are supported, FALSE otherwise +#define MS_UPDATE_ISUPDATESUPPORTED "Update/IsUpdateSupported" + +#endif + + +/////////////// Usage Example /////////////// + +#ifdef EXAMPLE_CODE + +// you need to #include "m_updater.h" and HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded) in your Load function... + +int OnModulesLoaded(WPARAM wParam, LPARAM lParam) { + + Update update = {0}; // for c you'd use memset or ZeroMemory... + char szVersion[16]; + + update.cbSize = sizeof(Update); + + update.szComponentName = pluginInfo.shortName; + update.pbVersion = (BYTE *)CreateVersionString(&pluginInfo, szVersion); + update.cpbVersion = strlen((char *)update.pbVersion); + + // these are the three lines that matter - the archive, the page containing the version string, and the text (or data) + // before the version that we use to locate it on the page + // (note that if the update URL and the version URL point to standard file listing entries, the backend xml + // data will be used to check for updates rather than the actual web page - this is not true for beta urls) + update.szUpdateURL = "http://scottellis.com.au:81/test/updater.zip"; + update.szVersionURL = "http://scottellis.com.au:81/test/updater_test.html"; + update.pbVersionPrefix = (BYTE *)"Updater version "; + + update.cpbVersionPrefix = strlen((char *)update.pbVersionPrefix); + + // do the same for the beta versions of the above struct members if you wish to allow beta updates from another URL + + CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update); + + // Alternatively, to register a plugin with e.g. file ID 2254 on the file listing... + // CallService(MS_UPDATE_REGISTERFL, (WPARAM)2254, (LPARAM)&pluginInfo); + + return 0; +} + +#endif diff --git a/yamn/libs/unicows.lib b/yamn/libs/unicows.lib new file mode 100644 index 0000000..9ef8bbd Binary files /dev/null and b/yamn/libs/unicows.lib differ diff --git a/yamn/m_account.h b/yamn/m_account.h new file mode 100644 index 0000000..2baadd2 --- /dev/null +++ b/yamn/m_account.h @@ -0,0 +1,239 @@ +/* + * This file defines all needed parameters for one account. + * Other plugin can use this (so YAMN does not check it and another plugin can inform YAMN about new mail e.g.), + * this can be usefull for plugins like Yahoo or MSN (Hotmail notify) + * + * (c) majvan 2002-2004 + */ + +#ifndef __ACCOUNT_H +#define __ACCOUNT_H + +#include +#include +#include "m_synchro.h" //include synchronizing objects. If you want to write protocol plugin, which works with YAMN accounts, it must use YAMN synchronizing objects + +// +//================================== OTHER DEFINITIONS ======================================== +// + +enum +{ +// Error codes returned from functions (services) working with account book files + EACC_SYSTEM=1, //use GetLastError() to retrieve detailed information about error + EACC_ALLOC, //problem with memory allocation + EACC_FILECOMPATIBILITY, //file is corrupted + EACC_ENDOFFILE, //unexpected end of file occured + EACC_FILEVERSION, //file should be YAMN book format, but newer version that expected + EACC_FILESIZE, //file has wrong size +}; + +enum +{ +// Status of account +// used in messages WM_YAMN_CHANGESTATUS +// used also in function GetStatus and SetStatus + ACC_IDLE=0, //account is IDLE (no work is performed with account) + ACC_FINDING, //DNS lookup for account + ACC_CONNECTING, //connecting in progress + ACC_LOGGING, //logging in progress + ACC_WORKING, //working + ACC_DISCONNECTING, //disconnecting from server +}; + +typedef struct CNotification +{ +//#define YAMN_NOTIFICATIONVERSION is not implemented, use YAMN_ACCOUNTVERSION instead + CNotification(): PopUpB(0), PopUpT(0), PopUpTime(0), App(NULL), AppParam(NULL), Sound(NULL), TrayIcon1(NULL), TrayIcon2(NULL) {} + +#define YAMN_ACC_SND 0x00000001 //Plays sound (1) +#define YAMN_ACC_MSG 0x00000002 //Shows dialog +#define YAMN_ACC_ICO 0x00000004 //Shows system tray icon (1) +#define YAMN_ACC_ICOB 0x00000008 //not used now, enables tray icon flashing (1) +#define YAMN_ACC_APP 0x00000010 //Runs application (1) +#define YAMN_ACC_POP 0x00000020 //Shows popup +#define YAMN_ACC_POPC 0x00000040 //Use custom colors in popup +#define YAMN_ACC_MSGP 0x00000080 //Persistant messgage. This means, when an situation occurs (e.g. new mail) and message is displayed, it is not destroyed when YAMN_ACC_MSG is not set +#define YAMN_ACC_KBN 0x00000100 //Use Keyboard notify +#define YAMN_ACC_CONT 0x00000200 //Use Contact notify +#define YAMN_ACC_CONTNICK 0x00000400 //Use Contact Nick replacement +#define YAMN_ACC_CONTNOEVENT 0x00000800 //Suppress event for this contact +//(1) - usable only in newmail notification + DWORD Flags; + + COLORREF PopUpB; + COLORREF PopUpT; + DWORD PopUpTime; + WCHAR *App; + WCHAR *AppParam; + +//These parameters are not stored in standard YAMN book file and therefore must be set by plugin + char *Sound; + HICON TrayIcon1; + HICON TrayIcon2; +} YAMN_NOTIFICATION,*PYAMN_NOTIFICATION; + +typedef struct CServer +{ + CServer(): Name(NULL),Login(NULL),Passwd(NULL) {} + + TCHAR *Name; + DWORD Port; + + TCHAR *Login; + +// Password encryption definitions +#define STARTCODEPSW 0x50 +#define ADDCODEPSW 0x0 + TCHAR *Passwd; + +} *PSERVER; + +// +//================================== ACCOUNT DEFINITION ================================== +// + +typedef struct CAccount +{ +#define YAMN_ACCOUNTFILEVERSION 2 //version of standard file format (YAMN book file format) +#define YAMN_ACCOUNTVERSION 3 +//If changes are made in this structure, version is changed. +//So then YAMN does not initialzie your structure, if version does not matches. + + BOOL AbleToWork; //This is set to TRUE by default. When it is needed to stop working on this account, YAMN sets this to zero. + + struct CYAMNProtoPlugin *Plugin; //free access, because this member should not be changed. The same as YAMN_PLUGIN structure + + TCHAR *Name; //access only through AccountAccessSO + +// DWORD Abilities; //access only through AccountAccessSO + + PSERVER Server; //access only through AccountAccessSO + + WORD Interval; //access only through AccountAccessSO + +// YAMN account flags (set by user) +#define YAMN_ACC_ENA 0x00000001 //Enables account. If account is disabled, no countdown is performed +#define YAMN_ACC_POPN 0x00000002 //Shows one popup per one new mail or for N mails +#define YAMN_ACC_APOP 0x00000004 //Use APOP authentication +#define YAMN_ACC_SSL23 0x00000008 //Use SSLv2,3 +#define YAMN_ACC_NOTLS 0x00000010 //Don't try StartTLS (STLS) even available +#define YAMN_ACC_BODY 0x00000020 //Always retrieve body of the message + DWORD Flags; //access only through AccountAccessSO + +// YAMN account flags (set by plugin) +#define YAMN_ACC_BROWSE 0x00000001 //Can browse mails. On this account we can run mailbrowser window +#define YAMN_ACC_POPUP 0x00000002 //Popups of new mail belonging to this account can be showed + DWORD AbilityFlags; + +// YAMN account status flags +#define YAMN_ACC_ST0 0x00000001 //Check (countdown) when Offline +#define YAMN_ACC_ST1 0x00000002 //Check (countdown) when Online +#define YAMN_ACC_ST2 0x00000004 //Check (countdown) when Away +#define YAMN_ACC_ST3 0x00000008 //Check (countdown) when N/A +#define YAMN_ACC_ST4 0x00000010 //Check (countdown) when Occupied +#define YAMN_ACC_ST5 0x00000020 //Check (countdown) when DND +#define YAMN_ACC_ST6 0x00000040 //Check (countdown) when Free for chat +#define YAMN_ACC_ST7 0x00000080 //Check (countdown) when Invisible +#define YAMN_ACC_ST8 0x00000100 //Check (countdown) when On the phone +#define YAMN_ACC_ST9 0x00000200 //Check (countdown) when Out to lunch +#define YAMN_ACC_STARTA 0x00010000 //Check on start anyway +#define YAMN_ACC_STARTS 0x00020000 //Check on start regarding to status setting +#define YAMN_ACC_FORCE 0x00040000 //Check when "check new mail" item pressed (it is called forced checking) + DWORD StatusFlags; //access only through AccountAccessSO + +// Plugin flags. Use this DWORD if you want YAMN to store it to YAMN book file. You can set here any value + DWORD PluginFlags; + + YAMN_NOTIFICATION NewMailN; //access only through AccountAccessSO + YAMN_NOTIFICATION NoNewMailN; //access only through AccountAccessSO + YAMN_NOTIFICATION BadConnectN; //access only through AccountAccessSO + + SYSTEMTIME LastChecked; //last check, access only through AccountAccessSO + SYSTEMTIME LastSChecked; //last check (successfull), access only through AccountAccessSO + SYSTEMTIME LastSynchronised; //last synchronisation (successfull), access only through AccountAccessSO + SYSTEMTIME LastMail; //last check when new mail detected, access only through AccountAccessSO + + char Status[255]; //access only through GetStatusFcn() and SetStatusFcn() functions + + DWORD TimeLeft; //access only through AccountAccessSO + + HANDLE Mails; //access only through MessagesAccessSO + +//Account members are mostly the same, but there can be protocol (POP3,IMAP...) special features. +//To use them, only inherit this class and add your own features. +//First idea was to add pointer to void, where plugin can store its own values. +//But this solution is better in my opinion. + +//This is event with counter. Event is signaled when no threads are using account (and will not be using) +//Very usefull for account delete operation + PSCOUNTER UsingThreads; + +//We have to achieve, that only one thread can write to account and more threads can read. +//Writing to account means that we change account parameters +//Reading from account meands we read account parameters +//Use WaitToRead(), ReadDone(), WaitToWrite(), WriteDone() synchronization functions +//For plugins, this is a pointer to void. It does not matter for plugin what is this variable for, +//because plugin works only with synchronization routines. And why is this void * ? It is because +//plugin does not need to include headers for SWMRG structures... + PSWMRG AccountAccessSO; + +//We have to achieve, that only one thread can write to account mails and more threads can read. +//While some thread writes mails, other thread can write to account. This can be small problem, but it never appears in YAMN. +//But you should think about this note if you want to add some features in the future +//Writing to messages means any changes to message queue or message data +//Reading from messages means reading message queue (browsing through all messages) or reading message data +//Use MsgsWaitToRead(),MsgsReadDone(),MsgsWaitToWrite(),MsgsWriteDone() synchronization functions + PSWMRG MessagesAccessSO; + +//For clist contact notification + HANDLE hContact; + BOOL isCounting; + + struct CAccount *Next; +} *HACCOUNT; + +// +//================================== FUNCTIONS DEFINITIONS ======================================== +// + +typedef void (WINAPI *YAMN_SETSTATUSFCN)(HACCOUNT,TCHAR *); +typedef void (WINAPI *YAMN_GETSTATUSFCN)(HACCOUNT,TCHAR *); + +// +//================================== QUICK FUNCTION CALL DEFINITIONS ======================================== +// + +//These are defininitions for YAMN exported functions. Your plugin can use them. +//pYAMNFcn is global variable, it is pointer to your structure containing YAMN functions. +//It is something similar like pluginLink variable in Miranda plugin. If you use +//this name of variable, you have already defined these functions and you can use them. +//It's similar to Miranda's CreateService function. + +//How to use YAMN functions: +//Create a structure containing pointer to functions you want to use in your plugin +//This structure can look something like this: +// +// struct +// { +// YAMN_SETSTATUSFCN SetStatusFcn; +// YAMN_GETSTATUSFCN GetStatusFcn; +// } *pYAMNFcn; +// +//then you have to fill this structure with pointers... +// +// pYAMNFcn->SetStatusFcn=(YAMN_SETSTATUSFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SETSTATUSID,(LPARAM)0); +// pYAMNFcn->GetStatusFcn=(YAMN_GETSTATUSFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_GETSTATUSID,(LPARAM)0); +// +//and in your plugin just simply use e.g.: +// +// SetAccountStatus(ActualAccount,ACC_CONNECTING); //this command set account status to "connecting to server" +// + +#define YAMN_SETSTATUSID "YAMN/SetStatus" +#define YAMN_GETSTATUSID "YAMN/GetStatus" + +#define SetAccountStatus(x,y) pYAMNFcn->SetStatusFcn(x,y) +#define GetAccountStatus(x,y) pYAMNFcn->GetStatusFcn(x,y) + +#endif diff --git a/yamn/m_filterplugin.h b/yamn/m_filterplugin.h new file mode 100644 index 0000000..210cb0c --- /dev/null +++ b/yamn/m_filterplugin.h @@ -0,0 +1,139 @@ +#ifndef __M_FILTERPLUGIN_H +#define __M_FILTERPLUGIN_H + +#include +#include "mails/m_mails.h" //for mail definition + +// +//================================== IMPORTED FUNCTIONS ================================== +// + +#ifndef YAMN_STANDARDFCN +typedef DWORD (WINAPI *YAMN_STANDARDFCN)(LPVOID); +#endif +typedef DWORD (WINAPI *YAMN_FILTERMAILFCN)(HACCOUNT,DWORD,HYAMNMAIL,DWORD); + +typedef struct CFilterImportFcn +{ +//If changes are made in this structure, version is changed. +//So then YAMN does not initialize your structure, if version does not match. +#define YAMN_FILTERIMPORTFCNVERSION 2 + +//Function is called to get info from mail and mark mail as spam or not... + YAMN_FILTERMAILFCN FilterMailFcnPtr; + +//Function is called when application exits. Plugin should unload + YAMN_STANDARDFCN UnLoadFcn; +} YAMN_FILTERIMPORTFCN, *PYAMN_FILTERIMPORTFCN; + +// +//================================== FILTER PLUGIN REGISTRATION STRUCTURES ================================== +// + +typedef struct CFilterPluginRegistration +{ +#define YAMN_FILTERREGISTRATIONVERSION 2 +//Name of plugin +//this member CANNOT be NULL. Just write here description, i.e. "PopFile filter plugin for YAMN" + char *Name; + +//The version of plugin. CANNOT be NULL. + char *Ver; + +//Plugin copyright +//Write here your copyright if you want (or NULL) + char *Copyright; + +//Plugin description. Can be NULL. + char *Description; + +//Your contact (email). Can be NULL. + char *Email; + +//The web page. Can be NULL. + char *WWW; +} YAMN_FILTERREGISTRATION, *PYAMN_FILTERREGISTRATION; + +typedef struct CYAMNFilterPlugin +{ +//Importance of plugin. Mails are filtered in the way, that filter with smallest importance number +//filters and marks mails first and the filter using the highest number marks mails the last. It means, +//that number with highest number is the most important, because it can set or clear flags as it wants, +//if another plugin set some flag, plugin with higher number can clear it. + DWORD Importance; + +//All needed other info from plugin + PYAMN_FILTERREGISTRATION PluginInfo; + +//Imported functions + PYAMN_FILTERIMPORTFCN FilterFcn; +} YAMN_FILTERPLUGIN, *PYAMN_FILTERPLUGIN, *HYAMNFILTERPLUGIN; + +typedef struct CFilterPluginQueue +{ + HYAMNFILTERPLUGIN Plugin; + struct CFilterPluginQueue *Next; +} YAMN_FILTERPLUGINQUEUE,*PYAMN_FILTERPLUGINQUEUE; + +// +//================================== YAMN SERVICES FOR PROTOCOL PLUGIN ================================== +// + +//RegisterFilterPlugin Service +//Registers filter plugin +//WPARAM- pointer to YAMN_FILTERREGISTRATION structure. Plugin must not delete this structure from memory. +//LPARAM- version of YAMN_FILTERREGISTRATION structure (use YAMN_PROTOREGISTRATIONVERSION definition) +//returns handle to plugin (HYAMNFILTERPLUGIN), if registration failed (plugin not registered) returns NULL +//You need next to call SetFilterPluginFcnImportFcn to have your plugin cooperated with YAMN. +#define MS_YAMN_REGISTERFILTERPLUGIN "YAMN/Service/RegisterFilterPlugin" + +//UnregisterFilterPlugin Service +//Unregisters filter plugin +//WPARAM- (HYAMNFILTERPLUGIN) plugin handle +//LPARAM- any value +//returns nonzero if success +#define MS_YAMN_UNREGISTERFILTERPLUGIN "YAMN/Service/UnregisterFilterPlugin" + +// +//================================== FUNCTIONS DEFINITIONS ======================================== +// + +typedef INT_PTR (WINAPI *YAMN_SETFILTERPLUGINFCNIMPORTFCN)(HYAMNFILTERPLUGIN Plugin,DWORD Importance,PYAMN_FILTERIMPORTFCN YAMNFilterFcn,DWORD YAMNFilterFcnVer); + +// +//================================== QUICK FUNCTION CALL DEFINITIONS ======================================== +// + +//These are defininitions for YAMN exported functions. Your plugin can use them. +//pYAMNFcn is global variable, it is pointer to your structure containing YAMN functions. +//It is something similar like pluginLink variable in Miranda plugin. If you use +//this name of variable, you have already defined these functions and you can use them. +//It's similar to Miranda's CreateService function. + +//How to use YAMN functions: +//Create a structure containing pointer to functions you want to use in your plugin +//This structure can look something like this: +// +// struct +// { +// YAMN_SETFILTERPLUGINFCNIMPORTFCN SetFilterPluginFcnImportFcn; +// } *pYAMNFcn; +// +//then you have to fill this structure with pointers... If you use Miranda services, you will do it like this +// +// pYAMNFcn->SetFilterPluginFcnImportFcn=(YAMN_SETFILTERPLUGINFCNIMPORTFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SETFILTERPLUGINFCNIMPORTID,(LPARAM)0); +// +//If you do not use Miranda services, call service MS_YAMN_GETFCNPTR directly. The address to the MS_YAMN_GETFCNPTR is sent to you in LoadFilter function: +// +// pYAMNFcn->SetFilterPluginFcnImportFcn=(YAMN_SETFILTERPLUGINFCNIMPORTFCN)YAMN_GetFcnPtr((WPARAM)YAMN_SETFILTERPLUGINFCNIMPORTID,(LPARAM)0); +// +//and in your plugin just simply use e.g.: +// +// SetFilterPluginFcnImport(...); +// + +#define YAMN_SETFILTERPLUGINFCNIMPORTID "YAMN/SetFilterPluginFcnImport" + +#define SetFilterPluginFcnImport(a,b,c,d) pYAMNFcn->SetFilterPluginFcnImportFcn(a,b,c,d) + +#endif diff --git a/yamn/m_messages.h b/yamn/m_messages.h new file mode 100644 index 0000000..7fc0fbe --- /dev/null +++ b/yamn/m_messages.h @@ -0,0 +1,41 @@ +#ifndef __MESSAGES_H +#define __MESSAGES_H + +//#include "list.h" + +// structure for chained list of handles (window handles, account handles, whatever) +struct WndHandles +{ + HANDLE Handle; + + struct WndHandles *Next; +}; + +#define WM_YAMN WM_APP+0x2800 //(0xA800 in fact) +enum +{ + WM_YAMN_CHANGEHOTKEY=WM_YAMN, + WM_YAMN_CHANGETIME, + +//ChangeStatus message +//WPARAM- (HACCOUNT) Account whose status is changed +//LPARAM- new status of account + WM_YAMN_CHANGESTATUS, + +//StopAccount message +//WPARAM- (HACCOUNT) Account, which should stop its work and finish immidiatelly + WM_YAMN_STOPACCOUNT, + +//Account content changed + WM_YAMN_CHANGECONTENT, + + WM_YAMN_UPDATEMAILS, + + WM_YAMN_NOTIFYICON, + + WM_YAMN_CHANGESTATUSOPTION, + + WM_YAMN_SHOWSELECTED, +}; + +#endif diff --git a/yamn/m_protoplugin.h b/yamn/m_protoplugin.h new file mode 100644 index 0000000..4407dae --- /dev/null +++ b/yamn/m_protoplugin.h @@ -0,0 +1,389 @@ +#ifndef __M_PROTOPLUGIN_H +#define __M_PROTOPLUGIN_H + +#include +#include "m_account.h" //for account import functions +#include "mails/m_mails.h" //for mail import functions + +// +//================================== OTHER DEFINITIONS ======================================== +// + +//structure is used to give parameters to Check, Synchro or Timeout function +struct CheckParam +{ +//Your plugin should use this definition +#define YAMN_CHECKVERSION 2 +//Version of this structure. Please verify your version in your plugin + DWORD Ver; +//Event that new Check thread must set to signal calling thread that "I've copied all parameters from stack" +//IMPORTANT!!!: Although version #defined in your plugin is not the same, your plugin MUST signal this event +//in any way. YAMN is waiting for this event. If you do not signal it, YAMN is blocked. + HANDLE ThreadRunningEV; +//ActualAccount- the only parameter used in Check function and should contain all needed information I think :) + HACCOUNT AccountParam; + +//I thought it, but this is needed, too +#define YAMN_NORMALCHECK 0 +#define YAMN_FORCECHECK 1 + DWORD Flags; + +//YAMN writes here some informations that are needed to pass to mail browser function (or bad connection) + void *BrowserParam; +//Calling thread (protocol plugin) can write here its own parameters. Usefull when protocol calls its own check function. YAMN always sets this parameter to NULL + void *CustomParam; +}; + +//structure is used to give parameters to DeleteMails function +struct DeleteParam +{ +//Your plugin should use this definition +#define YAMN_DELETEVERSION 1 +//Version of this structure. Please verify your version in your plugin + DWORD Ver; +//Event that new Delete thread must set to signal calling thread that it copied all parameters from stack +//IMPORTANT!!!: Although version #defined in your plugin is not the same, your plugin MUST signal this event +//in any way. YAMN is waiting for this event. If you do not signal it, YAMN is blocked. + HANDLE ThreadRunningEV; +//ActualAccount- which account to delete + HACCOUNT AccountParam; +//YAMN writes here some informations that are needed to pass to mail browser function (or bad connection or no new mail) + void *BrowserParam; +//Calling thread can write here its own parameter. Usefull when protocol calls its own delete function. YAMN always sets this parameter to NULL + void *CustomParam; +}; + +// +//================================== IMPORTED FUNCTIONS ================================== +// + +#ifndef YAMN_STANDARDFCN +typedef DWORD (WINAPI *YAMN_STANDARDFCN)(LPVOID); +#endif +typedef struct CYAMNVariables *(WINAPI *YAMN_GETVARIABLESFCN)(DWORD); +typedef HACCOUNT (WINAPI *YAMN_NEWACCOUNTFCN)(struct CYAMNProtoPlugin *,DWORD); +typedef void (WINAPI *YAMN_STOPACCOUNTFCN)(HACCOUNT); +typedef void (WINAPI *YAMN_DELETEACCOUNTFCN)(HACCOUNT); +typedef DWORD (WINAPI *YAMN_WRITEPLUGINOPTS)(HANDLE File,HACCOUNT); +typedef DWORD (WINAPI *YAMN_READPLUGINOPTS)(HACCOUNT,TCHAR **,TCHAR *); +typedef DWORD (WINAPI *YAMN_CHECKFCN)(struct CheckParam *); +typedef DWORD (WINAPI *YAMN_DELETEFCN)(struct DeleteParam *); +typedef WCHAR* (WINAPI *YAMN_GETERRORSTRINGWFCN)(DWORD); +typedef char* (WINAPI *YAMN_GETERRORSTRINGAFCN)(DWORD); +typedef void (WINAPI *YAMN_DELETEERRORSTRINGFCN)(LPVOID); +typedef DWORD (WINAPI *YAMN_WRITEACCOUNTSFCN)(); + +typedef struct CAccountImportFcn +{ +//If changes are made in this structure, version is changed. +//So then YAMN does not initialize your structure, if version does not match. +#define YAMN_PROTOIMPORTFCNVERSION 3 + +//Note: not all of these functions are needed to be implemented in your protocol plugin. Those +//functions, which are not implemented, you have to set to NULL. + +//Function is called to construct protocol defined account +//This is VERY IMPORTANT for YAMN and plugin to cooperate: +//Imagine following situation. YAMN wants to add new account (it is possible e.g. +//when loading accounts from file), so it has to call protocol constructor. +//It calls NewAccount function and plugin creates new account and returns +//its handle (pointer in fact). That means new account is created with plugin features +//(it is created inherited account, not base class). + YAMN_NEWACCOUNTFCN NewAccountFcnPtr; + +//Function is called to delete protocol defined variables to inherited CAccount structure + YAMN_DELETEACCOUNTFCN DeleteAccountFcnPtr; + +//Function is called when user requests not tu run account longer. (E.g. when closing Miranda) + YAMN_STOPACCOUNTFCN StopAccountFcnPtr; + +//Function is called when plugin should write its own info into book file + YAMN_WRITEPLUGINOPTS WritePluginOptsFcnPtr; + +//Function is called when plugin should read its own info from book file + YAMN_READPLUGINOPTS ReadPluginOptsFcnPtr; + +//Function is called to synchronise account (delete old mails and get the new ones) + YAMN_CHECKFCN SynchroFcnPtr; + +//Function is called when timer timed out- it can be the same as SynchroFcnPtr + YAMN_CHECKFCN TimeoutFcnPtr; + +//Function is called when forced checking- it can be the same as SynchroFcnPtr + YAMN_CHECKFCN ForceCheckFcnPtr; + +//Function is called when user wants to delete mails + YAMN_DELETEFCN DeleteMailsFcnPtr; + +//Function is called when YAMN wants to get error description. Note the parameter given in +//this function is in fact the same as your CheckFcnPtr, DeleteMailsFcnPtr etc. returns to YAMN. +//If you want, you may return pointer to some structure, which includes more information about +//error than only one DWORD. And then, you can in your function create Unicode string containing +//all your error code. YAMN copies this string into its own buffer. Your error code and pointer +//can be deleted in DeleteErrorStringFcnPtr, which is called by YAMN + YAMN_GETERRORSTRINGWFCN GetErrorStringWFcnPtr; + +//This is the same as previous one, but plugin returns normal string (not Unicode). YAMN first +//looks, if your plugin has implemented GetErrorStringWFcnPtr. If not, it looks for this function +//So as you (of course) wait, you implemnt only one of these functions or no one of them. + YAMN_GETERRORSTRINGAFCN GetErrorStringAFcnPtr; + +//Deletes error string that was allocated in your GetErrorStringXFcnPtr. Parameter to this fcn is +//Unicode or normal string. Therefore parameter is defined as LPVOID, but your plugin knows if it is +//Unicode or not... +//If NULL, YAMN does nothing with string + YAMN_DELETEERRORSTRINGFCN DeleteErrorStringFcnPtr; + +//Function is called to notify plugin, that it is quite good to store account status (and mails) + YAMN_WRITEACCOUNTSFCN WriteAccountsFcnPtr; + +//Function is called when user wants to view mails +//not used now, in the future + YAMN_STANDARDFCN ViewMailsFcnPtr; + +//Function is called when application exits. Plugin should unload + YAMN_STANDARDFCN UnLoadFcn; +} YAMN_PROTOIMPORTFCN, *PYAMN_PROTOIMPORTFCN; + +typedef HYAMNMAIL (WINAPI *YAMN_NEWMAILFCN)(HACCOUNT,DWORD); +typedef void (WINAPI *YAMN_DELETEMAILFCN)(HYAMNMAIL); +typedef DWORD (WINAPI *YAMN_WRITEMAILOPTS)(HANDLE File,HYAMNMAIL); +typedef DWORD (WINAPI *YAMN_READMAILOPTS)(HYAMNMAIL,TCHAR **,TCHAR *); + +typedef struct CMailImportFcn +{ +//If changes are made in this structure, version is changed. +//So then YAMN does not initialize your structure, if version does not match. +#define YAMN_MAILIMPORTFCNVERSION 1 + +//Note: not all of these functions are needed to be implemented in your protocol plugin. Those +//functions, which are not implemented, you have to set to NULL. + +//Function is called to construct protocol defined account +//This is VERY IMPORTANT for YAMN and plugin to cooperate: +//Imagine following situation. YAMN wants to add new account (it is possible e.g. +//when loading accounts from file), so it has to call protocol constructor. +//It calls NewAccount function and plugin creates new account and returns +//its handle (pointer in fact). That means new account is created with plugin features +//(it is created inherited account, not base class). + YAMN_NEWMAILFCN NewMailFcnPtr; + +//Function is called to delete protocol defined variables to inherited CAccount structure + YAMN_DELETEMAILFCN DeleteMailFcnPtr; + +//Function is called when plugin should write its own info into book file + YAMN_WRITEMAILOPTS WriteMailOptsFcnPtr; + +//Function is called when plugin should read its own info from book file + YAMN_READMAILOPTS ReadMailOptsFcnPtr; +} YAMN_MAILIMPORTFCN, *PYAMN_MAILIMPORTFCN; + +// +//================================== PROTOCOL PLUGIN REGISTRATION STRUCTURES ================================== +// + +typedef struct CProtoPluginRegistration +{ +#define YAMN_PROTOREGISTRATIONVERSION 1 +//Name of plugin +//this member CANNOT be NULL. Just write here description, i.e. "Yahoo Mail 1.2" + char *Name; + +//The version of plugin. CANNOT be NULL. + char *Ver; + +//Plugin copyright +//Write here your copyright if you want (or NULL) + char *Copyright; + +//Plugin description. Can be NULL. + char *Description; + +//Your contact (email). Can be NULL. + char *Email; + +//The web page. Can be NULL. + char *WWW; + +} YAMN_PROTOREGISTRATION, *PYAMN_PROTOREGISTRATION; + +typedef struct CYAMNProtoPlugin +{ +//Pointer to first protocol plugin account + HACCOUNT FirstAccount; + +//We prevent browsing through accounts (chained list) from deleting or adding any account +//If we want to delete or add, we must have "write" access to AccountBrowserSO +//Note that accounts can be changed during AccountBrowser is in "read" mode, because we do not add or delete account. + PSWMRG AccountBrowserSO; + +//All needed other info from plugin + PYAMN_PROTOREGISTRATION PluginInfo; + +//Imported functions + PYAMN_PROTOIMPORTFCN Fcn; + PYAMN_MAILIMPORTFCN MailFcn; +} YAMN_PROTOPLUGIN, *PYAMN_PROTOPLUGIN, *HYAMNPROTOPLUGIN; + +typedef struct CProtoPluginQueue +{ + HYAMNPROTOPLUGIN Plugin; + struct CProtoPluginQueue *Next; +} YAMN_PROTOPLUGINQUEUE,*PYAMN_PROTOPLUGINQUEUE; + +// +//================================== YAMN SERVICES FOR PROTOCOL PLUGIN ================================== +// + +//RegisterProtoPlugin Service +//Your plugin can call this service to "connect to YAMN"- it means, that you +//give some parameters to YAMN and YAMN can then cooperate with your protocol plugins +//WPARAM- pointer to YAMN_PROTOREGISTRATION structure. Plugin must not delete this structure from memory. +//LPARAM- version of YAMN_PROTOREGISTRATION structure (use YAMN_PROTOREGISTRATIONVERSION definition) +//returns handle to plugin (HYAMNPROTOPLUGIN), if registration failed (plugin not registered) returns NULL +//Note, that your plugin should store returned plugin handle, because it will be usefull in next services. +//You need next to call SetProtocolPluginFcnImportFcn to have your plugin cooperated with YAMN. +#define MS_YAMN_REGISTERPROTOPLUGIN "YAMN/Service/RegisterProtocolPlugin" + +//UnregisterProtoPlugin Service +//Removes plugin from YAMN and deltes its structures +//WPARAM- (HYAMNPROTOPLUGIN) handle of protocol plugin +//LPARAM- any value +//returns nonzero if success +#define MS_YAMN_UNREGISTERPROTOPLUGIN "YAMN/Service/UnregisterProtocolPlugin" + +//CreateAccount Service +//Your plugin should call this to create new account for your plugin. +//WPARAM- (HYAMNPLUGIN) Plugin handle +//LPARAM- CAccount version (use YAMN_ACCOUNTVERSION definition) +//returns pointer to (HACCOUNT) or pointer to your structure returned from imported NewAccountFcnPtr, if implemented +#define MS_YAMN_CREATEPLUGINACCOUNT "YAMN/Service/CreateAccount" + +//DeletePluginAccount Service +//Deletes plugin's account from memory. You probably won't use this service, because it deletes only account +//without any synchronization. Use MS_YAMN_DELETEACCOUNT instead. +//WPARAM- (HACCOUNT) to delete +//LPARAM- any value +//returns zero if failed, otherwise returns nonzero +#define MS_YAMN_DELETEPLUGINACCOUNT "YAMN/Service/DeletePluginAccount" + +//FindAccountByName Service +//Searches accounts queue for first account that belongs to plugin +//WPARAM- (HYAMNPLUGIN) Plugin handle +//LPARAM- (TCHAR *)string, name of account to find +//returns found HACCOUNT handle or NULL if not found +#define MS_YAMN_FINDACCOUNTBYNAME "YAMN/Service/FindAccountByName" + +//GetNextFreeAccount Service +//Creates new account for plugin and adds it to plugin account queue. +//Note!!! you have to use AccountBrowserSO in your plugin before and after calling this service, because it is not synchronized +//So the normal way is like this: +// WaitToWriteSO(MyPlugin->AccountBrowserSO); +// CallService(MS_YAMN_GETNEXTFREEACCOUNT,MyPlugin,YAMN_ACCOUNTVERSION); +// WriteDoneSO(MyPlugin->AccountBrowserSO); +// +//WPARAM- (HYAMNPLUGIN) Plugin handle +//LPARAM- CAccount version (use YAMN_ACCOUNTVERSION definition) +//returns new HACCOUNT handle or NULL if not found +#define MS_YAMN_GETNEXTFREEACCOUNT "YAMN/Service/GetNextFreeAccount" + +//DeleteAccount Service +//Deletes account from plugin account queue. It also deletes it, but in background (when needed). +//This deleting is full synchronized and safe. It is recommended for plugins to use this service. +//WPARAM- (HYAMNPLUGIN) Plugin handle +//LPARAM- (HACCOUNT) Account to delete +#define MS_YAMN_DELETEACCOUNT "YAMN/Service/DeleteAccount" + +//ReadAccountsA Service +//Reads standard accounts to file. Standard account means standard YAMN book format. +//WPARAM- (HYAMNPLUGIN) Plugin handle +//LPARAM- (char *)filename string. Put here your own desired filename. +//return value is one of the ones written in "account.h" file +#define MS_YAMN_READACCOUNTSA "YAMN/Service/ReadAccountsA" + +//ReadAccountsW Service +//Same as ReadAccountsA service, but difference is in WPARAM +//WPARAM- (HYAMNPLUGIN) Plugin handle +//LPARAM- (WCHAR *)filename string. Use MS_YAMN_GETFILENAMEW service to retrieve your filename, or +// just put your own desired filename +#define MS_YAMN_READACCOUNTSW "YAMN/Service/ReadAccountsW" + +//WriteAccountsA Service +//Writes standard accounts to file. Standard account means standard YAMN book format. It does not +//store special protocol features. It stores Account settings from CAccount struct and stores MIME mails +//from CMimeMsgQueue. If your Mails pointer does not point to CMimeMsgQueue structure, +//do not use this function. You are then forced to write your own function +//WPARAM- (HYAMNPLUGIN) Plugin handle +//LPARAM- (char *)filename string. Put here your own desired filename. +//return value is one of the ones written in "account.h" file +#define MS_YAMN_WRITEACCOUNTSA "YAMN/Service/WriteAccountsA" + +//WriteAccountsW Service +//Writes standard accounts to file. Standard account means standard YAMN book format. +//WPARAM- (HYAMNPLUGIN) Plugin handle +//LPARAM- (WCHAR *)filename string. Use MS_YAMN_GETFILENAMEW service to retrieve your filename, or +// just put your own desired filename +//return value is one of the ones written in "account.h" file +#define MS_YAMN_WRITEACCOUNTSW "YAMN/Service/WriteAccountsW" + +//GetFileNameA Service +//Function makes original filename, when you add your protocol string +//From "yahoo" makes "yamn-accounts.yahoo.xxxxx.book" filename +//It is good to use this fcn to have similar filenames... +//WPARAM- (char *) plugin string +//LPARAM- any value +//returns NULL when failed, otherwise returns (WCHAR *)string (!!! not char *) to filename!!! +//You can use MS_YAMN_DELETEFILENAME service to release allocated filename from memory +#define MS_YAMN_GETFILENAMEA "YAMN/Service/GetFileNameA" + +//GetFileNameW Service +//Same as GetFileNameA service, but difference is in WPARAM +//WPARAM- (WCHAR *) plugin string +//LPARAM- any value +#define MS_YAMN_GETFILENAMEW "YAMN/Service/GetFileNameW" + +//DeleteFileName Service +//deletes unicode string from memory +//WPARAM- (WCHAR *) pointer to unicode string +//LPARAM- any value +#define MS_YAMN_DELETEFILENAME "YAMN/Service/DeleteFileName" + +// +//================================== FUNCTIONS DEFINITIONS ======================================== +// + +typedef int (WINAPI *YAMN_SETPROTOCOLPLUGINFCNIMPORTFCN)(HYAMNPROTOPLUGIN Plugin,PYAMN_PROTOIMPORTFCN YAMNFcn,DWORD YAMNFcnVer,PYAMN_MAILIMPORTFCN YAMNMailFcn,DWORD YAMNMailFcnVer); + +// +//================================== QUICK FUNCTION CALL DEFINITIONS ======================================== +// + +//These are defininitions for YAMN exported functions. Your plugin can use them. +//pYAMNFcn is global variable, it is pointer to your structure containing YAMN functions. +//It is something similar like pluginLink variable in Miranda plugin. If you use +//this name of variable, you have already defined these functions and you can use them. +//It's similar to Miranda's CreateService function. + +//How to use YAMN functions: +//Create a structure containing pointer to functions you want to use in your plugin +//This structure can look something like this: +// +// struct +// { +// YAMN_SETPROTOCOLPLUGINFCNIMPORTFCN SetProtocolPluginFcnImportFcn; +// } *pYAMNFcn; +// +//then you have to fill this structure with pointers... +// +// pYAMNFcn->SetProtocolPluginFcnImportFcn=(YAMN_SETPROTOCOLPLUGINFCNIMPORTFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SETPROTOCOLPLUGINFCNIMPORTID,(LPARAM)0); +// +//and in your plugin just simply use e.g.: +// +// SetProtocolPluginFcnImport(...); +// + +#define YAMN_SETPROTOCOLPLUGINFCNIMPORTID "YAMN/SetProtocolPluginFcnImport" + +#define SetProtocolPluginFcnImport(a,b,c,d,e) pYAMNFcn->SetProtocolPluginFcnImportFcn(a,b,c,d,e) + +#endif diff --git a/yamn/m_synchro.h b/yamn/m_synchro.h new file mode 100644 index 0000000..ff3e601 --- /dev/null +++ b/yamn/m_synchro.h @@ -0,0 +1,160 @@ +#ifndef __SYNCHRO_H +#define __SYNCHRO_H + +#include + +// +//================================== OTHER DEFINITIONS ======================================== +// + +#define WAIT_FINISH WAIT_OBJECT_0+1 + +// This structure is used to get semaphore-like synchronization: +// Includes incrementing, decrementing DWORD value and if DWORD is zero, sets event +typedef struct SynchronisedCounter +{ +// Stores number value + HANDLE Event; + DWORD Number; + +// These methods are deleted due to external plugins. Use SCGetNumber,SCInc and SCDec instead +// DWORD GetNumber(); +// DWORD Inc(); +// DWORD Dec(); + +// Yes, some code is defined here. But it is not so problematic, because it uses only Win32 API calls and Win32 structures, + SynchronisedCounter(): Number(0) + { + InitializeCriticalSection(&CounterCS); + Event=CreateEvent(NULL,FALSE,TRUE,NULL); + SetEvent(Event); + } + + SynchronisedCounter(HANDLE InitializedEvent): Number(0) + { + InitializeCriticalSection(&CounterCS); + Event=InitializedEvent; + SetEvent(Event); + } + + ~SynchronisedCounter() + { + DeleteCriticalSection(&CounterCS); + CloseHandle(Event); + } + +//private: //it is not private as other functions (not methods) use these members + CRITICAL_SECTION CounterCS; +} SCOUNTER, *PSCOUNTER; + +// The single-writer/multiple-reader guard +// compound synchronization object (SO) +// Notices: Copyright (c) 1995-1997 Jeffrey Richter +// Changes: majvan, only one process implementation, +// hFinishEV event added- signals when we do not want to use this SO anymore +typedef struct SingleWriterMultiReaderGuard +{ +// This event guards access to the other objects +// managed by this data structure and also indicates +// whether any writer threads are writing. + HANDLE hEventNoWriter; + +// This manual-reset event is signaled when +// no reader threads are reading. + HANDLE hEventNoReaders; + +// This value is used simply as a counter. +// (the count is the number of reader threads) + HANDLE hSemNumReaders; + +// The request is for not to enter critical section +// for writing or reading due to going to delete guard + HANDLE hFinishEV; +} SWMRG, *PSWMRG; + +// +//================================== FUNCTIONS DEFINITIONS ======================================== +// + +typedef DWORD (WINAPI *YAMN_WAITTOWRITEFCN)(PSWMRG,PSCOUNTER); +typedef void (WINAPI *YAMN_WRITEDONEFCN)(PSWMRG,PSCOUNTER); +typedef DWORD (WINAPI *YAMN_WAITTOREADFCN)(PSWMRG); +typedef void (WINAPI *YAMN_READDONEFCN)(PSWMRG); +typedef DWORD (WINAPI *YAMN_SCMANAGEFCN)(PSCOUNTER); + +// +//================================== QUICK FUNCTION CALL DEFINITIONS ======================================== +// + +//These are defininitions for YAMN exported functions. Your plugin can use them. +//pYAMNFcn is global variable, it is pointer to your structure containing YAMN functions. +//It is something similar like pluginLink variable in Miranda plugin. If you use +//this name of variable, you have already defined these functions and you can use them. +//It's similar to Miranda's CreateService function. +//These functions are used to synchronize accounts. YAMN could create service for these +//functions and you could call them then e.g. CallService(MS_YAMNWAITTOWRITE,WPARAM,LPARAM), +//but I think this solution is better, because these functions are much used. It is more +//"normal" if you call function for example like: +//WaitToWrite(ActualAccount) than CallService(MS_YAMNWAITTOWRITE,ActualAccount,NULL)) + +//How to use YAMN functions: +//Create a structure containing pointer to functions you want to use in your plugin +//This structure can look something like this: +// +// struct +// { +// YAMN_WAITTOWRITEFCN WaitToWriteFcn; +// YAMN_WRITEDONEFCN WriteDoneFcn; +// } *pYAMNFcn; +// +//then you have to fill this structure with pointers... +//you have to use YAMN service to get pointer, like this (I wrote here all functions you may need, +//you can copy to your sources only those you need): +// +// pYAMNFcn->WaitToWriteFcn=(YAMN_WAITTOWRITEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_WAITTOWRITEID,(LPARAM)0); +// pYAMNFcn->WriteDoneFcn=(YAMN_WRITEDONEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_WRITEDONEID,(LPARAM)0); +// pYAMNFcn->WaitToReadFcn=(YAMN_WAITTOREADFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_WAITTOREADID,(LPARAM)0); +// pYAMNFcn->ReadDoneFcn=(YAMN_READDONEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_READDONEID,(LPARAM)0); +// pYAMNFcn->SCGetNumberFcn=(YAMN_SCMANAGEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SCGETNUMBERID,(LPARAM)0); +// pYAMNFcn->SCIncFcn=(YAMN_SCMANAGEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SCINCID,(LPARAM)0); +// pYAMNFcn->SCDecFcn=(YAMN_SCMANAGEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SCDECID,(LPARAM)0); +// +//and in your plugin just simply use e.g.: +// +// MsgsWriteDone(ActualAccount); //this command leaves write access to account mails +// + +#define YAMN_WAITTOWRITEID "YAMN/WaitToWrite" +#define YAMN_WRITEDONEID "YAMN/WriteDone" +#define YAMN_WAITTOREADID "YAMN/WaitToRead" +#define YAMN_READDONEID "YAMN/ReadDone" +#define YAMN_SCGETNUMBERID "YAMN/SCGetNumber" +#define YAMN_SCINCID "YAMN/SCInc" +#define YAMN_SCDECID "YAMN/SCDec" + +#define WaitToWrite(x) pYAMNFcn->WaitToWriteFcn(x->AccountAccessSO,0) +#define WaitToWriteEx(x,y) pYAMNFcn->WaitToWriteFcn(x->AccountAccessSO,y) +#define WriteDone(x) pYAMNFcn->WriteDoneFcn(x->AccountAccessSO,0) +#define WaitToRead(x) pYAMNFcn->WaitToReadFcn(x->AccountAccessSO) +#define WaitToReadEx(x,y) pYAMNFcn->WaitToReadFcn(x->AccountAccessSO,y) +#define ReadDone(x) pYAMNFcn->ReadDoneFcn(x->AccountAccessSO) + +#define MsgsWaitToWrite(x) pYAMNFcn->WaitToWriteFcn(x->MessagesAccessSO,0) +#define MsgsWaitToWriteEx(x,y) pYAMNFcn->WaitToWriteFcn(x->MessagesAccessSO,y) +#define MsgsWriteDone(x) pYAMNFcn->WriteDoneFcn(x->MessagesAccessSO,0) +#define MsgsWaitToRead(x) pYAMNFcn->WaitToReadFcn(x->MessagesAccessSO) +#define MsgsWaitToReadEx(x) pYAMNFcn->WaitToReadFcn(x->MessagesAccessSO,y) +#define MsgsReadDone(x) pYAMNFcn->ReadDoneFcn(x->MessagesAccessSO) + +#define WaitToWriteSO(x) pYAMNFcn->WaitToWriteFcn(x,0) +#define WaitToWriteSOEx(x,y) pYAMNFcn->WaitToWriteFcn(x,y) +#define WriteDoneSO(x) pYAMNFcn->WriteDoneFcn(x,0) +#define WaitToReadSO(x) pYAMNFcn->WaitToReadFcn(x) +#define WaitToReadSOEx(x,y) pYAMNFcn->WaitToReadFcn(x,y) +#define ReadDoneSO(x) pYAMNFcn->ReadDoneFcn(x) + +#define SCGetNumber(x) pYAMNFcn->SCGetNumberFcn(x) +#define SCInc(x) pYAMNFcn->SCIncFcn(x) +#define SCDec(x) pYAMNFcn->SCDecFcn(x) + +#endif diff --git a/yamn/m_yamn.h b/yamn/m_yamn.h new file mode 100644 index 0000000..035c71f --- /dev/null +++ b/yamn/m_yamn.h @@ -0,0 +1,154 @@ +#ifndef __M_YAMN_H +#define __M_YAMN_H + +#include + +// +//================================== VARIABLES STRUCT ======================================== +// + +#ifndef MIRANDASERVICE +typedef INT_PTR (*MIRANDASERVICE)(WPARAM,LPARAM); +#endif + +typedef struct CYAMNVariables +{ +#define YAMN_VARIABLESVERSION 3 + HINSTANCE hInst; + HANDLE MessageWnds; + HANDLE NewMailAccountWnd; + int Shutdown; +} YAMN_VARIABLES, *PYAMN_VARIABLES; + +// +//================================== EXPORTED FUNCTIONS STRUCT =============================== +// + +struct CExportedFunctions +{ + char* ID; + void *Ptr; +}; + +struct CExportedServices +{ + char* ID; + INT_PTR (* Ptr)(WPARAM,LPARAM); +}; + +// +//================================== YAMN EVENTS ================================== +// + +//UninstallPlugin Event +//Sent when user wants to uninstall YAMN and all its plugins +#define ME_YAMN_UNINSTALLPLUGINS "YAMN/MirandaEvents/UninstallPlugins" + +//NewMail Event +//Notifies you about new mail +//no arguments now (Developers, send mail, which params would you like to have, but note there's problem that +//params are 32b numbers. When it is pointer to some data, these data should persist while every plugin read them and +//after that they can be removed from memory. So it is problem) +#define ME_YAMN_NEWMAIL "YAMN/MirandaEvents/NewMail" + +// +//================================== YAMN SERVICES ================================== +// + +//GetFcnPtr Service +//Your plugin can co-operate with YAMN in 2 ways: with Miranda services and with YAMN exported functions +//Some commands are written in services, some are functions. The advantage of function calling instead of +//service calling is, that your code is more clear and it is faster than service calling (smaller, FASTER, +//easier- it is slogan of Miranda, isn't it ?). Miranda service has only 2 parameters, that can be +//disadvantage too. +//In every way, it is discutable which functions should be exported or if they should be implemented as +//services. And if YAMN should export some functions etc. Functions not used very often are now implemented +//as Miranda services. +// +//This service gets pointer to YAMN function. Then you can use function directly. In m_?????.h files you have +//definitions of some functions, with definitions of structure variable, so you can use functions very +//clearly, just look to header file. +//WPARAM- function ID. It is string representating function you need to get pointer (e.g. YAMN_WRITEWAITID) +//LPARAM- not used now, but set it to 0 +//returns pointer to YAMN function or NULL when functions does not exist +#define MS_YAMN_GETFCNPTR "YAMN/Service/GetFcn" + +//GetVariables Service +//Ask YAMN for pointer to CYAMNVariables structure. +//WPARAM- YAMN_VARIABLESVERSION +//LPARAM- any value +//returns pointer to YAMN_VARIABLES or NULL when version of structure does not match +#define MS_YAMN_GETVARIABLES "YAMN/Service/GetVar" + +//ForceCheck Service +//Check mail on accounts +//WPARAM- not used +//LPARAM- not used +#define MS_YAMN_FORCECHECK "YAMN/Service/ForceCheck" + +//AccountCheck Service +//Check mail on individual account +//WPARAM- HACCOUNT +//LPARAM- BOOL: Show Popup on no new mail +#define MS_YAMN_ACCOUNTCHECK "YAMN/Service/AccountCheck" + +//Contact List Context Menu Click +//wParam=(WPARAM)hContact +//lParam=0 +// +//Event is fired when there is a double click on a CList contact, +//it is upto the caller to check for the protocol & status +//of the HCONTACT, it's not done for you anymore since it didn't make +//sense to store all this information in memory, etc. +#define MS_YAMN_CLISTCONTEXT "YAMN/Service/ClistContactContextMenu" + +//Contact List Context Menu Click for application +//wParam=(WPARAM)hContact +//lParam=0 +// +//Event is fired when there is a double click on a CList contact, +//it is upto the caller to check for the protocol & status +//of the HCONTACT, it's not done for you anymore since it didn't make +//sense to store all this information in memory, etc. +#define MS_YAMN_CLISTCONTEXTAPP "YAMN/Service/ClistContactContextMenuApp" + +//Contact List Double Click +//wParam=(WPARAM)hContact +//lParam=0 +// +//Event is fired when there is a double click on a CList contact, +//it is upto the caller to check for the protocol & status +//of the HCONTACT, it's not done for you anymore since it didn't make +//sense to store all this information in memory, etc. +#define MS_YAMN_CLISTDBLCLICK "YAMN/Service/ClistContactDoubleclicked" + +//FilterMail Service +//Ask YAMN to process mail filtering. YAMN calls filter plugins to mark mail as spam etc... Warning! Leave all +//read or write access to mail as this function waits for write-access to mail! +//WPARAM- (HACCOUNT) account to which mail belongs +//LPARAM- (HYAMNMAIL) mail to filter +#define MS_YAMN_FILTERMAIL "YAMN/Service/FilterMail" + +//MailBrowser Service +//runs mail browser window (or tray icon only or popups only) +//WPARAM- pointer to YAMN_MAILBROWSERPARAM structure, data to mailbrowser. You do not need to fill ThreadRunningEV event member. +//LPARAM- YAMN_MAILBROWSERPARAM structure version param. Use YAMN_MAILBROWSERVERSION definition. +//returns zero if failed, nonzero if succeed +#define MS_YAMN_MAILBROWSER "YAMN/Service/RunMailBrowser" + +//NoNewMail Service +//runs no new mail procedure (shows popups e.g.) +//WPARAM- pointer to YAMN_NONEWMAILPARAM structure, data to no new mail procedure. You do not need to fill ThreadRunningEV event member. +//LPARAM- YAMN_NONEWMAILPARAM structure version param. Use YAMN_NONEWMAILVERSION definition. +//returns zero if failed, nonzero if succeed +#define MS_YAMN_NONEWMAILPROC "YAMN/Service/NoNewMailProc" + +//BadConnection Service +//runs bad connection window +//WPARAM- pointer to YAMN_BADCONNECTIONPARAM structure, data to mailbrowser. You do not need to fill ThreadRunningEV event member. +//LPARAM- YAMN_BADCONNECTIONPARAM structure version param. Use YAMN_BADCONNECTIONVERSION definition. +//returns zero if failed, nonzero if succeed +#define MS_YAMN_BADCONNECTION "YAMN/Service/BadConnection" + +#define MUUID_YAMN_FORCECHECK { 0x7d15e716, 0x6045, 0x40e3, { 0xa2, 0xb5, 0x5f, 0xb, 0xa4, 0x2b, 0xc7, 0x77 } } +#endif diff --git a/yamn/mails/decode.cpp b/yamn/mails/decode.cpp new file mode 100644 index 0000000..15c23e9 --- /dev/null +++ b/yamn/mails/decode.cpp @@ -0,0 +1,558 @@ +/* + * This code implements decoding encoded MIME header in style + * =?iso-8859-2?Q? "User using email in central Europe characters such as =E9" ?= + * + * (c) majvan 2002-2004 + */ +#include "../yamn.h" +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +struct _tcptable CodePageNamesAll[]= +{ + {_T("ANSI"),_T(""),TRUE,CP_ACP}, + {_T("WINDOWS-1"),_T("250"),0,1250}, + {_T("WINDOWS-1"),_T("251"),0,1251}, + {_T("WINDOWS-1"),_T("252"),0,1252}, + {_T("WINDOWS-1"),_T("253"),0,1253}, + {_T("WINDOWS-1"),_T("254"),0,1254}, + {_T("WINDOWS-1"),_T("255"),0,1255}, + {_T("WINDOWS-1"),_T("256"),0,1256}, + {_T("WINDOWS-1"),_T("257"),0,1257}, + {_T("WINDOWS-1"),_T("258"),0,1258}, + {_T("CP1"),_T("250"),0,1250}, + {_T("CP1"),_T("251"),0,1251}, + {_T("CP1"),_T("252"),0,1252}, + {_T("CP1"),_T("253"),0,1253}, + {_T("CP1"),_T("254"),0,1254}, + {_T("CP1"),_T("255"),0,1255}, + {_T("CP1"),_T("256"),0,1256}, + {_T("CP1"),_T("257"),0,1257}, + {_T("CP1"),_T("258"),0,1258}, + {_T("ANSI-1"),_T("250"),0,1250}, + {_T("ANSI-1"),_T("251"),0,1251}, + {_T("ANSI-1"),_T("252"),0,1252}, + {_T("ANSI-1"),_T("253"),0,1253}, + {_T("ANSI-1"),_T("254"),0,1254}, + {_T("ANSI-1"),_T("255"),0,1255}, + {_T("ANSI-1"),_T("256"),0,1256}, + {_T("ANSI-1"),_T("257"),0,1257}, + {_T("ANSI-1"),_T("258"),0,1258}, + {_T("KOI8"),_T("-R"),0,20866}, + {_T("KOI8"),_T(""),0,20866}, + {_T("KOI8"),_T("-U"),0,21866}, + {_T("KOI8"),_T("-RU"),0,21866}, + {_T("US-"),_T("ASCII"),0,20127}, + {_T("CP"),_T("367"),0,20127}, + {_T("ASCII"),_T(""),0,20127}, + {_T("ASCII"),_T("7"),0,20127}, + {_T("ISO-8859"),_T("-1"),0,28591}, + {_T("ISO-8859"),_T("-2"),0,28592}, + {_T("ISO-8859"),_T("-3"),0,28593}, + {_T("ISO-8859"),_T("-4"),0,28594}, + {_T("ISO-8859"),_T("-5"),0,28595}, + {_T("ISO-8859"),_T("-6"),0,28596}, + {_T("ISO-8859"),_T("-7"),0,28597}, + {_T("ISO-8859"),_T("-8"),0,28598}, + {_T("ISO-8859"),_T("-9"),0,28599}, + {_T("ISO-8859"),_T("-15"),0,28605}, + {_T("ISO_8859"),_T("-1"),0,28591}, + {_T("ISO_8859"),_T("-2"),0,28592}, + {_T("ISO_8859"),_T("-3"),0,28593}, + {_T("ISO_8859"),_T("-4"),0,28594}, + {_T("ISO_8859"),_T("-5"),0,28595}, + {_T("ISO_8859"),_T("-6"),0,28596}, + {_T("ISO_8859"),_T("-7"),0,28597}, + {_T("ISO_8859"),_T("-8"),0,28598}, + {_T("ISO_8859"),_T("-9"),0,28599}, + {_T("ISO_8859"),_T("-15"),0,28605}, + {_T("ISO-"),_T("10646-USC2"),0,1200}, + {_T("ISO-2022"),_T("/2-JP"),0,50220}, + {_T("ISO-2022"),_T("-JP"),0,50221}, + {_T("ISO-2022"),_T("/JIS-JP"),0,50222}, + {_T("ISO-2022"),_T("-KR"),0,50225}, + {_T("ISO-2022"),_T("-CH(SP)"),0,50227}, + {_T("ISO-2022"),_T("-CH(TR)"),0,50229}, + {_T("UTF-"),_T("7"),0,65000}, + {_T("UTF-"),_T("8"),0,65001}, + {_T("ARAB-"),_T("TRANSPARENT"),0,710}, + {_T("ASMO-"),_T("TRANSPARENT"),0,720}, + {_T("ASMO-"),_T("449"),0,709}, + {_T("ASMO-"),_T("708"),0,708}, + {_T("BIG5"),_T(""),0,950}, + {_T("EUC-"),_T("CH(SP)"),0,51936}, + {_T("EUC-"),_T("CH(TR)"),0,51950}, + {_T("EUC-"),_T("JP"),0,51932}, + {_T("EUC-"),_T("KR"),0,51949}, + {_T("GB-"),_T("2312"),0,20936}, + {_T("GB"),_T("2312"),0,20936}, + {_T("HZGB-"),_T("2312"),0,52936}, + {_T("IBM-"),_T("037"),0,37}, + {_T("IBM-"),_T("290"),0,290}, + {_T("IBM-"),_T("437"),0,437}, + {_T("IBM-"),_T("500"),0,500}, + {_T("IBM-"),_T("775"),0,775}, + {_T("IBM-"),_T("850"),0,850}, + {_T("IBM-"),_T("852"),0,852}, + {_T("IBM-"),_T("855"),0,855}, + {_T("IBM-"),_T("857"),0,857}, + {_T("IBM-"),_T("860"),0,860}, + {_T("IBM-"),_T("861"),0,861}, + {_T("IBM-"),_T("862"),0,862}, + {_T("IBM-"),_T("863"),0,863}, + {_T("IBM-"),_T("864"),0,864}, + {_T("IBM-"),_T("865"),0,865}, + {_T("IBM-"),_T("866"),0,866}, + {_T("IBM-"),_T("869"),0,869}, + {_T("IBM-"),_T("870"),0,870}, + {_T("IBM-"),_T("875"),0,875}, + {_T("IBM-"),_T("1026"),0,1026}, + {_T("IBM-"),_T("273"),0,20273}, + {_T("IBM-"),_T("277"),0,20277}, + {_T("IBM-"),_T("278"),0,20278}, + {_T("IBM-"),_T("280"),0,20280}, + {_T("IBM-"),_T("284"),0,20284}, + {_T("IBM-"),_T("285"),0,20285}, + {_T("IBM-"),_T("290"),0,20290}, + {_T("IBM-"),_T("297"),0,20297}, + {_T("IBM-"),_T("420"),0,20420}, + {_T("IBM-"),_T("423"),0,20423}, + {_T("IBM-"),_T("871"),0,20871}, + {_T("IBM-"),_T("880"),0,20880}, + {_T("IBM-"),_T("905"),0,20905}, + {_T("IBM-"),_T("THAI"),0,20838}, + {_T("ISCII-"),_T("DEVANAGARI"),0,57002}, + {_T("ISCII-"),_T("BENGALI"),0,57003}, + {_T("ISCII-"),_T("TAMIL"),0,57004}, + {_T("ISCII-"),_T("TELUGU"),0,57005}, + {_T("ISCII-"),_T("ASSAMESE"),0,57006}, + {_T("ISCII-"),_T("ORIYA"),0,57007}, + {_T("ISCII-"),_T("KANNADA"),0,57008}, + {_T("ISCII-"),_T("MALAYALAM"),0,57009}, + {_T("ISCII-"),_T("GUJARATI"),0,57010}, + {_T("ISCII-"),_T("PUNJABI"),0,57011}, + {_T("KOR-"),_T("JOHAB"),0,1361}, + {_T("KSC-"),_T("5601"),0,1361}, + {_T("MAC-"),_T("ROMAN"),0,10000}, + {_T("MAC-"),_T("JP"),0,10001}, + {_T("MAC-"),_T("CH(SP)(BIG5)"),0,10002}, + {_T("MAC-"),_T("KR"),0,10003}, + {_T("MAC-"),_T("AR"),0,10004}, + {_T("MAC-"),_T("HW"),0,10005}, + {_T("MAC-"),_T("GR"),0,10006}, + {_T("MAC-"),_T("CY"),0,10007}, + {_T("MAC-"),_T("CH(SP)(GB2312)"),0,10008}, + {_T("MAC-"),_T("ROMANIA"),0,10010}, + {_T("MAC-"),_T("UA"),0,10017}, + {_T("MAC-"),_T("TH"),0,10021}, + {_T("MAC-"),_T("LAT2"),0,10029}, + {_T("MAC-"),_T("ICE"),0,10079}, + {_T("MAC-"),_T("TR"),0,10081}, + {_T("MAC-"),_T("CR"),0,10082}, +}; + +int CPLENALL = (sizeof(CodePageNamesAll)/sizeof(CodePageNamesAll[0])); +struct _tcptable *CodePageNamesSupp; +int CPLENSUPP = 1; + +//Gets codepage ID from string representing charset such as "iso-8859-1" +// input- the string +// size- max length of input string +int GetCharsetFromString(char *input,size_t size); + +//HexValue to DecValue ('a' to 10) +// HexValue- hexa value ('a') +// DecValue- poiner where to store dec value +// returns 0 if not success +int FromHexa(char HexValue,char *DecValue); + +//Decodes a char from Base64 +// Base64Value- input char in Base64 +// DecValue- pointer where to store the result +// returns 0 if not success +int FromBase64(char Base64Value,char *DecValue); + +//Decodes string in quoted printable +// Src- input string +// Dst- where to store output string +// DstLen- how max long should be output string +// isQ- if is "Q-encoding" modification. should be TRUE in headers +// always returns 1 +int DecodeQuotedPrintable(char *Src,char *Dst,int DstLen, BOOL isQ); + +//Decodes string in base64 +// Src- input string +// Dst- where to store output string +// DstLen- how max long should be output string +// returns 0 if string was not properly decoded +int DecodeBase64(char *Src,char *Dst,int DstLen); + +//Converts string to unicode from string with specified codepage +// stream- input string +// cp- codepage of input string +// out- pointer to new allocated memory that contains unicode string +int ConvertStringToUnicode(char *stream,unsigned int cp,WCHAR **out); + +//Converts string from MIME header to unicode +// stream- input string +// cp- codepage of input string +// storeto- pointer to memory that contains unicode string +// mode- MIME_PLAIN or MIME_MAIL (MIME_MAIL deletes '"' from start and end of string) +void ConvertCodedStringToUnicode(char *stream,WCHAR **storeto,DWORD cp,int mode); + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +int GetCharsetFromString(char *input,size_t size) +//"ISO-8859-1" to ID from table +{ + char *pin=input; + char *pout,*parser; + + if((size<1) || (parser=pout=new char[size+1])==NULL) + return -1; + while((*pin!=0) && (pin-input< (INT_PTR)size)) + { + if ((*pin>='a') && (*pin<='z')) + *parser++=*(pin++)-('a'-'A'); // make it capital + //else if(*pin=='\"') // this is already done in ExtractFromContentType + // *pin++; //skip the quotes if any + else + *parser++=*pin++; + } + + *parser=(char)0; + +#ifdef DEBUG_DECODECODEPAGE + DebugLog(DecodeFile,"%s",pout); +#endif + for(int i=0;i='0' && HexValue<='9') + { + *DecValue=HexValue-'0'; + return 1; + } + if(HexValue>='A' && HexValue<='F') + { + *DecValue=HexValue-'A'+10; + return 1; + } + if(HexValue>='a' && HexValue<='f') + { + *DecValue=HexValue-'a'+10; + return 1; + } + return 0; +} + +int FromBase64(char Base64Value,char *DecValue) +{ + if(Base64Value>='A' && Base64Value<='Z') + { + *DecValue=Base64Value-'A'; + return 1; + } + if(Base64Value>='a' && Base64Value<='z') + { + *DecValue=Base64Value-'a'+26; + return 1; + } + if(Base64Value>='0' && Base64Value<='9') + { + *DecValue=Base64Value-'0'+52; + return 1; + } + if(Base64Value=='+') + { + *DecValue=Base64Value-'+'+62; + return 1; + } + if(Base64Value=='/') + { + *DecValue=Base64Value-'/'+63; + return 1; + } + if(Base64Value=='=') + { + *DecValue=0; + return 1; + } + return 0; +} + +int DecodeQuotedPrintable(char *Src,char *Dst,int DstLen, BOOL isQ) +{ +#ifdef DEBUG_DECODEQUOTED + char *DstTemp=Dst; + DebugLog(DecodeFile,"%s",Src); +#endif + for(int Counter=0;((char)*Src!=0) && DstLen && (Counter++%s",DstTemp); +#endif + return 1; +} + +int DecodeBase64(char *Src,char *Dst,int DstLen) +{ + int Result=0; + char Locator=0,MiniResult[4]; + char *End=Dst+DstLen; + + MiniResult[0]=MiniResult[1]=MiniResult[2]=MiniResult[3]=0; + +#ifdef DEBUG_DECODEBASE64 + char *DstTemp=Dst; + DebugLog(DecodeFile,"\n%s\n\n",Src); +#endif + while(*Src!=0 && DstLen && Dst!=End) + { + if ((*Src==0x0D)||(*Src==0x0A)) { + Src++; + continue; + } + if((!(Result=FromBase64(*Src,MiniResult+Locator)) && (*Src==0)) || Locator++==3) //end_of_str || end_of_4_bytes + { + Locator=0; //next write to the first byte + *Dst++=(char)((MiniResult[0]<<2) | (MiniResult[1]>>4)); + if(Dst==End) goto end; //DstLen exceeded? + *Dst++=(char)((MiniResult[1]<<4) | (MiniResult[2]>>2)); + if(Dst==End) goto end; //someones don't like goto, but not me + *Dst++=(char)((MiniResult[2]<<6) | MiniResult[3]); + if(!Result && (*Src==0)) goto end; //end of string? + MiniResult[0]=MiniResult[1]=MiniResult[2]=MiniResult[3]=0; //zero 4byte buffer for next loop + } + if(!Result) return 0; //unrecognised character occured + Src++; + } +end: + *Dst=0; +#ifdef DEBUG_DECODEBASE64 + DebugLog(DecodeFile,"\n%s\n",DstTemp); +#endif + return 1; +} + + + +int ConvertStringToUnicode(char *stream,unsigned int cp,WCHAR **out) +{ + CPINFO CPInfo; + WCHAR *temp,*src=*out,*dest; + size_t outlen; + int streamlen,Index; + + //codepages, which require to have set 0 in dwFlags parameter when calling MultiByteToWideChar + DWORD CodePagesZeroFlags[]={50220,50221,50222,50225,50227,50229,52936,54936,57002,57003,57004,57005,57006,57007,57008,57009,57010,57011,65000,65001}; + + if((cp!=CP_ACP) && (cp!=CP_OEMCP) && (cp!=CP_MACCP) && (cp!=CP_THREAD_ACP) && (cp!=CP_SYMBOL) && (cp!=CP_UTF7) && (cp!=CP_UTF8) && !GetCPInfo(cp,&CPInfo)) + cp=CP_ACP; +#ifdef DEBUG_DECODECODEPAGE + DebugLog(DecodeFile,"%d",cp); +#endif + + for(Index=0;Index tempstoreLength) break; + start++; + } + } + tempstore[outind] = 0; + *storeto = tempstore; +} diff --git a/yamn/mails/m_decode.h b/yamn/mails/m_decode.h new file mode 100644 index 0000000..e6d2b52 --- /dev/null +++ b/yamn/mails/m_decode.h @@ -0,0 +1,25 @@ +#ifndef __DECODE_H +#define __DECODE_H + +#include "../debug.h" + +#define DOTLINE(s) ((((s)[-2]=='\r') || ((s)[-2]=='\n')) && ((s)[-1]=='.') && (((s)[0]=='\r') || ((s)[0]=='\n') || ((s)[0]=='\0'))) // be careful, it's different to ESR's pop3.c ;-) +#define ENDLINE(s) (((s)[0]=='\r') || ((s)[0]=='\n')) //endline +#define WS(s) (((s)[0]==' ') || ((s)[0]=='\t')) //whitespace +#define ENDLINEWS(s) ((((s)[0]=='\r') || ((s)[0]=='\n')) && (((((s)[1]=='\r') || ((s)[1]=='\n')) && (((s)[2]==' ') || ((s)[2]=='\t'))) || (((s)[1]==' ') || ((s)[1]=='\t')))) //endline+whitespace: enters(CR or LF and their combinations) followed by space or tab +#define EOS(s) ((s)[0]==0) //end of string (stream) + +#define CODES(s) ((s[0]=='=') && (s[1]=='?')) //start of coded string +#define CODEE(s) ((s[0]=='?') && (s[1]=='=')) //end of coded string +#define CODED(s) (s[0]=='?') //code delimiter + +#define MIME_PLAIN 1 +#define MIME_MAIL 2 + +struct cptable +{ + char *name; + unsigned int ID; +}; + +#endif diff --git a/yamn/mails/m_mails.h b/yamn/mails/m_mails.h new file mode 100644 index 0000000..e1826a1 --- /dev/null +++ b/yamn/mails/m_mails.h @@ -0,0 +1,285 @@ +#ifndef __MAILS_H +#define __MAILS_H + +#include +#include +#include "../m_account.h" + +// +//================================== OTHER DEFINITIONS ======================================== +// + +typedef struct CShortNames +{ + char *Value; + char *ValueNick; + struct CShortNames *Next; +} YAMN_MIMESHORTNAMES,*PYAMN_MIMESHORTNAMES; + +typedef struct CNames +{ + WCHAR *Value; + WCHAR *ValueNick; + struct CNames *Next; +} YAMN_MIMENAMES,*PYAMN_MIMENAMES; + +struct CShortHeader +//this header is used in to get non-unicode data from mime header +{ + char *From; + char *FromNick; + char *ReturnPath; + char *ReturnPathNick; + char *Subject; + PYAMN_MIMESHORTNAMES To; + PYAMN_MIMESHORTNAMES Cc; + PYAMN_MIMESHORTNAMES Bcc; + char *Date; + char Priority; + char *Body; + + int CP; + + CShortHeader() {} + ~CShortHeader() {} +}; + +struct CHeader +//this header is used in miranda to store final results of mime reading in Unicode +{ + WCHAR *From; + WCHAR *FromNick; + WCHAR *ReturnPath; + WCHAR *ReturnPathNick; + WCHAR *Subject; + PYAMN_MIMENAMES To; + PYAMN_MIMENAMES Cc; + PYAMN_MIMENAMES Bcc; + WCHAR *Date; + TCHAR Priority; + WCHAR *Body; + + CHeader() {} + ~CHeader() {} +}; + +struct CMimeItem +{ + char *name; + char *value; + struct CMimeItem *Next; + CMimeItem(): name(NULL), value(NULL), Next(NULL){} +}; + +typedef struct CMailData //this is plugin-independent +{ +#define YAMN_MAILDATAVERSION 3 + + DWORD Size; + int CP; + + struct CMimeItem *TranslatedHeader; //MIME items + struct CMimeItem *Additional; //MIME items not read from server (custom, for filter plugins etc.) + char *Body; //Message body + + CMailData(): CP(-1), Size(0), TranslatedHeader(NULL), Body(NULL){} +} MAILDATA,*PMAILDATA; + +typedef struct CMimeMsgQueue +{ +#define YAMN_MAILVERSION 3 + char *ID; //The ID of mail. This ID identifies every mail in the account, so plugin should set it + + DWORD Number; + +#define YAMN_MSG_ANY 0xffffffff //any mail + +//The difference between new and unseen: when new mail is found in account, it becomes unseen and new. But in the next check, if the same mail is found, it is not new. +//However, when user was not near computer, he does not know about this mail- it is unseen. After user accepts, that he saw new mails, it becomes seen. +#define YAMN_MSG_NEW 0x80000000 //this mail is new +#define YAMN_MSG_UNSEEN 0x40000000 //this mail is mailbrowser unseen +#define YAMN_MSG_DISPLAY 0x20000000 //this mail can be displayed in mailbrowser +#define YAMN_MSG_POPUP 0x10000000 //this mail can be displayed in popup and can invoke a popup +#define YAMN_MSG_SYSTRAY 0x08000000 //this mail can invoke systray icon +#define YAMN_MSG_BROWSER 0x04000000 //this mail can run mailbrowser +#define YAMN_MSG_DISPLAYC 0x02000000 //this mail is inserted to browser mail counter system (the "Account - xx new mails, yy total" phrase) +#define YAMN_MSG_POPUPC 0x01000000 //this mail is inserted to popup counter system (the "Account - xx new mails, yy total" phrase) + +#define YAMN_MSG_SOUND 0x00800000 //this mail can "play sound" +#define YAMN_MSG_APP 0x00400000 //this mail can "launch application" +#define YAMN_MSG_NEVENT 0x00100000 //this mail can launch Miranda "new mail" event + +#define YAMN_MSG_VIRTUAL 0x00080000 //this mail is not real- does not exists + +#define YAMN_MSG_FILTERED 0x00040000 //this mail has been filtered + +#define YAMN_MSG_DELETETRASH 0x00020000 //this mail should be moved to the trash bin rather than really deleting from mailbox (this is only switch doing nothing, perhaps usefull for filter plugins) +#define YAMN_MSG_DELETED 0x00010000 //this mail is already deleted from server (also must be set virtual flag) (when doing synchronizations between 2 queues, YAMN then does not touch this mail) +#define YAMN_MSG_MEMDELETE 0x00008000 //this mail will be deleted immidiatelly from memory (and disk) when deleted from server (some opposite of YAMN_MSG_DELETED) +#define YAMN_MSG_USERDELETE 0x00004000 //this mail is about to delete from server (user deletes manually) +#define YAMN_MSG_AUTODELETE 0x00002000 //this mail is about to delete from server (plugin marks it for deleting) +#define YAMN_MSG_DELETEOK 0x00001000 //this mail is confirmed to delete (this flag must be set to delete this mail) + +#define YAMN_MSG_BODYREQUESTED 0x00000800 //user requested (part of) the body. In POP3 it should be (TOP ) +#define YAMN_MSG_BODYRECEIVED 0x00000200 //(part of) the body.received; +#define YAMN_MSG_STAYUNSEEN 0x00000400 //this mail stays unseen while user does not really see it + +#define YAMN_MSG_DELETE (YAMN_MSG_USERDELETE | YAMN_MSG_AUTODELETE) + +#define YAMN_MSG_NORMALNEW (YAMN_MSG_NEW | YAMN_MSG_UNSEEN | YAMN_MSG_BROWSER | YAMN_MSG_DISPLAY | YAMN_MSG_DISPLAYC | YAMN_MSG_POPUP | YAMN_MSG_POPUPC | YAMN_MSG_SYSTRAY | YAMN_MSG_SOUND | YAMN_MSG_APP | YAMN_MSG_NEVENT | YAMN_MSG_MEMDELETE | YAMN_MSG_STAYUNSEEN) + +#define YAMN_MSG_FLAGSSET(maildata,flag) ((maildata & flag)==flag) + +#define YAMN_MSG_SPAML1 1 //spam level 1: notify, show in another color in mail browser +#define YAMN_MSG_SPAML2 2 //spam level 2: do not notify, show in another color in mail browser +#define YAMN_MSG_SPAML3 3 //spam level 3: delete, show in another color in mail browser that it was deleted, you do not need to set YAMN_MSG_AUTODELETE +#define YAMN_MSG_SPAML4 4 //spam level 4: delete, do not show, you do not need to set YAMN_MSG_AUTODELETE +#define YAMN_MSG_SPAMMASK 0x0000000F + +#define YAMN_MSG_SPAML(maildata,level) ((maildata & YAMN_MSG_SPAMMASK)==level) + DWORD Flags; +//Plugins can read mail data, but it can be NULL!!! So plugin should use Load and Save services to load or save data and Unload to release data from memory + PMAILDATA MailData; +//Here YAMN stores its own informations about this mail. Not usefull for plugins... +// void *YAMNData; + HWND MsgWindow; +//plugins can store here its own data + void *PluginData; + + CMimeMsgQueue(): ID(NULL), Number(0), Flags(0), MailData(NULL), MsgWindow(NULL), PluginData(NULL), Next(NULL){} + ~CMimeMsgQueue(){} + + struct CMimeMsgQueue *Next; +} YAMNMAIL,*HYAMNMAIL; + +#define LoadedMailData(x) (x->MailData!=NULL) + +// +//================================== YAMN MAIL SERVICES ================================== +// + +//CreateAccountMail Service +//Your plugin should call this to create new mail for your plugin. +//WPARAM- (HACCOUNT) Account handle +//LPARAM- CMailData version (use YAMN_MAILVERSION definition) +//returns pointer to (HYAMNMAIL) or pointer to your structure returned from imported NewMailFcnPtr, if implemented +#define MS_YAMN_CREATEACCOUNTMAIL "YAMN/Service/CreateMail" +#define CreateAccountMail(x) (HYAMNMAIL)CallService(MS_YAMN_CREATEACCOUNTMAIL,(WPARAM)x,(LPARAM)YAMN_MAILVERSION) + +//DeleteAccountMail Service +//Deletes plugin's mail from memory. You probably won't use this service, because it deletes only account +//without any synchronization. Use MS_YAMN_DELETEACCOUNT instead. Note that deleting mail is something like "this mail is +//not more in the account". +//WPARAM- (HYAMNPROTOPLUGIN) handle of plugin, which is going to delete mail +//LPARAM- (HYAMNMAIL) mail going to delete +//returns zero if failed, otherwise returns nonzero +#define MS_YAMN_DELETEACCOUNTMAIL "YAMN/Service/DeletePluginMail" +#define DeleteAccountMail(x,y) CallService(MS_YAMN_DELETEACCOUNTMAIL,(WPARAM)x,(LPARAM)y) + +//LoadMailData Service +//This service loads mail from standard YAMN storage (now it is 1 file, from which mails are loaded once at startup, but +//in the future it can be Miranda profile file or separate file (1 file per 1 mail). It depends on YAMN implementation... +//Use this function if you want to read or write to MailData member of mail structure. Please use synchronization obejcts +//before calling this service (so you must have read or write access to mails) +//WPARAM- (HYAMNMAIL) mail where to load data +//LPARAM- (DWORD) version of MAILDATA structure (use YAMN_MAILDATAVERSION definition) +//returns pointer to new allocated MailData structure (the same value as MailData member) +#define MS_YAMN_LOADMAILDATA "YAMN/Service/LoadMailData" +#define LoadMailData(x) (PMAILDATA)CallService(MS_YAMN_LOADMAILDATA,(WPARAM)x,(LPARAM)YAMN_MAILDATAVERSION) + +//UnloadMailData Service +//This service frees mail data from memory. It does not care if data were saved or not. So you should save mail before you +//release data from memory. +//WPARAM- (HYAMNMAIL) mail whose data are about to free +//LPARAM- nothing yet +//returns nonzero if success +#define MS_YAMN_UNLOADMAILDATA "YAMN/Service/UnloadMailData" +#define UnloadMailData(x) CallService(MS_YAMN_UNLOADMAILDATA,(WPARAM)x,(LPARAM)0) + +//SaveMailData Service +//This service saves mail to standard YAMN storage (when using now 1 book file, it does nothing, because save is done when +//using MS_YAMN_WRITEACCOUNT service. In the future, mail can be saved to Miranda profile or to separate file...) +//WPARAM- (HYAMNMAIL) mail to save +//LPARAM- (DWORD) version of MAILDATA structure (use YAMN_MAILDATAVERSION definition) +//returns ZERO! if succes +#define MS_YAMN_SAVEMAILDATA "YAMN/Service/SaveMailData" +#define SaveMailData(x) CallService(MS_YAMN_SAVEMAILDATA,(WPARAM)x,(LPARAM)YAMN_MAILDATAVERSION) + +// +//================================== FUNCTIONS DEFINITIONS ======================================== +// + +//typedef void (WINAPI *YAMN_SENDMESSAGEFCN)(UINT,WPARAM,LPARAM); +typedef void (WINAPI *YAMN_SYNCHROMIMEMSGSFCN)(HACCOUNT,HYAMNMAIL *,HYAMNMAIL *,HYAMNMAIL *,HYAMNMAIL *); +typedef void (WINAPI *YAMN_TRANSLATEHEADERFCN)(char *,int,struct CMimeItem **); +typedef void (WINAPI *YAMN_APPENDQUEUEFCN)(HYAMNMAIL,HYAMNMAIL); +typedef void (WINAPI *YAMN_DELETEMIMEQUEUEFCN)(HACCOUNT,HYAMNMAIL); +typedef void (WINAPI *YAMN_DELETEMIMEMESSAGEFCN)(HYAMNMAIL *,HYAMNMAIL,int); +typedef HYAMNMAIL (WINAPI *YAMN_FINDMIMEMESSAGEFCN)(HYAMNMAIL,char *); +typedef HYAMNMAIL (WINAPI *YAMN_CREATENEWDELETEQUEUEFCN)(HYAMNMAIL); +typedef void (WINAPI *YAMN_SETREMOVEQUEUEFLAGSFCN)(HYAMNMAIL,DWORD,DWORD,DWORD,int); + +// +//================================== QUICK FUNCTION CALL DEFINITIONS ======================================== +// + +//These are defininitions for YAMN exported functions. Your plugin can use them. +//pYAMNFcn is global variable, it is pointer to your structure containing YAMN functions. +//It is something similar like pluginLink variable in Miranda plugin. If you use +//this name of variable, you have already defined these functions and you can use them. +//It's similar to Miranda's CreateService function. + +//How to use YAMN functions: +//Create a structure containing pointer to functions you want to use in your plugin +//This structure can look something like this: +// +// struct +// { +// YAMN_SYNCHROMIMEMSGSFCN SynchroMessagesFcn; +// YAMN_APPENDQUEUEFCN AppendQueueFcn; +// } *pYAMNMailFcn; +// +//then you have to fill this structure with pointers... +//you have to use YAMN service to get pointer, like this (I wrote here all functions you may need, +//you can copy to your sources only those you need): +// +// pYAMNMailFcn->SynchroMessagesFcn=(YAMN_SYNCHROMIMEMSGSFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SYNCHROMIMEMSGSID,(LPARAM)0); +// pYAMNMailFcn->TranslateHeaderFcn=(YAMN_TRANSLATEHEADERFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_TRANSLATEHEADERID,(LPARAM)0); +// pYAMNMailFcn->AppendQueueFcn=(YAMN_APPENDQUEUEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_APPENDQUEUEID,(LPARAM)0); +// pYAMNMailFcn->DeleteMessagesToEndFcn=(YAMN_DELETEMIMEQUEUEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_DELETEMIMEQUEUEID,(LPARAM)0); +// pYAMNMailFcn->DeleteMessageFromQueueFcn=(YAMN_DELETEMIMEMESSAGEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_DELETEMIMEMESSAGEID,(LPARAM)0); +// pYAMNMailFcn->FindMessageByIDFcn=(YAMN_FINDMIMEMESSAGEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_FINDMIMEMESSAGEID,(LPARAM)0); +// pYAMNMailFcn->CreateNewDeleteQueueFcn=(YAMN_CREATENEWDELETEQUEUEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_CREATENEWDELETEQUEUEID,(LPARAM)0); +// pYAMNMailFcn->SetRemoveQueueFlagsFcn=(YAMN_SETREMOVEQUEUEFLAGSFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SETREMOVEQUEUEFLAGSID,(LPARAM)0); +// +// +//and in your plugin just simply use e.g.: +// +// DeleteMIMEQueue(MyAccount,OldMessages); //this command deletes all messages in the mail queue OldMessages +// + +#define YAMN_SYNCHROMIMEMSGSID "YAMN/SynchroMessages" +#define YAMN_TRANSLATEHEADERID "YAMN/TranslateHeader" +#define YAMN_APPENDQUEUEID "YAMN/AppendQueue" +#define YAMN_DELETEMIMEQUEUEID "YAMN/DeleteMIMEQueue" +#define YAMN_DELETEMIMEMESSAGEID "YAMN/DeleteMIMEMessage" +#define YAMN_FINDMIMEMESSAGEID "YAMN/FindMIMEMessageByID" +#define YAMN_CREATENEWDELETEQUEUEID "YAMN/CreateNewDeleteQueue" +#define YAMN_SETREMOVEQUEUEFLAGSID "YAMN/SetRemoveQueueFlags" + +#define YAMN_FLAG_REMOVE 0 +#define YAMN_FLAG_SET 1 + + +#define SynchroMessages(a,b,c,d,e) pYAMNMailFcn->SynchroMessagesFcn(a,b,c,d,e) +#define TranslateHeader(a,b,c) pYAMNMailFcn->TranslateHeaderFcn(a,b,c) +#define AppendQueue(x,y) pYAMNMailFcn->AppendQueueFcn(x,y) +#define DeleteMIMEQueue(x,y) pYAMNMailFcn->DeleteMessagesToEndFcn(x,y) +#define DeleteMIMEMessage(x,y) pYAMNMailFcn->DeleteMessageFromQueueFcn(x,y,0) +#define DeleteMIMEMessageEx(x,y,z) pYAMNMailFcn->DeleteMessageFromQueueFcn(x,y,z) +#define FindMIMEMessageByID(x,y) pYAMNMailFcn->FindMessageByIDFcn(x,y) +#define CreateNewDeleteQueue(x) pYAMNMailFcn->CreateNewDeleteQueueFcn(x) +#define SetQueueFlags(a,b,c,d) pYAMNMailFcn->SetRemoveQueueFlagsFcn(a,b,c,d,1) +#define RemoveQueueFlags(a,b,c,d) pYAMNMailFcn->SetRemoveQueueFlagsFcn(a,b,c,d,0) + +#endif diff --git a/yamn/mails/mails.cpp b/yamn/mails/mails.cpp new file mode 100644 index 0000000..b99a9fd --- /dev/null +++ b/yamn/mails/mails.cpp @@ -0,0 +1,499 @@ +/* + * This code implements retrieving info from MIME header + * + * (c) majvan 2002-2004 + */ + +#pragma warning( disable : 4290 ) +#include "../yamn.h" + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +// SMALL INTRO +// Mails are queued in a queue (chained list). Pointer to first mail is pointed from Account structure +// member called Mails. +// Mail queue is ended with NULL- pointered mail (NULL handle) + +//Creates new mail for plugin (calling plugin's constructor, when plugin imported to YAMN) +INT_PTR CreateAccountMailSvc(WPARAM wParam,LPARAM lParam); + +//Deletes mail for plugin (calling plugin's destructor, when plugin imported to YAMN) +INT_PTR DeleteAccountMailSvc(WPARAM wParam,LPARAM lParam); + +//Loads mail data from standard storage to memory +INT_PTR LoadMailDataSvc(WPARAM wParam,LPARAM lParam); + +//Deletes mail data from memory +INT_PTR UnloadMailDataSvc(WPARAM wParam,LPARAM); + +//Saves mail data from memory to standard storage +INT_PTR SaveMailDataSvc(WPARAM wParam,LPARAM lParam); + +//Appends second MIME mail queue to the first one +//Only finds the end of first queue and its Next memember repoints to second one +void WINAPI AppendQueueFcn(HYAMNMAIL first,HYAMNMAIL second); + +//Synchronizes two accounts +//Function finds, if there were some mails deleted from mailbox and deletes (depends on RemovedOld param) them from OldQueue +//Next finds, if there are new mails. Mails that are still on mailbox are deleted (depends on RemovedNew param) from NewQueue +//After this, OldQueue is pointer to mails that are on mailbox, but not new mails +//and NewQueue contains new mails in account +//New accounts can be then appended to account mails queue, but they have set the New flag +// +//Two mails equals if they have the same ID +// +// hPlugin- handle of plugin going to delete mails +// OldQueue- queue of mails that we found on mailbox last time, after function finishes queue contains all mails except new ones +// RemovedOld- queue of mails where to store removed mails from OldQueue, if NULL deletes mails from OldQueue +// NewQueue- queue of mails that we found on mailbox (all mails), after function finishes queue contains only new mails +// RemovedNew- queue of mails where to store removed mails from NewQueue, if NULL deletes mails from NewQueue +//So function works like: +//1. delete (or move to RemovedOld queue if RemovedOld is not NULL) all mails from OldQueue not found in NewQueue +//2. delete (or move to RemovedNew queue if RemovedNew is not NULL) all mails from NewQueue found in OldQueue +void WINAPI SynchroMessagesFcn(HACCOUNT Account,HYAMNMAIL *OldQueue,HYAMNMAIL *RemovedOld,HYAMNMAIL *NewQueue,HYAMNMAIL *RemovedNew); + +//Deletes messages from mail From to the end +// Account- account who owns mails +// From- first mail in queue, which is going to delete +void WINAPI DeleteMessagesToEndFcn(HACCOUNT Account,HYAMNMAIL From); + +//Removes message from queue, does not delete from memory +// From- queue pointer +// Which- mail to delete +// mode- nonzero if you want to decrement numbers in messages that are bigger than the one in Which mail, 0 if not +void WINAPI DeleteMessageFromQueueFcn(HYAMNMAIL *From,HYAMNMAIL Which,int mode); + +//Finds message in queue that has the same ID number +// From- message queue +// ID- pointer to ID +// returns pointer to found message, NULL if not found +HYAMNMAIL WINAPI FindMessageByIDFcn(HYAMNMAIL From,char *ID); + +//Translate header from text to queue of CMimeItem structures +//This means that new queue will contain all info about headers +// stream- pointer to text containing header (can be ended with zero) +// len- length of stream +// head- function fills this pointer to first header item in queue +void WINAPI TranslateHeaderFcn(char *stream,int len,struct CMimeItem **head); + +//Creates new mail queue, copying only these mails, that have set flag for deleting +// From- message queue, whose mail with given flag are duplicated +// returns new mail queue (or NULL when no mail with flag is in From queue) +//Function does not copy the whole mails, it copies only ID string. And ID is copied as string, so +//you can use this fcn only if you have your ID as pointer to char string ended with zero character +HYAMNMAIL WINAPI CreateNewDeleteQueueFcn(HYAMNMAIL From); + +//Sets/removes flags from specific mails +// From- pointer to first message +// FlagsSet- mail must have set these flags... +// FlagsNotSet- ...and must not have set these flags... +// FlagsToSetRemove- ...to set/remove these flags (see mode) +// mode- nonzero to set, else remove +void WINAPI SetRemoveFlagsInQueueFcn(HYAMNMAIL From,DWORD FlagsSet,DWORD FlagsNotSet,DWORD FlagsToSetRemove,int mode); + +struct CExportedFunctions MailExportedFcn[]= +{ + {YAMN_SYNCHROMIMEMSGSID,(void *)SynchroMessagesFcn}, + {YAMN_TRANSLATEHEADERID,(void *)TranslateHeaderFcn}, + {YAMN_APPENDQUEUEID,(void *)AppendQueueFcn}, + {YAMN_DELETEMIMEQUEUEID,(void *)DeleteMessagesToEndFcn}, + {YAMN_DELETEMIMEMESSAGEID,(void *)DeleteMessageFromQueueFcn}, + {YAMN_FINDMIMEMESSAGEID,(void *)FindMessageByIDFcn}, + {YAMN_CREATENEWDELETEQUEUEID,(void *)CreateNewDeleteQueueFcn}, + {YAMN_SETREMOVEQUEUEFLAGSID,(void *)SetRemoveFlagsInQueueFcn}, +}; + +struct CExportedServices MailExportedSvc[]= +{ + {MS_YAMN_CREATEACCOUNTMAIL,CreateAccountMailSvc}, + {MS_YAMN_DELETEACCOUNTMAIL,DeleteAccountMailSvc}, + {MS_YAMN_LOADMAILDATA,LoadMailDataSvc}, + {MS_YAMN_UNLOADMAILDATA,UnloadMailDataSvc}, + {MS_YAMN_SAVEMAILDATA,SaveMailDataSvc}, +}; + + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +INT_PTR CreateAccountMailSvc(WPARAM wParam,LPARAM lParam) +{ + HACCOUNT Account=(HACCOUNT)wParam; + DWORD MailVersion=(DWORD)lParam; + HYAMNMAIL NewMail; + +//test if we are going to initialize members of suitable structure (structures of plugin and YAMN must match) + if(MailVersion!=YAMN_MAILVERSION) + return NULL; + + if(Account->Plugin!=NULL) + { + if(Account->Plugin->MailFcn->NewMailFcnPtr!=NULL) + { +//Let plugin create its own structure, which can be derived from CAccount structure + if(NULL==(NewMail=Account->Plugin->MailFcn->NewMailFcnPtr(Account,YAMN_MAILVERSION))) + return NULL; + } + else + { +//We suggest plugin uses standard CAccount structure, so we create it + if(NULL==(NewMail=new YAMNMAIL)) +//If not created successfully + return NULL; + NewMail->MailData=NULL; + } +//Init every members of structure, used by YAMN + return (INT_PTR)NewMail; + } + return NULL; +} + +INT_PTR DeleteAccountMailSvc(WPARAM wParam,LPARAM lParam) +{ + HYAMNPROTOPLUGIN Plugin=(HYAMNPROTOPLUGIN)wParam; + HYAMNMAIL OldMail=(HYAMNMAIL)lParam; + struct CMimeItem *TH; + + if(Plugin->MailFcn!=NULL){ + if(Plugin->MailFcn->DeleteMailFcnPtr!=NULL) { + //Let plugin delete its own CMimeMsgQueue derived structure + Plugin->MailFcn->DeleteMailFcnPtr(OldMail); + return 1; + } + } + if(OldMail->MailData!=NULL) { + if(OldMail->MailData->Body!=NULL) + delete[] OldMail->MailData->Body; + if((TH=OldMail->MailData->TranslatedHeader)!=NULL) + for(;OldMail->MailData->TranslatedHeader!=NULL;) { + TH=TH->Next; + if(OldMail->MailData->TranslatedHeader->name!=NULL) + delete[] OldMail->MailData->TranslatedHeader->name; + if(OldMail->MailData->TranslatedHeader->value!=NULL) + delete[] OldMail->MailData->TranslatedHeader->value; + delete OldMail->MailData->TranslatedHeader; + OldMail->MailData->TranslatedHeader=TH; + } + delete OldMail->MailData; + } + if(OldMail->ID!=NULL) + delete[] OldMail->ID; + + delete OldMail; //consider mail as standard HYAMNMAIL, not initialized before and use its own destructor + return 1; +} + + +void WINAPI AppendQueueFcn(HYAMNMAIL first,HYAMNMAIL second) +{ + HYAMNMAIL Finder=first; + while(Finder->Next!=NULL) Finder=Finder->Next; + Finder->Next=second; +} + +INT_PTR LoadMailDataSvc(WPARAM wParam,LPARAM lParam) +{ + HYAMNMAIL Mail=(HYAMNMAIL)wParam; + DWORD MailVersion=(DWORD)lParam; + + if(MailVersion!=YAMN_MAILDATAVERSION) + return NULL; + +//now we have all data to memory persisting, so no loading is needed + return (INT_PTR)Mail->MailData; +} + +INT_PTR UnloadMailDataSvc(WPARAM wParam,LPARAM) +{ + HYAMNMAIL Mail=(HYAMNMAIL)wParam; + +//now we should delete structure from memory, but it will be made in future YAMN version + return 1; +} + +INT_PTR SaveMailDataSvc(WPARAM wParam,LPARAM lParam) +{ + HYAMNMAIL Mail=(HYAMNMAIL)wParam; + DWORD MailVersion=(DWORD)lParam; + + if(MailVersion!=YAMN_MAILDATAVERSION) + return (INT_PTR)-1; + +//now we have all data to memory persisting, so no saving is needed + return (INT_PTR)0; +} + +void WINAPI SynchroMessagesFcn(HACCOUNT Account,HYAMNMAIL *OldQueue,HYAMNMAIL *RemovedOld,HYAMNMAIL *NewQueue,HYAMNMAIL *RemovedNew) +//deletes messages from new queue, if they are old +//it also deletes messages from old queue, if they are not in mailbox anymore +//"YAMN_MSG_DELETED" messages in old queue remain in old queue (are never removed, although they are not in new queue) +//"YAMN_MSG_DELETED" messages in new queue remain in new queue (are never removed, although they can be in old queue) +{ + HYAMNMAIL Finder,FinderPrev; + HYAMNMAIL Parser,ParserPrev; + HYAMNMAIL RemovedOldParser =NULL; + HYAMNMAIL RemovedNewParser =NULL; + if(RemovedOld!=NULL) *RemovedOld=NULL; + if(RemovedNew!=NULL) *RemovedNew=NULL; + + for(FinderPrev=NULL,Finder=*OldQueue;Finder!=NULL;) + { + if(Finder->Flags & YAMN_MSG_DELETED) //if old queue contains deleted mail + { + FinderPrev=Finder; + Finder=Finder->Next; //get next message in old queue for testing + continue; + } + for(ParserPrev=NULL,Parser=*NewQueue;Parser!=NULL;ParserPrev=Parser,Parser=Parser->Next) + { + if(Parser->Flags & YAMN_MSG_DELETED) + continue; + + if(Parser->ID==NULL) //simply ignore the message, that has not filled its ID + continue; + + if(0==strcmp(Parser->ID,Finder->ID)) //search for equal message in new queue + break; + } + if(Parser!=NULL) //found equal message in new queue + { + if(Parser==*NewQueue) + *NewQueue=(*NewQueue)->Next; + else + ParserPrev->Next=Parser->Next; + Finder->Number=Parser->Number; //rewrite the number of current message in old queue + + if(RemovedNew==NULL) //delete from new queue + DeleteAccountMailSvc((WPARAM)Account->Plugin,(LPARAM)Parser); + else //or move to RemovedNew + { + if(RemovedNewParser==NULL) //if it is first mail removed from NewQueue + *RemovedNew=Parser; //set RemovedNew queue to point to first message in removed queue + else + RemovedNewParser->Next=Parser; //else don't forget to show to next message in RemovedNew queue + RemovedNewParser=Parser; //follow RemovedNew queue + RemovedNewParser->Next=NULL; + } + FinderPrev=Finder; + Finder=Finder->Next; //get next message in old queue for testing + } + else //a message was already deleted from mailbox + { + if(Finder==*OldQueue) //if we are at the first item in OldQueue + { + *OldQueue=(*OldQueue)->Next; //set OldQueue to next item + if(RemovedOld==NULL) //delete from old queue + DeleteAccountMailSvc((WPARAM)Account->Plugin,(LPARAM)Finder); + else //or move to RemovedOld + { + if(RemovedOldParser==NULL) //if it is first mail removed from OldQueue + *RemovedOld=Finder; //set RemovedOld queue to point to first message in removed queue + else + RemovedOldParser->Next=Finder; //else don't forget to show to next message in RemovedNew queue + RemovedOldParser=Finder; //follow RemovedOld queue + RemovedOldParser->Next=NULL; + } + Finder=*OldQueue; + } + else + { + FinderPrev->Next=Finder->Next; + if(RemovedOld==NULL) //delete from old queue + DeleteAccountMailSvc((WPARAM)Account->Plugin,(LPARAM)Finder); + else //or move to RemovedOld + { + if(RemovedOldParser==NULL) //if it is first mail removed from OldQueue + *RemovedOld=Finder; //set RemovedOld queue to point to first message in removed queue + else + RemovedOldParser->Next=Finder; //else don't forget to show to next message in RemovedNew queue + RemovedOldParser=Finder; //follow RemovedOld queue + RemovedOldParser->Next=NULL; + } + Finder=FinderPrev->Next; + } + } + } +} + +void WINAPI DeleteMessagesToEndFcn(HACCOUNT Account,HYAMNMAIL From) +{ + HYAMNMAIL Temp; + while(From!=NULL) + { + Temp=From; + From=From->Next; + DeleteAccountMailSvc((WPARAM)Account->Plugin,(LPARAM)Temp); + } +} + +void WINAPI DeleteMessageFromQueueFcn(HYAMNMAIL *From,HYAMNMAIL Which,int mode=0) +{ + DWORD Number=Which->Number; + HYAMNMAIL Parser; + + if(*From==Which) + { + Parser=Which->Next; + *From=Parser; + } + else + { + for(Parser=*From;Which!=Parser->Next;Parser=Parser->Next) + if(mode && (Parser->Number>Number)) Parser->Number--; + if(mode && (Parser->Number>Number)) Parser->Number--; + Parser->Next=Parser->Next->Next; + Parser=Which->Next; + } + if(mode) + for(;Parser!=NULL;Parser=Parser->Next) + if(Parser->Number>Number) Parser->Number--; +} + +void DeleteMessagesFromQueue(HYAMNMAIL *From,HYAMNMAIL Which,int mode=0) +{ + HYAMNMAIL Parser; + + for(Parser=Which;Parser!=NULL;Parser=Parser->Next) + DeleteMessageFromQueueFcn(From,Parser,mode); +} + +HYAMNMAIL WINAPI FindMessageByIDFcn(HYAMNMAIL From,char *ID) +{ + HYAMNMAIL Browser; + + for(Browser=From;Browser!=NULL;Browser=Browser->Next) + if(0==lstrcmp(Browser->ID,ID)) + break; + return Browser; +} + +void WINAPI TranslateHeaderFcn(char *stream,int len,struct CMimeItem **head) +{ + try + { + char *finder=stream; + char *prev1,*prev2,*prev3; + struct CMimeItem *Item=NULL; + + while(finder<=(stream+len)) + { + while(ENDLINEWS(finder)) finder++; + + //at the start of line + if(DOTLINE(finder+1)) //at the end of stream + break; + + prev1=finder; + + while(*finder!=':' && !EOS(finder)) finder++; + if(!EOS(finder)) + prev2=finder++; + else + break; + + while(WS(finder) && !EOS(finder)) finder++; + if(!EOS(finder)) + prev3=finder; + else + break; + + do + { + if(ENDLINEWS(finder)) finder+=2; //after endline information continues + while(!ENDLINE(finder) && !EOS(finder)) finder++; + }while(ENDLINEWS(finder)); + + if(Item!=NULL) + { + if(NULL==(Item->Next=new struct CMimeItem)) + break; + Item=Item->Next; + } + else + { + Item = new CMimeItem; + *head = Item; + } + + Item->Next=NULL; + Item->name=new char [prev2-prev1+1]; + lstrcpyn(Item->name,prev1,prev2-prev1+1); + Item->value=new char [finder-prev3+1]; + lstrcpyn(Item->value,prev3,finder-prev3+1); + + if(EOS(finder)) + break; + finder++; + if(ENDLINE(finder)) { + finder++; + if(ENDLINE(finder)) { + // end of headers. message body begins + finder++; + if(ENDLINE(finder))finder++; + prev1 = finder; + while (!DOTLINE(finder+1))finder++; + if (ENDLINE(finder))finder--; + prev2 = finder; + if (prev2>prev1){ // yes, we have body + if(NULL==(Item->Next=new struct CMimeItem)) break; // Cant create new item?! + Item=Item->Next; + Item->Next=NULL;//just in case; + Item->name=new char[5]; strncpy(Item->name,"Body",5); + Item->value=new char [prev2-prev1]; + lstrcpyn(Item->value,prev1,prev2-prev1-1); + } + break; // there is nothing else + } + } + } + } + catch(...) + { + MessageBox(NULL,"Translate header error","",0); + } +} + +HYAMNMAIL WINAPI CreateNewDeleteQueueFcn(HYAMNMAIL From) +{ + HYAMNMAIL FirstMail,Browser; + + for(FirstMail=NULL;From!=NULL;From=From->Next) + { + if((From->Flags & (YAMN_MSG_USERDELETE | YAMN_MSG_AUTODELETE)) && !(From->Flags & YAMN_MSG_DELETED)) + { + if(FirstMail==NULL) + { + FirstMail=Browser=new YAMNMAIL; + if(FirstMail==NULL) + break; + } + else + { + Browser->Next=new YAMNMAIL; + Browser=Browser->Next; + } + Browser->ID=new char[strlen(From->ID)+1]; + strcpy(Browser->ID,From->ID); + Browser->Number=From->Number; + Browser->Flags=From->Flags; + } + } + return FirstMail; +} + +void WINAPI SetRemoveFlagsInQueueFcn(HYAMNMAIL From,DWORD FlagsSet,DWORD FlagsNotSet,DWORD FlagsToSetRemove,int mode) +{ + HYAMNMAIL msgq; + + for(msgq=(HYAMNMAIL)From;msgq!=NULL;msgq=msgq->Next) + { + if((FlagsSet==(msgq->Flags & FlagsSet)) && (0==(msgq->Flags & FlagsNotSet))) + { + if(mode) + msgq->Flags=msgq->Flags | FlagsToSetRemove; + else + msgq->Flags=msgq->Flags & ~FlagsToSetRemove; + } + } +} diff --git a/yamn/mails/mime.cpp b/yamn/mails/mime.cpp new file mode 100644 index 0000000..f2364c9 --- /dev/null +++ b/yamn/mails/mime.cpp @@ -0,0 +1,732 @@ +/* + * This code implements retrieving info from MIME header + * + * (c) majvan 2002-2004 + */ + +#pragma warning( disable : 4290 ) +#include "../yamn.h" + +//- imported --------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +extern SWMRG *AccountBrowserSO; +extern struct WndHandles *MessageWnd; + +extern int GetCharsetFromString(char *input,size_t size); +extern void SendMsgToRecepients(struct WndHandles *FirstWin,UINT msg,WPARAM wParam,LPARAM lParam); +extern void ConvertCodedStringToUnicode(char *stream,WCHAR **storeto,DWORD cp,int mode); +extern DWORD WINAPI MailBrowser(LPVOID Param); +extern DWORD WINAPI NoNewMailProc(LPVOID Param); +extern DWORD WINAPI BadConnection(LPVOID Param); + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +//Copies one string to another +// srcstart- source string +// srcend- address to the end of source string +// dest- pointer that stores new allocated string that contains copy of source string +// mode- MIME_PLAIN or MIME_MAIL (MIME_MAIL deletes '"' characters (or '<' and '>') if they are at start and end of source string +void CopyToHeader(char *srcstart,char *srcend,char **dest,int mode); + +//Extracts email address (finds nick name and mail and then stores them to strings) +// finder- source string +// storeto- pointer that receives address of mail string +// storetonick- pointer that receives address of nickname +void ExtractAddressFromLine(char *finder,char **storeto,char **storetonick); + +//Extracts simple text from string +// finder- source string +// storeto- pointer that receives address of string +void ExtractStringFromLine(char *finder,char **storeto); + +//Extracts some item from content-type string +//Example: ContentType string: "TEXT/PLAIN; charset=US-ASCII", item:"charset=", returns: "US-ASCII" +// ContetType- content-type string +// value- string item +// returns extracted string (or NULL when not found) +char *ExtractFromContentType(char *ContentType,char *value); + +//Extracts info from header text into header members +//Note that this function as well as struct CShortHeadwer can be always changed, because there are many items to extract +//(e.g. the X-Priority and Importance and so on) +// items- translated header (see TranslateHeaderFcn) +// head- header to be filled with values extracted from items +void ExtractShortHeader(struct CMimeItem *items,struct CShortHeader *head); + +//Extracts header to mail using ExtractShortHeader fcn. +// items- translated header (see TranslateHeaderFcn) +// CP- codepage used when no default found +// head- header to be filled with values extracted from items, in unicode (wide char) +void ExtractHeader(struct CMimeItem *items,int &CP,struct CHeader *head); + +//Deletes items in CShortHeader structure +// head- structure whose items are deleted +void DeleteShortHeaderContent(struct CShortHeader *head); + +//Deletes list of YAMN_MIMENAMES structures +// Names- pointer to first item of list +void DeleteNames(PYAMN_MIMENAMES Names); + +//Deletes list of YAMN_MIMESHORTNAMES structures +// Names- pointer to first item of list +void DeleteShortNames(PYAMN_MIMESHORTNAMES Names); + +//Makes a string lowercase +// string- string to be lowercased +void inline ToLower(char *string); + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +void CopyToHeader(char *srcstart,char *srcend,char **dest,int mode) +{ + char *dst; + + if(dest==NULL) + return; + if(srcstart>=srcend) + return; + + if((mode==MIME_MAIL) && (((*srcstart=='"') && (*(srcend-1)=='"')) || ((*srcstart=='<') && (*(srcend-1)=='>')))) + { + srcstart++; + srcend--; + } + + if(srcstart>=srcend) + return; + + if(NULL!=*dest) + delete[] *dest; + if(NULL==(*dest=new char[srcend-srcstart+1])) + return; + + dst=*dest; + + for(;srcstart' at the end of line + CopyToHeader(finder,finderend+1,storeto,MIME_MAIL); + else //at the end of line, there's '>' + { + char *finder2=finderend; + while((*finder2!='<') && (finder2>finder)) finder2--; //go to matching '<' or to the start + CopyToHeader(finder2,finderend+1,storeto,MIME_MAIL); + if(*finder2=='<') //if we found '<', the rest copy as from nick + { + finder2--; + while(WS(finder2) || ENDLINE(finder2)) finder2--; //parse whitespace + CopyToHeader(finder,finder2+1,storetonick,MIME_MAIL); //and store nickname + } + } + } + else + { + char *finderend=finder+1; + do + { + if(ENDLINEWS(finderend)) //after endline information continues + finderend+=2; + while(!ENDLINE(finderend) && (*finderend!='>') && !EOS(finderend)) finderend++; //seek to the matching < or to the end of line or to the end of string + }while(ENDLINEWS(finderend)); + CopyToHeader(finder,finderend+1,storeto,MIME_MAIL); //go to first '>' or to the end and copy + finder=finderend+1; + while(WS(finder)) finder++; //parse whitespace + if(!ENDLINE(finder) && !EOS(finder)) //if there are chars yet, it's nick + { + finderend=finder+1; + while(!ENDLINE(finderend) && !EOS(finderend)) finderend++; //seek to the end of line or to the end of string + finderend--; + while(WS(finderend)) finderend--; //find the end of line, no whitespace + CopyToHeader(finder,finderend+1,storetonick,MIME_MAIL); + } + } +} + +void ExtractStringFromLine(char *finder,char **storeto) +{ + if(finder==NULL) + { + *storeto=NULL; + return; + } + while(WS(finder)) finder++; + char *finderend=finder; + + do + { + if(ENDLINEWS(finderend)) finderend++; //after endline information continues + while(!ENDLINE(finderend) && !EOS(finderend)) finderend++; + }while(ENDLINEWS(finderend)); + finderend--; + while(WS(finderend)) finderend--; //find the end of line, no whitespace + CopyToHeader(finder,finderend+1,storeto,MIME_PLAIN); +} + +char *ExtractFromContentType(char *ContentType,char *value) +{ + char *lowered = _strdup(ContentType); + ToLower(lowered); + char *finder=strstr(lowered,value); + if(finder==NULL){ + free (lowered); + return NULL; + } + finder = finder-lowered+ContentType; + free (lowered); + + char *temp,*copier; + char *CopiedString; + + temp=finder-1; + while((temp>ContentType) && WS(temp)) temp--; //now we have to find, if the word "Charset=" is located after ';' like "; Charset=" + if(*temp!=';' && !ENDLINE(temp) && temp!=ContentType) + return NULL; + finder=finder+strlen(value); //jump over value string + + while(WS(finder)) finder++; //jump over whitespaces + temp=finder; + while(*temp!=0 && *temp!=';') temp++; //jump to the end of setting (to the next ;) + temp--; + while(WS(temp)) temp--; //remove whitespaces from the end + if (*finder=='\"'){ //remove heading and tailing quotes + finder++; + if (*temp=='\"') temp--; + } + if(NULL==(CopiedString=new char[++temp-finder+1])) + return NULL; + for(copier=CopiedString;finder!=temp;*copier++=*finder++); //copy string + *copier=0; //and end it with zero character + + return CopiedString; +} + +void ExtractShortHeader(struct CMimeItem *items,struct CShortHeader *head) +{ + for(;items!=NULL;items=items->Next) + { + //at the start of line + //MessageBox(NULL,items->value,items->name,0); + if(0==_strnicmp(items->name,"From",4)) + { + if(items->value==NULL) + continue; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,""); + #endif + ExtractAddressFromLine(items->value,&head->From,&head->FromNick); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + } + else if(0==_strnicmp(items->name,"Return-Path",11)) + { + if(items->value==NULL) + continue; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,""); + #endif + ExtractAddressFromLine(items->value,&head->ReturnPath,&head->ReturnPathNick); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + } + else if(0==_strnicmp(items->name,"Subject",7)) + { + if(items->value==NULL) + continue; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,""); + #endif + ExtractStringFromLine(items->value,&head->Subject); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + } + else if(0==_strnicmp(items->name,"Body",4)) + { + if(items->value==NULL) + continue; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,""); + #endif + ExtractStringFromLine(items->value,&head->Body); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + } + else if(0==_strnicmp(items->name,"Date",4)) + { + if(items->value==NULL) + continue; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,""); + #endif + ExtractStringFromLine(items->value,&head->Date); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + } + else if(0==_strnicmp(items->name,"Content-Type",12)) + { + if(items->value==NULL) + continue; + + char *ContentType=NULL,*CharSetStr; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,""); + #endif + ExtractStringFromLine(items->value,&ContentType); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + ToLower(ContentType); + if(NULL!=(CharSetStr=ExtractFromContentType(ContentType,"charset="))) + { + head->CP=GetCharsetFromString(CharSetStr,strlen(CharSetStr)); + delete[] CharSetStr; + } + delete[] ContentType; + } + else if(0==_strnicmp(items->name,"Importance",10)) + { + if(items->value==NULL) + continue; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,""); + #endif + if(head->Priority!=-1) + { + if(0==strncmp(items->value,"low",3)) + head->Priority=5; + else if(0==strncmp(items->value,"normal",6)) + head->Priority=3; + else if(0==strncmp(items->value,"high",4)) + head->Priority=1; + } + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + } + else if(0==_strnicmp(items->name,"X-Priority",10)) + { + if(items->value==NULL) + continue; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,""); + #endif + if((*items->value>='1') && (*items->value<='5')) + head->Priority=*items->value-'0'; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + } + + } +} + +void ExtractHeader(struct CMimeItem *items,int &CP,struct CHeader *head) +{ + struct CShortHeader ShortHeader; + + ZeroMemory(&ShortHeader,sizeof(struct CShortHeader)); + ShortHeader.Priority=ShortHeader.CP=-1; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + ExtractShortHeader(items,&ShortHeader); + + head->Priority=ShortHeader.Priority==-1 ? 3 : ShortHeader.Priority; + CP=ShortHeader.CP==-1 ? CP : ShortHeader.CP; + #ifdef DEBUG_DECODE + if(NULL!=ShortHeader.From) + DebugLog(DecodeFile,"%s%s%s%s%s%s\n"); + DebugLog(DecodeFile,"\n"); + #endif + + ConvertCodedStringToUnicode(ShortHeader.From,&head->From,CP,MIME_PLAIN); + + #ifdef DEBUG_DECODE + if(NULL!=head->From) + DebugLogW(DecodeFile,L"%s\n",head->From); + #endif + ConvertCodedStringToUnicode(ShortHeader.FromNick,&head->FromNick,CP,MIME_MAIL); + #ifdef DEBUG_DECODE + if(NULL!=head->FromNick) + DebugLogW(DecodeFile,L"%s\n",head->FromNick); + #endif + ConvertCodedStringToUnicode(ShortHeader.ReturnPath,&head->ReturnPath,CP,MIME_PLAIN); + #ifdef DEBUG_DECODE + if(NULL!=head->ReturnPath) + DebugLogW(DecodeFile,L"%s\n",head->ReturnPath); + #endif + ConvertCodedStringToUnicode(ShortHeader.ReturnPathNick,&head->ReturnPathNick,CP,MIME_MAIL); + #ifdef DEBUG_DECODE + if(NULL!=head->ReturnPathNick) + DebugLogW(DecodeFile,L"%s\n",head->ReturnPathNick); + #endif + ConvertCodedStringToUnicode(ShortHeader.Subject,&head->Subject,CP,MIME_PLAIN); + #ifdef DEBUG_DECODE + if(NULL!=head->Subject) + DebugLogW(DecodeFile,L"%s\n",head->Subject); + #endif + ConvertCodedStringToUnicode(ShortHeader.Date,&head->Date,CP,MIME_PLAIN); + #ifdef DEBUG_DECODE + if(NULL!=head->Date) + DebugLogW(DecodeFile,L"%s\n",head->Date); + #endif + + ConvertCodedStringToUnicode(ShortHeader.Body,&head->Body,CP,MIME_PLAIN); + #ifdef DEBUG_DECODE + if(NULL!=head->Body) + DebugLogW(DecodeFile,L"%s\n",head->Body); + #endif + + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + + DeleteShortHeaderContent(&ShortHeader); + +// head->From=L"Frommmm"; +// head->Subject=L"Subject"; + return; +} + +void DeleteShortHeaderContent(struct CShortHeader *head) +{ + if(head->From!=NULL) delete[] head->From; + if(head->FromNick!=NULL) delete[] head->FromNick; + if(head->ReturnPath!=NULL) delete[] head->ReturnPath; + if(head->ReturnPathNick!=NULL) delete[] head->ReturnPathNick; + if(head->Subject!=NULL) delete[] head->Subject; + if(head->Date!=NULL) delete[] head->Date; + if(head->To!=NULL) DeleteShortNames(head->To); + if(head->Cc!=NULL) DeleteShortNames(head->Cc); + if(head->Bcc!=NULL) DeleteShortNames(head->Bcc); + if(head->Body!=NULL) delete[] head->Body; +} + +void DeleteHeaderContent(struct CHeader *head) +{ + if(head->From!=NULL) delete[] head->From; + if(head->FromNick!=NULL) delete[] head->FromNick; + if(head->ReturnPath!=NULL) delete[] head->ReturnPath; + if(head->ReturnPathNick!=NULL) delete[] head->ReturnPathNick; + if(head->Subject!=NULL) delete[] head->Subject; + if(head->Date!=NULL) delete[] head->Date; + if(head->Body!=NULL) delete[] head->Body; + if(head->To!=NULL) DeleteNames(head->To); + if(head->Cc!=NULL) DeleteNames(head->Cc); + if(head->Bcc!=NULL) DeleteNames(head->Bcc); +} + +void DeleteNames(PYAMN_MIMENAMES Names) +{ + PYAMN_MIMENAMES Parser=Names,Old; + for(;Parser!=NULL;Parser=Parser->Next) + { + if(Parser->Value!=NULL) + delete[] Parser->Value; + if(Parser->ValueNick!=NULL) + delete[] Parser->ValueNick; + Old=Parser; + Parser=Parser->Next; + delete Old; + } +} + +void DeleteShortNames(PYAMN_MIMESHORTNAMES Names) +{ + PYAMN_MIMESHORTNAMES Parser=Names,Old; + for(;Parser!=NULL;Parser=Parser->Next) + { + if(Parser->Value!=NULL) + delete[] Parser->Value; + if(Parser->ValueNick!=NULL) + delete[] Parser->ValueNick; + Old=Parser; + Parser=Parser->Next; + delete Old; + } +} + + +void inline ToLower(char *string) +{ + for(;*string!=0;string++) + if(*string>='A' && *string<='Z') *string=*string-'A'+'a'; +} + +#define TE_UNKNOWN +#define TE_QUOTEDPRINTABLE 1 +#define TE_BASE64 2 +struct APartDataType +{ + char *Src;//Input + char *ContType; + int CodePage; + char *TransEnc; + BYTE TransEncType; //TE_something + char *body; + int bodyLen; + WCHAR *wBody; +}; + + +void ParseAPart(APartDataType *data) +{ + size_t len = strlen(data->Src); + try + { + char *finder=data->Src; + char *prev1,*prev2,*prev3; + + while(finder<=(data->Src+len)) + { + while(ENDLINEWS(finder)) finder++; + + //at the start of line + if (finder>data->Src){ + if (*(finder-2)=='\r' || *(finder-2)=='\n') + *(finder-2)=0; + if (*(finder-1)=='\r' || *(finder-1)=='\n') + *(finder-1)=0; + } + prev1=finder; + + while(*finder!=':' && !EOS(finder) && !ENDLINE(finder)) finder++; + if (ENDLINE(finder)||EOS(finder)){ + // no ":" in the line? here the body begins; + data->body = prev1; + break; + } + prev2=finder++; + + while(WS(finder) && !EOS(finder)) finder++; + if(!EOS(finder)) + prev3=finder; + else + break; + + do + { + if(ENDLINEWS(finder)) finder+=2; //after endline information continues + while(!ENDLINE(finder) && !EOS(finder)) finder++; + }while(ENDLINEWS(finder)); + + if (!_strnicmp(prev1,"Content-type",prev2-prev1)){ + data->ContType = prev3; + } else if (!_strnicmp(prev1,"Content-Transfer-Encoding",prev2-prev1)){ + data->TransEnc = prev3; + } + + if(EOS(finder)) + break; + finder++; + if(ENDLINE(finder)) { + finder++; + if(ENDLINE(finder)) { + // end of headers. message body begins + if (finder>data->Src){ + if (*(finder-2)=='\r' || *(finder-2)=='\n') + *(finder-2)=0; + if (*(finder-1)=='\r' || *(finder-1)=='\n') + *(finder-1)=0; + } + finder++; + if(ENDLINE(finder))finder++; + prev1 = finder; + while (!EOS(finder+1))finder++; + if (ENDLINE(finder))finder--; + prev2 = finder; + if (prev2>prev1){ // yes, we have body + data->body = prev1; + } + break; // there is nothing else + } + } + } + } + catch(...) + { + MessageBox(NULL,_T("Translate header error"),_T(""),0); + } + if (data->body) data->bodyLen = (int)strlen(data->body); +} + +//from decode.cpp +int DecodeQuotedPrintable(char *Src,char *Dst,int DstLen, BOOL isQ); +int DecodeBase64(char *Src,char *Dst,int DstLen); +int ConvertStringToUnicode(char *stream,unsigned int cp,WCHAR **out); + +WCHAR *ParseMultipartBody(char *src, char *bond) +{ + char *srcback = _strdup(src); + size_t sizebond = strlen(bond); + int numparts = 1; + int i; + char *courbond = srcback; + WCHAR *dest; + for (;(courbond=strstr(courbond,bond));numparts++,courbond+=sizebond); + APartDataType *partData = new APartDataType[numparts]; + memset(partData, 0, sizeof(APartDataType)*numparts); + partData[0].Src = courbond = srcback; + for (i=1;(courbond=strstr(courbond,bond));i++,courbond+=sizebond){ + *(courbond-2) = 0; + partData[i].Src = courbond+sizebond; + while (ENDLINE(partData[i].Src)) partData[i].Src++; + } + size_t resultSize=0; + for (i=0;i +Delivered-To: pablo@decode.com.ar +Received: (qmail 5438 invoked by uid 618); 5 Sep 2003 19:49:16 -0000 +Mailing-List: contact foromundial-help@decode.com.ar; run by ezmlm +Precedence: bulk +X-No-Archive: yes +List-Post: +List-Help: +List-Unsubscribe: +List-Subscribe: +X-Seq: 1047 +Delivered-To: mailing list foromundial@decode.com.ar +Received: (qmail 5432 invoked by uid 618); 5 Sep 2003 19:49:15 -0000 +X-Spam-Status: No, hits=3.9 required=7.5 +Message-Id: <4.2.1.20030905163128.00a998a0@mail.labsem.cetuc.puc-rio.br> +X-Sender: sandra@mail.labsem.cetuc.puc-rio.br +X-Mailer: QUALCOMM Windows Eudora Pro Version 4.2.1 +Date: Fri, 05 Sep 2003 16:48:12 -0300 +To: foromundial@decode.com.ar +From: "Sandra M. Landi" +Mime-Version: 1.0 +Content-Type: multipart/alternative; + boundary="=====================_4293080==_.ALT" +X-Antirelay: Good relay from local net2 139.82.127.0/26 +Subject: [foromundial-1047] frases para un viernes + + +. diff --git a/yamn/mails/test/header2.txt b/yamn/mails/test/header2.txt new file mode 100644 index 0000000..3ba81a2 --- /dev/null +++ b/yamn/mails/test/header2.txt @@ -0,0 +1,97 @@ +Return-Path: +Received: [from megami.sprintserve.net (megami.sprintserve.net [207.142.136.160]) + by mail2.ba.psg.sk with ESMTP id i4FHNUY6018585 + for ; Sat, 15 May 2004 19:23:31 +0200] +X-Envelope-To: +Received: from miranda by megami.sprintserve.net with local (Exim 4.34) + id 1BP2sS-0006W6-MS + for om3tn@psg.sk; Sat, 15 May 2004 13:23:12 -0400 +To: Undisclosed-recipients:; +Subject: UpozornØn¡ na odpovØÔ v t‚matu - YAMN problem +Reply-to: forum@miranda-im.org +From: forum@miranda-im.org: +Message-ID: +MIME-Version: 1.0 +Content-type: text/plain; charset=Windows-1250 +Content-transfer-encoding: 8bit +Date: Sat, 15 May 2004 13:23:12 -0400 +X-Priority: 3 +X-MSMail-Priority: Normal +X-Mailer: PHP +X-MimeOLE: Produced By phpBB2 +X-MailScanner-Information: Please contact the ISP for more information +X-MailScanner: Found to be clean +X-AntiAbuse: This header was added to track abuse, please include it with any abuse report +X-AntiAbuse: Primary Hostname - megami.sprintserve.net +X-AntiAbuse: Original Domain - psg.sk +X-AntiAbuse: Originator/Caller UID/GID - [32110 32110] / [47 12] +X-AntiAbuse: Sender Address Domain - megami.sprintserve.net +X-Source: +X-Source-Args: +X-Source-Dir: +. + +Subject: UpozornØn¡ na odpovØÔ v t‚matu - YAMN problem + +Return-Path: +Received: [from megami.sprintserve.net (megami.sprintserve.net [207.142.136.160]) + by mail2.ba.psg.sk with ESMTP id i4FHX2Y6020695 + for ; Sat, 15 May 2004 19:33:03 +0200] +X-Envelope-To: +Received: from miranda by megami.sprintserve.net with local (Exim 4.34) + id 1BP31h-0001cs-Ai + for om3tn@psg.sk; Sat, 15 May 2004 13:32:45 -0400 +To: Undisclosed-recipients:; +Subject: UpozornØn¡ na odpovØÔ v t‚matu - YAMN problem +Reply-to: forum@miranda-im.org +From: forum@miranda-im.org +Message-ID: <0873b36d0931479c4ebe23ba71ff4810@forums.miranda-im.org> +MIME-Version: 1.0 +Content-type: text/plain; charset=Windows-1250 +Content-transfer-encoding: 8bit +Date: Sat, 15 May 2004 13:32:45 -0400 +X-Priority: 3 +X-MSMail-Priority: Normal +X-Mailer: PHP +X-MimeOLE: Produced By phpBB2 +X-MailScanner-Information: Please contact the ISP for more information +X-MailScanner: Found to be clean +X-AntiAbuse: This header was added to track abuse, please include it with any abuse report +X-AntiAbuse: Primary Hostname - megami.sprintserve.net +X-AntiAbuse: Original Domain - psg.sk +X-AntiAbuse: Originator/Caller UID/GID - [32110 32110] / [47 12] +X-AntiAbuse: Sender Address Domain - megami.sprintserve.net +X-Source: +X-Source-Args: +X-Source-Dir: + +. + +Received: by hplm (mbox om3tn) + (with POP3 daemon cucipop (v1.31 1998/05/13) Tue May 27 18:42:20 2003) +X-From_: HMF@hotbox.ru Tue May 20 18:11:44 2003 +Return-Path: +Received: from ns1.slovanet.net (ns1.slovanet.net [195.28.64.119]) + by hplm.psg.sk (8.12.9/8.12.7) with SMTP id h4KGBfxJ003732 + for ; Tue, 20 May 2003 18:11:44 +0200 +X-Envelope-To: +Received: (qmail 6339 invoked from network); 20 May 2003 18:11:45 +0200 +Received: from unknown (HELO ??+???) (61.33.134.106) + by ns1.slovanet.net with SMTP; 20 May 2003 18:11:45 +0200 +Received: by london.com (Postfix, from userid 302) + id WTS; Tue, 20 May 2003 20:13:19 +Received: from Œù+⌥ (Œù+⌥ [61.33.134.106]) + by mill.co.uk (Postfix) with ESMTP id 613 + for ; Tue, 20 May 2003 20:13:19 +Subject: Òàìîæåííàî÷èñòêà. ÔèíëäèÌîñêâà. Îò 0,8 çà êã, âêëþ÷àâñå ! 20:13:19 +From: +To: OM3TN +Reply-To: <> +X-Mailer: AOL 7.0 for Windows UK sub 52 +X-Priority: 1 +X-MSMail-Priority: High +Mime-Version: 1.0 +Content-Type: text/html; charset="Windows-1251" +Content-Transfer-Encoding: 7bit +Date: Tue, 20 May 2003 20:13:21 +Message-Id: \ No newline at end of file diff --git a/yamn/mails/test/readme.txt b/yamn/mails/test/readme.txt new file mode 100644 index 0000000..35a30b2 --- /dev/null +++ b/yamn/mails/test/readme.txt @@ -0,0 +1,4 @@ +This is project for testing mime encoding/decoding. It +is very usefull for developers, when some problems with +non-standard headers occured. You can use it to step through +MIME decoding functions. diff --git a/yamn/mails/test/test.cpp b/yamn/mails/test/test.cpp new file mode 100644 index 0000000..f8dcd14 --- /dev/null +++ b/yamn/mails/test/test.cpp @@ -0,0 +1,42 @@ +/* + * This file is for testing purposes. Save in header.txt your problem header and you can + * browse through functions to get result + * + * (c) majvan 2002-2004 + */ + +#include +#include "../m_mails.h" + +extern void WINAPI TranslateHeaderFcn(char *stream,int len,struct CMimeItem **head); +extern void ExtractHeader(struct CMimeItem *items,int CP,struct CHeader *head); + +void main() +{ + char Buffer[8192]; //we do not suppose longer header + FILE *fp; + YAMNMAIL *Mail; + PMAILDATA *MailData; + CMimeItem *head; + + struct CHeader ExtractedHeader; + + if(NULL==(fp=fopen("header2.txt","r"))) + return; + fread(Buffer,sizeof(Buffer),1,fp); + if(ferror(fp)) + { + fclose(fp); + return; + } + fclose(fp); + Mail = new YAMNMAIL; + MailData = new PMAILDATA; + head = new CMimeItem; + Mail->MailData = *MailData; + Mail->MailData->TranslatedHeader = head; + + TranslateHeaderFcn(Buffer,strlen(Buffer), &Mail->MailData->TranslatedHeader); + ExtractHeader(Mail->MailData->TranslatedHeader,CP_ACP,&ExtractedHeader); + return; +} \ No newline at end of file diff --git a/yamn/mails/test/test.dsp b/yamn/mails/test/test.dsp new file mode 100644 index 0000000..6d01b36 --- /dev/null +++ b/yamn/mails/test/test.dsp @@ -0,0 +1,112 @@ +# Microsoft Developer Studio Project File - Name="test" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=test - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "test.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "test.mak" CFG="test - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "test - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "test - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "test - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x405 /d "NDEBUG" +# ADD RSC /l 0x405 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "test - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c +# ADD BASE RSC /l 0x405 /d "_DEBUG" +# ADD RSC /l 0x405 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "test - Win32 Release" +# Name "test - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\decode.cpp +# End Source File +# Begin Source File + +SOURCE=..\mails.cpp +# End Source File +# Begin Source File + +SOURCE=..\mime.cpp +# End Source File +# Begin Source File + +SOURCE=.\test.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/yamn/mails/test/test.dsw b/yamn/mails/test/test.dsw new file mode 100644 index 0000000..e25096d --- /dev/null +++ b/yamn/mails/test/test.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "test"=.\test.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/yamn/main.cpp b/yamn/main.cpp new file mode 100644 index 0000000..9abb1a9 --- /dev/null +++ b/yamn/main.cpp @@ -0,0 +1,846 @@ +/* + * YAMN plugin main file + * Miranda homepage: http://miranda-icq.sourceforge.net/ + * YAMN homepage: http://www.majvan.host.sk/Projekty/YAMN + * + * initializes all variables for further work + * + * (c) majvan 2002-2004 + */ + + +#include "main.h" +#include "yamn.h" +#include "resources/resource.h" +#include +//- imported --------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +//CRITICAL_SECTION MWCS; +//CRITICAL_SECTION ASCS; +//CRITICAL_SECTION PRCS; + +extern LPCRITICAL_SECTION PluginRegCS; +extern HANDLE ExitEV; +extern HANDLE WriteToFileEV; + +extern int PosX,PosY,SizeX,SizeY; +extern int HeadPosX,HeadPosY,HeadSizeX,HeadSizeY,HeadSplitPos; + +//From account.cpp +extern LPCRITICAL_SECTION AccountStatusCS; +extern LPCRITICAL_SECTION FileWritingCS; +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +WCHAR *ProfileName = NULL; //e.g. "majvan" +WCHAR *UserDirectory = NULL; //e.g. "F:\WINNT\Profiles\UserXYZ" +char *ProtoName = YAMN_DBMODULE; +//char *AltProtoName; +char *szMirandaDir = NULL; +char *szProfileDir = NULL; + +INT_PTR YAMN_STATUS; + +BOOL UninstallPlugins; + +HANDLE hAccountFolder; + +HINSTANCE *hDllPlugins; +static int iDllPlugins=0; + +PLUGINLINK *pluginLink; +YAMN_VARIABLES YAMNVar; + +static const MUUID interfaces[] = {MUUID_YAMN_FORCECHECK, MIID_LAST}; + +PLUGININFOEX pluginInfo={ + sizeof(PLUGININFOEX), + YAMN_SHORTNAME, + YAMN_VERSION, + "Mail notifier and browser for Miranda IM. Included POP3 protocol.", + "y_b tweety (majvan)", + "francois.mean@skynet.be", + "© (2002-2004 majvan) 2005-2007 tweety y_b Miranda community", + "http://www.miranda-im.org/download/details.php?action=viewfile&id=3411", //"http://www.majvan.host.sk/Projekty/YAMN?fm=soft", + UNICODE_AWARE, + 0, //doesn't replace anything built-in + { 0xb047a7e5, 0x27a, 0x4cfc, { 0x8b, 0x18, 0xed, 0xa8, 0x34, 0x5d, 0x27, 0x90 } } // {B047A7E5-027A-4cfc-8B18-EDA8345D2790} + +}; + +SKINSOUNDDESC NewMailSound={ + sizeof(SKINSOUNDDESC), + YAMN_NEWMAILSOUND, //name to refer to sound when playing and in db + YAMN_NEWMAILSNDDESC, //description for options dialog + "", //default sound file to use, without path +}; + +SKINSOUNDDESC ConnectFailureSound={ + sizeof(SKINSOUNDDESC), + YAMN_CONNECTFAILSOUND, //name to refer to sound when playing and in db + YAMN_CONNECTFAILSNDDESC,//description for options dialog + "", //default sound file to use, without path +}; + +HANDLE hNewMailHook; +//HANDLE hUninstallPluginsHook; + +HANDLE NoWriterEV; + +HANDLE hTTButton; //TopToolBar button + +DWORD HotKeyThreadID; + +UINT SecTimer; + +BOOL bIcolibEmbededInCore = FALSE; + +HICON hYamnIcons[ICONSNUMBER]; +char *iconDescs[ICONSNUMBER]={ICONSDESCS}; +char *iconNames[ICONSNUMBER]={ICONSNAMES}; + int iconIndexes[ICONSNUMBER]={ICONSINDS}; + +HANDLE hMenuItemMain = 0; +HANDLE hMenuItemCont = 0; +HANDLE hMenuItemContApp = 0; + +BOOL (WINAPI *MyEnableThemeDialogTexture)(HANDLE, DWORD) = 0; +HMODULE hUxTheme = 0; + +// function pointers, use typedefs for casting to shut up the compiler when using GetProcAddress() + +typedef BOOL (WINAPI *PITA)(); +typedef HANDLE (WINAPI *POTD)(HWND, LPCWSTR); +typedef UINT (WINAPI *PDTB)(HANDLE, HDC, int, int, RECT *, RECT *); +typedef UINT (WINAPI *PCTD)(HANDLE); +typedef UINT (WINAPI *PDTT)(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, DWORD, RECT *); + +PITA pfnIsThemeActive = 0; +POTD pfnOpenThemeData = 0; +PDTB pfnDrawThemeBackground = 0; +PCTD pfnCloseThemeData = 0; +PDTT pfnDrawThemeText = 0; + +#define FIXED_TAB_SIZE 100 // default value for fixed width tabs + +/* + * visual styles support (XP+) + * returns 0 on failure + */ + +int InitVSApi() +{ + if((hUxTheme = LoadLibraryA("uxtheme.dll")) == 0) + return 0; + + pfnIsThemeActive = (PITA)GetProcAddress(hUxTheme, "IsThemeActive"); + pfnOpenThemeData = (POTD)GetProcAddress(hUxTheme, "OpenThemeData"); + pfnDrawThemeBackground = (PDTB)GetProcAddress(hUxTheme, "DrawThemeBackground"); + pfnCloseThemeData = (PCTD)GetProcAddress(hUxTheme, "CloseThemeData"); + pfnDrawThemeText = (PDTT)GetProcAddress(hUxTheme, "DrawThemeText"); + + MyEnableThemeDialogTexture = (BOOL (WINAPI *)(HANDLE, DWORD))GetProcAddress(hUxTheme, "EnableThemeDialogTexture"); + if(pfnIsThemeActive != 0 && pfnOpenThemeData != 0 && pfnDrawThemeBackground != 0 && pfnCloseThemeData != 0 && pfnDrawThemeText != 0) { + return 1; + } + return 0; +} + +/* + * unload uxtheme.dll + */ + +int FreeVSApi() +{ + if(hUxTheme != 0) + FreeLibrary(hUxTheme); + return 0; +} + + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +static void GetProfileDirectory(char *szPath,int cbPath) +//This is copied from Miranda's sources. In 0.2.1.0 it is needed, in newer vesions of Miranda use MS_DB_GETPROFILEPATH service +{ + szProfileDir=new char[MAX_PATH]; + if (ServiceExists(MS_DB_GETPROFILEPATH)){ + if (!CallService(MS_DB_GETPROFILEPATH,(WPARAM)cbPath,(LPARAM)szPath)) { + lstrcpy(szProfileDir,szPath); + return; //success + } + } + char szMirandaIni[MAX_PATH],szExpandedProfileDir[MAX_PATH]; + DWORD dwAttributes; + + lstrcpy(szMirandaIni,szMirandaDir); + lstrcat(szMirandaIni,"\\mirandaboot.ini"); + GetPrivateProfileString("Database","ProfileDir",".",szProfileDir,sizeof(szProfileDir),szMirandaIni); + ExpandEnvironmentStrings(szProfileDir,szExpandedProfileDir,sizeof(szExpandedProfileDir)); + _chdir(szMirandaDir); + if(!_fullpath(szPath,szExpandedProfileDir,cbPath)) + lstrcpyn(szPath,szMirandaDir,cbPath); + if(szPath[lstrlen(szPath)-1]=='\\') szPath[lstrlen(szPath)-1]='\0'; + if((dwAttributes=GetFileAttributes(szPath))!=0xffffffff&&dwAttributes&FILE_ATTRIBUTE_DIRECTORY) return; + CreateDirectory(szPath,NULL); +} + +void SetDefaultProtocolIcons() +{ + char szFileName[MAX_PATH+1]; + char oldname[] = YAMN_DBMODULE"4007_"; // the deprecated one + char dllname[] = "plugins\\"YAMN_DBMODULE".dll,-xxxxx"; + + // determine whether external icon file exists + lstrcpy(szFileName, szMirandaDir); + lstrcat(szFileName, "\\icons\\proto_"YAMN_DBMODULE".dll"); + BOOL isDllPresent = (_access(szFileName, 0) == 0); + + WORD statuses[4] = {ID_STATUS_OFFLINE,ID_STATUS_ONLINE,ID_STATUS_NA,ID_STATUS_OCCUPIED}; + BYTE indices[4] = {7, 0, 3, 4}; + //From skinicons.c skinIconStatusToIdStatus[] + BYTE protoStatusInd[4] = {0,1,4,5}; + + for (int i=0;i<4;i++){ + oldname[sizeof(oldname)-2]=protoStatusInd[i]+'1'; // "Out for lunch will not work here" + if (isDllPresent){ // use the icons in proto_YAMN.dll and delete any user settings + DBDeleteContactSetting(NULL, "Icons", oldname); + } else { + DBVARIANT dbv; + if(!DBGetContactSetting(NULL,"SkinIcons",iconNames[indices[i]],&dbv)) + {// user won't be able to set status icons different from those in YAMN section + DBWriteContactSettingString(NULL, "Icons", oldname, (char *)dbv.pszVal); + DBFreeVariant(&dbv); + } else { + _snprintf(&dllname[sizeof(dllname)-6],5,"%d",iconIndexes[indices[i]]); + DBWriteContactSettingString(NULL, "Icons", oldname, dllname); + } + } + } +} + +extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) +{ +#ifndef WIN2IN1 + OSVERSIONINFO OSversion; + + OSversion.dwOSVersionInfoSize=sizeof(OSVERSIONINFO); + + GetVersionEx(&OSversion); + switch(OSversion.dwPlatformId) + { + case VER_PLATFORM_WIN32s: + case VER_PLATFORM_WIN32_WINDOWS: +#ifndef WIN9X + MessageBoxA(NULL,"This YAMN cannot run on Windows 95, 98 or Me. Why? Read FAQ. You should download Win9x version.","YAMN error",MB_OK | MB_ICONSTOP); + return FALSE; +#else + break; +#endif + case VER_PLATFORM_WIN32_NT: +#ifdef WIN9X + MessageBoxA(NULL,"This YAMN is intended for Windows 95, 98 or Me. You should use native WinNT version.","YAMN error",MB_OK | MB_ICONSTOP); + return FALSE; +#else + break; +#endif + } +#endif // WIN2IN1 + YAMNVar.hInst=hinstDLL; + if(fdwReason==DLL_PROCESS_ATTACH) + { + if(NULL==(UserDirectory=new WCHAR[MAX_PATH])) + return FALSE; + } + return TRUE; +} + +extern "C" __declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion) +{ + if (mirandaVersion >= PLUGIN_MAKE_VERSION(0, 7, 0, 3)) + bIcolibEmbededInCore = TRUE; + pluginInfo.cbSize = sizeof(PLUGININFO);//Miranda pre-0.7.0.17 does not load the plugin if cbSize does not match. + return (PLUGININFO *) &pluginInfo; +} + +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) +{ + if (mirandaVersion >= PLUGIN_MAKE_VERSION(0, 7, 0, 3)) + bIcolibEmbededInCore = TRUE; + pluginInfo.cbSize = sizeof(PLUGININFOEX);//Make sure cbSize is correct; + return &pluginInfo; +} + +extern "C" __declspec(dllexport) const MUUID * MirandaPluginInterfaces(void) +{ + return interfaces; +} + +#ifdef YAMN_DEBUG +static char unknownCP[1500]={0}; +#endif +// The callback function +BOOL CALLBACK EnumSystemCodePagesProc(LPTSTR cpStr) +{ + //Convert code page string to number + UINT cp = _ttoi(cpStr); + if (!IsValidCodePage(cp)) + return TRUE; + + //Get Code Page name + CPINFOEX info; + if(GetCPInfoEx(cp,0,&info)){ + #ifdef YAMN_DEBUG + BOOLEAN found = FALSE; + #endif + for (int i=1;iYAMN tweety win9x "; + #else + update.szUpdateURL = "http://addons.miranda-im.org/feed.php?dlfile=2165"; + update.szVersionURL = "http://addons.miranda-im.org/details.php?action=viewfile&id=2165"; + update.pbVersionPrefix = (BYTE *)"YAMN tweety "; + #endif*/ + update.szUpdateURL = "http://addons.miranda-im.org/feed.php?dlfile=3411"; + update.szVersionURL = "http://addons.miranda-im.org/details.php?action=viewfile&id=3411"; + update.pbVersionPrefix = (BYTE *)"YAMN 2in1 "; + wsprintf(szUrl,"http://www.miranda-fr.net/tweety/yamn/%s.zip",YAMN_FILENAME); + update.szBetaUpdateURL = szUrl; + update.szBetaVersionURL = "http://www.miranda-fr.net/tweety/yamn/yamn_beta.html"; + update.pbBetaVersionPrefix = (BYTE *)"YAMN version "; + update.cpbVersionPrefix = (int)strlen((char *)update.pbVersionPrefix); + update.cpbBetaVersionPrefix = (int)strlen((char *)update.pbBetaVersionPrefix); + + CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update); + + } + if (ServiceExists(MS_FOLDERS_GET_PATH)){ + //char AccountFolder[MAX_PATH]; + //CallService(MS_DB_GETPROFILEPATH, (WPARAM) MAX_PATH, (LPARAM)AccountFolder); + //sprintf(AccountFolder,"%s\\%s",AccountFolder,ProtoName); + hAccountFolder = FoldersRegisterCustomPathW(ProtoName,YAMN_DBMODULE" Account Folder",UserDirectory); + + FoldersGetCustomPathW(hAccountFolder, UserDirectory, MAX_PATH, UserDirectory); + //MultiByteToWideChar(CP_ACP,MB_USEGLYPHCHARS,AccountFolder,-1,UserDirectory,strlen(AccountFolder)+1); + } + + RegisterPOP3Plugin(0,0); + + return 0; +} + +//int IcoLibIconsChanged(WPARAM wParam, LPARAM lParam); // implemented in services.cpp +extern HCURSOR hCurSplitNS, hCurSplitWE; +extern "C" int __declspec(dllexport) Load(PLUGINLINK *link) +{ + UINT mod,vk; + char pn[MAX_PATH+1]; + char *fc; + int i,k; + + pluginLink=link; + + YAMN_STATUS = ID_STATUS_OFFLINE; + + // we get the Miranda Root Path + szMirandaDir=new char[MAX_PATH]; + if (ServiceExists(MS_UTILS_PATHTOABSOLUTE)){ + CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)".",(LPARAM)szMirandaDir); + } + else { + char *str2; + GetModuleFileName(GetModuleHandle(NULL),szMirandaDir,MAX_PATH); + str2=strrchr(szMirandaDir,'\\'); + if(str2!=NULL) *str2=0; + } + + // we get the user path where our yamn-account.book.ini is stored from mirandaboot.ini file + char szProfileDir[MAX_PATH+1]; + GetProfileDirectory(szProfileDir,sizeof(szProfileDir)); + MultiByteToWideChar(CP_ACP,MB_USEGLYPHCHARS,szProfileDir,-1,UserDirectory,(int)strlen(szProfileDir)+1); + + + // Enumerate all the code pages available for the System Locale + EnumSystemCodePages(EnumSystemCodePagesProc, CP_INSTALLED); + CodePageNamesSupp = new _tcptable[CPLENSUPP]; + for (i=0,k=0;ipszDocsPath,DocFiles); + if(ppup->bDoDeleteSettings) + PUIRemoveDbModule("YAMN"); + return 0; +} + +int Shutdown(WPARAM,LPARAM) +{ + DBWriteContactSettingDword(NULL,YAMN_DBMODULE,YAMN_DBMSGPOSX,HeadPosX); + DBWriteContactSettingDword(NULL,YAMN_DBMODULE,YAMN_DBMSGPOSY,HeadPosY); + DBWriteContactSettingDword(NULL,YAMN_DBMODULE,YAMN_DBMSGSIZEX,HeadSizeX); + DBWriteContactSettingDword(NULL,YAMN_DBMODULE,YAMN_DBMSGSIZEY,HeadSizeY); + DBWriteContactSettingWord(NULL,YAMN_DBMODULE,YAMN_DBMSGPOSSPLIT,HeadSplitPos); + YAMNVar.Shutdown=TRUE; +// CallService(MS_TTB_REMOVEBUTTON,(WPARAM)hTTButton,0); //this often leads to deadlock in Miranda (bug in Miranda) + KillTimer(NULL,SecTimer); + + UnregisterProtoPlugins(); + UnregisterFilterPlugins(); + return 0; +} + +//We undo all things from Load() +extern "C" int __declspec(dllexport) Unload(void) +{ +#ifdef YAMN_DEBUG + UnInitDebug(); +#endif + DestroyCursor(hCurSplitNS); + DestroyCursor(hCurSplitWE); + + CloseHandle(NoWriterEV); + CloseHandle(WriteToFileEV); + CloseHandle(ExitEV); + + FreeVSApi(); + + DeleteCriticalSection(AccountStatusCS); + delete AccountStatusCS; + DeleteCriticalSection(FileWritingCS); + delete FileWritingCS; + DeleteCriticalSection(PluginRegCS); + + delete PluginRegCS; + UnhookEvents(); + DestroyServiceFunctions(); + + UnloadPlugins(); + + delete [] CodePageNamesSupp; + delete [] szMirandaDir; + delete [] UserDirectory; + delete [] szProfileDir; + delete [] ProfileName; + return 0; +} + +void LoadPlugins() +{ + HANDLE hFind; + WIN32_FIND_DATA fd; + char szSearchPath[MAX_PATH]; + char szPluginPath[MAX_PATH]; + lstrcpy(szSearchPath,szMirandaDir); + lstrcat(szSearchPath,"\\Plugins\\YAMN\\*.dll"); + typedef INT_PTR (*LOADFILTERFCN)(MIRANDASERVICE GetYAMNFcn); + + hDllPlugins=NULL; + + if(INVALID_HANDLE_VALUE!=(hFind=FindFirstFile(szSearchPath,&fd))) + { + do + { //rewritten from Miranda sources... Needed because Win32 API has a bug in FindFirstFile, search is done for *.dlllllll... too + char *dot=strrchr(fd.cFileName,'.'); + if(dot) + { // we have a dot + int len=(int)strlen(fd.cFileName); // find the length of the string + char* end=fd.cFileName+len; // get a pointer to the NULL + int safe=(end-dot)-1; // figure out how many chars after the dot are "safe", not including NULL + + if((safe!=3) || (lstrcmpi(dot+1,"dll")!=0)) //not bound, however the "dll" string should mean only 3 chars are compared + continue; + } + else + continue; + + HINSTANCE hDll; + LOADFILTERFCN LoadFilter; + + lstrcpy(szPluginPath,szMirandaDir); + lstrcat(szPluginPath,"\\Plugins\\YAMN\\"); + lstrcat(szPluginPath,fd.cFileName); + if((hDll=LoadLibrary(szPluginPath))==NULL) continue; + LoadFilter=(LOADFILTERFCN)GetProcAddress(hDll,"LoadFilter"); + if(NULL==LoadFilter) + { + FreeLibrary(hDll); + hDll=NULL; + continue; + } + if(!(*LoadFilter)(GetFcnPtrSvc)) + { + FreeLibrary(hDll); + hDll=NULL; + } + + if(hDll!=NULL) + { + hDllPlugins=(HINSTANCE *)realloc((void *)hDllPlugins,(iDllPlugins+1)*sizeof(HINSTANCE)); + hDllPlugins[iDllPlugins++]=hDll; + } + } while(FindNextFile(hFind,&fd)); + FindClose(hFind); + } +} + +void UnloadPlugins() +{ + for(int i=iDllPlugins-1;i>=0;i--) { + if(FreeLibrary(hDllPlugins[i])){ + hDllPlugins[i]=NULL; //for safety + iDllPlugins --; + } + } + if(hDllPlugins){ + free((void *)hDllPlugins); + hDllPlugins = NULL; + } +} + +void GetIconSize(HICON hIcon, int* sizeX, int* sizeY) +{ + ICONINFO ii; + BITMAP bm; + GetIconInfo(hIcon, &ii); + GetObject(ii.hbmColor, sizeof(bm), &bm); + if (sizeX != NULL) *sizeX = bm.bmWidth; + if (sizeY != NULL) *sizeY = bm.bmHeight; + DeleteObject(ii.hbmMask); + DeleteObject(ii.hbmColor); +} + +HBITMAP LoadBmpFromIcon(HICON hIcon) +{ + HBITMAP hBmp, hoBmp; + HDC hdc, hdcMem; + HBRUSH hBkgBrush; + + int IconSizeX = 16; + int IconSizeY = 16; + + //GetIconSize(hIcon, &IconSizeX, &IconSizeY); + + //DebugLog(SynchroFile,"Icon size %i %i\n",IconSizeX,IconSizeY); + + if ((IconSizeX == 0) || (IconSizeY == 0)) + { + IconSizeX = 16; + IconSizeY = 16; + } + + RECT rc; + BITMAPINFOHEADER bih = {0}; + int widthBytes; + + hBkgBrush = CreateSolidBrush(GetSysColor(COLOR_3DFACE)); + bih.biSize = sizeof(bih); + bih.biBitCount = 24; + bih.biPlanes = 1; + bih.biCompression = BI_RGB; + bih.biHeight = IconSizeY; + bih.biWidth = IconSizeX; + widthBytes = ((bih.biWidth*bih.biBitCount + 31) >> 5) * 4; + rc.top = rc.left = 0; + rc.right = bih.biWidth; + rc.bottom = bih.biHeight; + hdc = GetDC(NULL); + hBmp = CreateCompatibleBitmap(hdc, bih.biWidth, bih.biHeight); + hdcMem = CreateCompatibleDC(hdc); + hoBmp = (HBITMAP)SelectObject(hdcMem, hBmp); + FillRect(hdcMem, &rc, hBkgBrush); + DrawIconEx(hdcMem, 0, 0, hIcon, bih.biWidth, bih.biHeight, 0, NULL, DI_NORMAL); + SelectObject(hdcMem, hoBmp); + + return hBmp; +} + +int AddTopToolbarIcon(WPARAM,LPARAM) +{ + TTBButton Button= + { + sizeof(TTBButton), + NULL, + NULL, + NULL, + MS_YAMN_FORCECHECK, + TTBBF_VISIBLE | TTBBF_SHOWTOOLTIP, // | TTBBF_DRAWBORDER, + 0,0,0,0, + NULL + }; + + if(!DBGetContactSettingByte(NULL,YAMN_DBMODULE,YAMN_TTBFCHECK,1)) + return 1; + + Button.name=Translate("Check mail"); + + Button.hbBitmapUp = LoadBmpFromIcon(hYamnIcons[5]); + Button.hbBitmapDown = LoadBmpFromIcon(hYamnIcons[6]); //LoadBitmap(YAMNVar.hInst,MAKEINTRESOURCE(IDB_BMTTB)); + + if((HANDLE)-1==(hTTButton=(HANDLE)CallService(MS_TTB_ADDBUTTON,(WPARAM)&Button,(LPARAM)0))) + return 1; + CallService(MS_TTB_SETBUTTONOPTIONS,MAKEWPARAM((WORD)TTBO_TIPNAME,(WORD)hTTButton),(LPARAM)Translate("Check mail")); + return 0; +} + +int UninstallQuestionSvc(WPARAM wParam,LPARAM) +{ +// if(strcmp((char *)wParam,Translate("Yet Another Mail Notifier"))) +// return 0; + switch(MessageBoxA(NULL,Translate("Do you also want to remove native YAMN plugins settings?"),Translate("YAMN uninstalling"),MB_YESNOCANCEL|MB_ICONQUESTION)) + { + case IDYES: + UninstallPlugins=TRUE; + break; + case IDNO: + UninstallPlugins=FALSE; + break; + case IDCANCEL: + return 1; + } + return 0; +} diff --git a/yamn/main.h b/yamn/main.h new file mode 100644 index 0000000..21923ae --- /dev/null +++ b/yamn/main.h @@ -0,0 +1,66 @@ +#ifndef __MAIN_H +#define __MAIN_H + +#ifdef __GNUC__ + #define __try + #define __except(x) if (0) /* don't execute handler */ + #define __finally + #define _try __try + #define _except __except + #define _finally __finally +#endif +//For updater +//#define YAMN_9x +#ifndef WIN2IN1 +#ifdef YAMN_9x + #define YAMN_SHORTNAME "YAMN tweety win9x" + #define YAMN_FILENAME "yamn_9x" +#else + #define YAMN_SHORTNAME "YAMN tweety" + #define YAMN_FILENAME "yamn" +#endif +#else + #define YAMN_SHORTNAME "YAMN tweety 2in1" + #define YAMN_FILENAME "yamn" +#endif //WIN2IN1 + +#include "version.h" +#define YAMN_NEWMAILSNDDESC "YAMN: new mail message" +#define YAMN_CONNECTFAILSNDDESC "YAMN: connect failed" +#define YAMN_CONNECTFAILSOUND "YAMN/Sound/ConnectFail" +#define YAMN_NEWMAILSOUND "YAMN/Sound/NewMail" + +#define YAMN_DBMODULE "YAMN" +#define YAMN_DBPOSX "MailBrowserWinX" +#define YAMN_DBPOSY "MailBrowserWinY" +#define YAMN_DBSIZEX "MailBrowserWinW" +#define YAMN_DBSIZEY "MailBrowserWinH" +#define YAMN_DBMSGPOSX "MailMessageWinX" +#define YAMN_DBMSGPOSY "MailMessageWinY" +#define YAMN_DBMSGSIZEX "MailMessageWinW" +#define YAMN_DBMSGSIZEY "MailMessageWinH" +#define YAMN_DBMSGPOSSPLIT "MailMessageSplitY" +#define YAMN_HKCHECKMAIL "HKCheckMail" +#define YAMN_TTBFCHECK "ForceCheckTTB" +#define YAMN_SHOWMAINMENU "ShowMainMenu" +#define YAMN_CLOSEDELETE "CloseOnDelete" +#define YAMN_SHOWASPROTO "ShowAsProtcol" +#define YAMN_DBTIMEOPTIONS "MailBrowserTimeOpts" + +#define YAMN_DEFAULTHK MAKEWORD(VK_F12,MOD_CONTROL) + +#define SHOWDATELONG 0x01 +#define SHOWDATENOTODAY 0x02 +#define SHOWDATENOSECONDS 0x04 + +extern unsigned char optDateTime; + +void UnloadPlugins(); + +// Loading Icon and checking for icolib +void LoadIcons(); +extern int iconIndexes[]; + + +#endif + diff --git a/yamn/mingw/base.dev b/yamn/mingw/base.dev new file mode 100644 index 0000000..42e2fab --- /dev/null +++ b/yamn/mingw/base.dev @@ -0,0 +1,69 @@ +[Project] +FileName=base.dev +Name=base +Ver=1 +IsCpp=1 +Type=3 +Compiler=-D__GNUWIN32__ -mcpu=i486 -D_M_IX86=400 -W -fno-inline -DWIN32 -DNDEBUG -D_WINDOWS_@@_ +CppCompiler=-D__GNUWIN32__ -mcpu=i486 -D_M_IX86=400 -W -fno-inline -DWIN32 -DNDEBUG -D_WINDOWS_@@_ +Includes=../../../include +Linker=-lkernel32 -luser32_@@_ +Libs= +UnitCount=2 +Folders="Header Files","Resource Files","Source Files" +ObjFiles= +PrivateResource= +ResourceIncludes= +MakeIncludes= +Icon= +ExeOutput=binfilter +ObjectOutput=objbase +OverrideOutput=0 +OverrideOutputName=base.dll +HostApplication= +CommandLine= +UseCustomMakefile=1 +CustomMakefile=base.win +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0010000001001000000100 + +[Unit1] +FileName=..\filter\base\maindll.cpp +Folder="Source Files" +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit2] +FileName=..\filter\base\debug.cpp +Folder="Source Files" +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion=0.1 +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename=base.dll +ProductName=base +ProductVersion=0.1 +AutoIncBuildNr=0 + diff --git a/yamn/mingw/base.win b/yamn/mingw/base.win new file mode 100644 index 0000000..3af9e7a --- /dev/null +++ b/yamn/mingw/base.win @@ -0,0 +1,38 @@ +# Project: base +# Makefile created by Dev-C++ 4.9.9.2 + +CPP = g++.exe +CC = gcc.exe +WINDRES = windres.exe +RES = +OBJ = objbase/maindll.o objbase/debug.o $(RES) +LINKOBJ = objbase/maindll.o objbase/debug.o $(RES) +LIBS = -lkernel32 -luser32 -s +INCS = -I"../../../include" +CXXINCS = -I"../../../include" +BIN = binfilter/base.dll +CXXFLAGS = $(CXXINCS) -D__GNUWIN32__ -W -fno-inline -DWIN32 -DNDEBUG -D_WINDOWS -w -fweb -frename-registers -Os +CFLAGS = $(INCS) -D__GNUWIN32__ -W -fno-inline -DWIN32 -DNDEBUG -D_WINDOWS -w -fweb -frename-registers -Os +RM = rm -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before binfilter/base.dll all-after + + +clean: clean-custom + ${RM} $(OBJ) $(BIN) + +DLLWRAP=dllwrap.exe +DEFFILE=objbase/libbase.def +STATICLIB=objbase/libbase.a + +$(BIN): $(LINKOBJ) +# $(DLLWRAP) --output-def $(DEFFILE) --driver-name c++ --implib $(STATICLIB) $(LINKOBJ) $(LIBS) -o $(BIN) + $(CPP) $(LINKOBJ) $(LIBS) -o $(BIN) -mdll + +objbase/maindll.o: ../filter/base/maindll.cpp + $(CPP) -c ../filter/base/maindll.cpp -o objbase/maindll.o $(CXXFLAGS) + +objbase/debug.o: ../filter/base/debug.cpp + $(CPP) -c ../filter/base/debug.cpp -o objbase/debug.o $(CXXFLAGS) diff --git a/yamn/mingw/simple.dev b/yamn/mingw/simple.dev new file mode 100644 index 0000000..617324b --- /dev/null +++ b/yamn/mingw/simple.dev @@ -0,0 +1,59 @@ +[Project] +FileName=simple.dev +Name=simple +Ver=1 +IsCpp=1 +Type=3 +Compiler=-D__GNUWIN32__ -mcpu=i486 -D_M_IX86=400 -W -fno-inline -DWIN32 -DNDEBUG -D_WINDOWS_@@_ +CppCompiler=-D__GNUWIN32__ -mcpu=i486 -D_M_IX86=400 -W -fno-inline -DWIN32 -DNDEBUG -D_WINDOWS_@@_ +Includes=../../../include +Linker=-lkernel32 -luser32_@@_ +Libs= +UnitCount=1 +Folders="Header Files","Resource Files","Source Files" +ObjFiles= +PrivateResource= +ResourceIncludes= +MakeIncludes= +Icon= +ExeOutput=binfilter +ObjectOutput=objsimple +OverrideOutput=0 +OverrideOutputName=simple.dll +HostApplication= +CommandLine= +UseCustomMakefile=1 +CustomMakefile=simple.win +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0010000001001000000100 + +[Unit1] +FileName=..\filter\Simple\maindll.cpp +Folder="Source Files" +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion=0.1 +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename=simple.dll +ProductName=simple +ProductVersion=0.1 +AutoIncBuildNr=0 + diff --git a/yamn/mingw/simple.win b/yamn/mingw/simple.win new file mode 100644 index 0000000..fc9e3c6 --- /dev/null +++ b/yamn/mingw/simple.win @@ -0,0 +1,35 @@ +# Project: simple +# Makefile created by Dev-C++ 4.9.9.2 + +CPP = g++.exe +CC = gcc.exe +WINDRES = windres.exe +RES = +OBJ = objsimple/maindll.o $(RES) +LINKOBJ = objsimple/maindll.o $(RES) +LIBS = -lkernel32 -luser32 -s +INCS = -I"../../../include" +CXXINCS = -I"../../../include" +BIN = binfilter/simple.dll +CXXFLAGS = $(CXXINCS) -D__GNUWIN32__ -W -fno-inline -DWIN32 -DNDEBUG -D_WINDOWS -w -fweb -frename-registers -Os +CFLAGS = $(INCS) -D__GNUWIN32__ -W -fno-inline -DWIN32 -DNDEBUG -D_WINDOWS -w -fweb -frename-registers -Os +RM = rm -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before binfilter/simple.dll all-after + + +clean: clean-custom + ${RM} $(OBJ) $(BIN) + +DLLWRAP=dllwrap.exe +DEFFILE=objsimple/libsimple.def +STATICLIB=objsimple/libsimple.a + +$(BIN): $(LINKOBJ) +# $(DLLWRAP) --output-def $(DEFFILE) --driver-name c++ --implib $(STATICLIB) $(LINKOBJ) $(LIBS) -o $(BIN) + $(CPP) $(LINKOBJ) $(LIBS) -o $(BIN) -mdll + +objsimple/maindll.o: ../filter/Simple/maindll.cpp + $(CPP) -c ../filter/Simple/maindll.cpp -o objsimple/maindll.o $(CXXFLAGS) diff --git a/yamn/mingw/yamn-2in1.dev b/yamn/mingw/yamn-2in1.dev new file mode 100644 index 0000000..615e63f --- /dev/null +++ b/yamn/mingw/yamn-2in1.dev @@ -0,0 +1,469 @@ +[Project] +FileName=yamn-2in1.dev +Name=YAMN +Ver=1 +IsCpp=1 +Type=3 +Compiler=-D__GNUWIN32__ -W -DWIN32 -DNDEBUG -D_WINDOWS -DWIN2IN1 +CppCompiler=-D__GNUWIN32__ -W -DWIN32 -DNDEBUG -D_WINDOWS -DWIN2IN1 +Includes=../../../include +Linker=-lunicows -lkernel32 -luser32 -lshell32 -lmsvcrt -lcomctl32 -lcomdlg32 -lgdi32 -lwsock32 --image-base "0x60010000" +Libs=../libs +UnitCount=36 +Folders=Documentation,"Resource Files",YAMN,YAMN/Header,YAMN/include,"YAMN/Mail browser, dialogs",YAMN/Mails,"YAMN/POP3 plugin" +ObjFiles= +PrivateResource=YAMN_private.rc +ResourceIncludes=../resources +MakeIncludes= +Icon= +ExeOutput=bin2in1 +ObjectOutput=objs2in1 +OverrideOutput=1 +OverrideOutputName=YAMN.dll +HostApplication= +CommandLine= +UseCustomMakefile=1 +CustomMakefile=yamn-2in1.win +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0010000001001000000100 + +[Unit1] +FileName=..\browser\badconnect.cpp +Folder=YAMN/Mail browser, dialogs +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit2] +FileName=..\browser\mailbrowser.cpp +Folder=YAMN/Mail browser, dialogs +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=..\mails\decode.cpp +Folder=YAMN/Mails +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=..\mails\mails.cpp +Folder=YAMN/Mails +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=..\mails\mime.cpp +Folder=YAMN/Mails +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=..\proto\md5.c +Folder=YAMN/POP3 plugin +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=..\proto\netlib.cpp +Folder=YAMN/POP3 plugin +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit8] +FileName=..\proto\pop3\pop3.cpp +Folder=YAMN/POP3 plugin +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit9] +FileName=..\proto\pop3\pop3comm.cpp +Folder=YAMN/POP3 plugin +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit10] +FileName=..\proto\pop3\pop3opt.cpp +Folder=YAMN/POP3 plugin +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit11] +FileName=..\proto\ssl.cpp +Folder=YAMN/POP3 plugin +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit12] +FileName=..\debug.h +Folder=YAMN/Header +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit13] +FileName=..\main.h +Folder=YAMN/Header +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit14] +FileName=..\proto\pop3\pop3.h +Folder=YAMN/Header +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit15] +FileName=..\proto\pop3\pop3comm.h +Folder=YAMN/Header +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit16] +FileName=..\proto\pop3\pop3opt.h +Folder=YAMN/Header +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit17] +FileName=..\yamn.h +Folder=YAMN/Header +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit18] +FileName=..\include\m_kbdnotify.h +Folder=YAMN/include +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit19] +FileName=..\include\m_popup.h +Folder=YAMN/include +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit20] +FileName=..\include\m_toptoolbar.h +Folder=YAMN/include +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit21] +FileName=..\include\m_uninstaller.h +Folder=YAMN/include +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit22] +FileName=..\include\m_updater.h +Folder=YAMN/include +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit23] +FileName=..\account.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit24] +FileName=..\ChangeLog.txt +Folder=Documentation +Compile=0 +CompileCpp=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit25] +FileName=..\debug.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit26] +FileName=..\filterplugin.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit27] +FileName=..\main.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit28] +FileName=..\protoplugin.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit29] +FileName=..\services.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit30] +FileName=..\synchro.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit31] +FileName=..\yamn.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit32] +FileName=..\resources\ttbfcheck.bmp +Folder=Resource Files +Compile=0 +CompileCpp=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit33] +FileName=..\resources\YAMN.rc +Folder=Resource Files +Compile=1 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit34] +FileName=..\docs\language.pop3.txt +Folder=Documentation +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit35] +FileName=..\docs\language.txt +Folder=Documentation +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit36] +FileName=..\m_messages.h +Folder=YAMN/include +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit37] +FileName=..\resources\icoyamn2.ico +Folder=Resource Files +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit38] +FileName=..\resources\icoyamn3.ico +Folder=Resource Files +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit39] +FileName=..\resources\ttbfcheck.bmp +Folder=Resource Files +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit40] +FileName=..\resources\YAMN.rc +Folder=Resource Files +Compile=1 +CompileCpp=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit41] +FileName=..\docs\language.pop3.txt +Folder=Documentation +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit42] +FileName=..\docs\language.txt +Folder=Documentation +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion=0.1 +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename=YAMN.exe +ProductName=YAMN +ProductVersion=0.1 +AutoIncBuildNr=0 + diff --git a/yamn/mingw/yamn-2in1.win b/yamn/mingw/yamn-2in1.win new file mode 100644 index 0000000..5b90f86 --- /dev/null +++ b/yamn/mingw/yamn-2in1.win @@ -0,0 +1,92 @@ +# Project: YAMN +# Makefile created by Dev-C++ 4.9.9.2 + +CPP = g++.exe +CC = gcc.exe +WINDRES = windres.exe +RES = objs2in1/YAMN.res +OBJ = objs2in1/badconnect.o objs2in1/mailbrowser.o objs2in1/decode.o objs2in1/mails.o objs2in1/mime.o objs2in1/md5.o objs2in1/netlib.o objs2in1/pop3.o objs2in1/pop3comm.o objs2in1/pop3opt.o objs2in1/ssl.o objs2in1/account.o objs2in1/debug.o objs2in1/filterplugin.o objs2in1/main.o objs2in1/protoplugin.o objs2in1/services.o objs2in1/synchro.o objs2in1/yamn.o $(RES) +LINKOBJ = objs2in1/badconnect.o objs2in1/mailbrowser.o objs2in1/decode.o objs2in1/mails.o objs2in1/mime.o objs2in1/md5.o objs2in1/netlib.o objs2in1/pop3.o objs2in1/pop3comm.o objs2in1/pop3opt.o objs2in1/ssl.o objs2in1/account.o objs2in1/debug.o objs2in1/filterplugin.o objs2in1/main.o objs2in1/protoplugin.o objs2in1/services.o objs2in1/synchro.o objs2in1/yamn.o $(RES) +LIBS = -L"../libs" -lunicows -lkernel32 -luser32 -lshell32 -lmsvcrt -lcomctl32 -lcomdlg32 -lgdi32 -lwsock32 -s +INCS = -I"../../../include" +CXXINCS = -I"../../../include" +BIN = bin2in1/yamn.dll +CXXFLAGS = $(CXXINCS) -D__GNUWIN32__ -W -fno-inline -DWIN32 -DNDEBUG -D_WINDOWS -DWIN2IN1 -w -fweb -frename-registers -Os +CFLAGS = $(INCS) -D__GNUWIN32__ -W -fno-inline -DWIN32 -DNDEBUG -D_WINDOWS -DWIN2IN1 -w -fweb -frename-registers -Os +RM = rm -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before bin2in1/yamn.dll all-after + + +clean: clean-custom + ${RM} $(OBJ) $(BIN) + +DLLWRAP=dllwrap.exe +DEFFILE=bin2in1/libYAMN.def +STATICLIB=bin2in1/libYAMN.a + +$(BIN): $(LINKOBJ) +# $(DLLWRAP) --output-def $(DEFFILE) --driver-name c++ --implib $(STATICLIB) $(LINKOBJ) $(LIBS) -o $(BIN) + $(CPP) $(LINKOBJ) $(LIBS) -o $(BIN) -mdll + +objs2in1/badconnect.o: ../browser/badconnect.cpp + $(CPP) -c ../browser/badconnect.cpp -o objs2in1/badconnect.o $(CXXFLAGS) + +objs2in1/mailbrowser.o: ../browser/mailbrowser.cpp + $(CPP) -c ../browser/mailbrowser.cpp -o objs2in1/mailbrowser.o $(CXXFLAGS) + +objs2in1/decode.o: ../mails/decode.cpp + $(CPP) -c ../mails/decode.cpp -o objs2in1/decode.o $(CXXFLAGS) + +objs2in1/mails.o: ../mails/mails.cpp + $(CPP) -c ../mails/mails.cpp -o objs2in1/mails.o $(CXXFLAGS) + +objs2in1/mime.o: ../mails/mime.cpp + $(CPP) -c ../mails/mime.cpp -o objs2in1/mime.o $(CXXFLAGS) + +objs2in1/md5.o: ../proto/md5.c + $(CC) -c ../proto/md5.c -o objs2in1/md5.o $(CFLAGS) + +objs2in1/netlib.o: ../proto/netlib.cpp + $(CPP) -c ../proto/netlib.cpp -o objs2in1/netlib.o $(CXXFLAGS) + +objs2in1/pop3.o: ../proto/pop3/pop3.cpp + $(CPP) -c ../proto/pop3/pop3.cpp -o objs2in1/pop3.o $(CXXFLAGS) + +objs2in1/pop3comm.o: ../proto/pop3/pop3comm.cpp + $(CPP) -c ../proto/pop3/pop3comm.cpp -o objs2in1/pop3comm.o $(CXXFLAGS) + +objs2in1/pop3opt.o: ../proto/pop3/pop3opt.cpp + $(CPP) -c ../proto/pop3/pop3opt.cpp -o objs2in1/pop3opt.o $(CXXFLAGS) + +objs2in1/ssl.o: ../proto/ssl.cpp + $(CPP) -c ../proto/ssl.cpp -o objs2in1/ssl.o $(CXXFLAGS) + +objs2in1/account.o: ../account.cpp + $(CPP) -c ../account.cpp -o objs2in1/account.o $(CXXFLAGS) + +objs2in1/debug.o: ../debug.cpp + $(CPP) -c ../debug.cpp -o objs2in1/debug.o $(CXXFLAGS) + +objs2in1/filterplugin.o: ../filterplugin.cpp + $(CPP) -c ../filterplugin.cpp -o objs2in1/filterplugin.o $(CXXFLAGS) + +objs2in1/main.o: ../main.cpp + $(CPP) -c ../main.cpp -o objs2in1/main.o $(CXXFLAGS) + +objs2in1/protoplugin.o: ../protoplugin.cpp + $(CPP) -c ../protoplugin.cpp -o objs2in1/protoplugin.o $(CXXFLAGS) + +objs2in1/services.o: ../services.cpp + $(CPP) -c ../services.cpp -o objs2in1/services.o $(CXXFLAGS) + +objs2in1/synchro.o: ../synchro.cpp + $(CPP) -c ../synchro.cpp -o objs2in1/synchro.o $(CXXFLAGS) + +objs2in1/yamn.o: ../yamn.cpp + $(CPP) -c ../yamn.cpp -o objs2in1/yamn.o $(CXXFLAGS) + +objs2in1/YAMN.res: ../resources/YAMN.rc + $(WINDRES) -i ../resources/YAMN.rc --input-format=rc -o objs2in1/YAMN.res -O coff --include-dir ../resources diff --git a/yamn/mingw/yamn-w9x.dev b/yamn/mingw/yamn-w9x.dev new file mode 100644 index 0000000..b652000 --- /dev/null +++ b/yamn/mingw/yamn-w9x.dev @@ -0,0 +1,469 @@ +[Project] +FileName=yamn-w9x.dev +Name=YAMN +Ver=1 +IsCpp=1 +Type=3 +Compiler=-D__GNUWIN32__ -W -DWIN32 -DNDEBUG -D_WINDOWS -DWIN9X +CppCompiler=-D__GNUWIN32__ -W -DWIN32 -DNDEBUG -D_WINDOWS -DWIN9X +Includes=../../../include +Linker=-lunicows -lkernel32 -luser32 -lshell32 -lmsvcrt -lcomctl32 -lcomdlg32 -lgdi32 -lwsock32 --image-base "0x60010000" +Libs=../libs +UnitCount=36 +Folders=Documentation,"Resource Files",YAMN,YAMN/Header,YAMN/include,"YAMN/Mail browser, dialogs",YAMN/Mails,"YAMN/POP3 plugin" +ObjFiles= +PrivateResource=YAMN_private.rc +ResourceIncludes=../resources +MakeIncludes= +Icon= +ExeOutput=bin9x +ObjectOutput=objs9x +OverrideOutput=1 +OverrideOutputName=YAMN.dll +HostApplication= +CommandLine= +UseCustomMakefile=1 +CustomMakefile=yamn-w9x.win +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0010000001001000000100 + +[Unit1] +FileName=..\browser\badconnect.cpp +Folder=YAMN/Mail browser, dialogs +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit2] +FileName=..\browser\mailbrowser.cpp +Folder=YAMN/Mail browser, dialogs +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=..\mails\decode.cpp +Folder=YAMN/Mails +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=..\mails\mails.cpp +Folder=YAMN/Mails +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=..\mails\mime.cpp +Folder=YAMN/Mails +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=..\proto\md5.c +Folder=YAMN/POP3 plugin +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=..\proto\netlib.cpp +Folder=YAMN/POP3 plugin +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit8] +FileName=..\proto\pop3\pop3.cpp +Folder=YAMN/POP3 plugin +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit9] +FileName=..\proto\pop3\pop3comm.cpp +Folder=YAMN/POP3 plugin +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit10] +FileName=..\proto\pop3\pop3opt.cpp +Folder=YAMN/POP3 plugin +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit11] +FileName=..\proto\ssl.cpp +Folder=YAMN/POP3 plugin +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit12] +FileName=..\debug.h +Folder=YAMN/Header +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit13] +FileName=..\main.h +Folder=YAMN/Header +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit14] +FileName=..\proto\pop3\pop3.h +Folder=YAMN/Header +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit15] +FileName=..\proto\pop3\pop3comm.h +Folder=YAMN/Header +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit16] +FileName=..\proto\pop3\pop3opt.h +Folder=YAMN/Header +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit17] +FileName=..\yamn.h +Folder=YAMN/Header +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit18] +FileName=..\include\m_kbdnotify.h +Folder=YAMN/include +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit19] +FileName=..\include\m_popup.h +Folder=YAMN/include +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit20] +FileName=..\include\m_toptoolbar.h +Folder=YAMN/include +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit21] +FileName=..\include\m_uninstaller.h +Folder=YAMN/include +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit22] +FileName=..\include\m_updater.h +Folder=YAMN/include +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit23] +FileName=..\account.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit24] +FileName=..\ChangeLog.txt +Folder=Documentation +Compile=0 +CompileCpp=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit25] +FileName=..\debug.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit26] +FileName=..\filterplugin.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit27] +FileName=..\main.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit28] +FileName=..\protoplugin.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit29] +FileName=..\services.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit30] +FileName=..\synchro.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit31] +FileName=..\yamn.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit32] +FileName=..\resources\ttbfcheck.bmp +Folder=Resource Files +Compile=0 +CompileCpp=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit33] +FileName=..\resources\YAMN.rc +Folder=Resource Files +Compile=1 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit34] +FileName=..\docs\language.pop3.txt +Folder=Documentation +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit35] +FileName=..\docs\language.txt +Folder=Documentation +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit36] +FileName=..\m_messages.h +Folder=YAMN/include +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit37] +FileName=..\resources\icoyamn2.ico +Folder=Resource Files +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit38] +FileName=..\resources\icoyamn3.ico +Folder=Resource Files +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit39] +FileName=..\resources\ttbfcheck.bmp +Folder=Resource Files +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit40] +FileName=..\resources\YAMN.rc +Folder=Resource Files +Compile=1 +CompileCpp=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit41] +FileName=..\docs\language.pop3.txt +Folder=Documentation +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit42] +FileName=..\docs\language.txt +Folder=Documentation +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion=0.1 +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename=YAMN.exe +ProductName=YAMN +ProductVersion=0.1 +AutoIncBuildNr=0 + diff --git a/yamn/mingw/yamn-w9x.win b/yamn/mingw/yamn-w9x.win new file mode 100644 index 0000000..0e741d5 --- /dev/null +++ b/yamn/mingw/yamn-w9x.win @@ -0,0 +1,92 @@ +# Project: YAMN +# Makefile created by Dev-C++ 4.9.9.2 + +CPP = g++.exe +CC = gcc.exe +WINDRES = windres.exe +RES = objs9x/YAMN.res +OBJ = objs9x/badconnect.o objs9x/mailbrowser.o objs9x/decode.o objs9x/mails.o objs9x/mime.o objs9x/md5.o objs9x/netlib.o objs9x/pop3.o objs9x/pop3comm.o objs9x/pop3opt.o objs9x/ssl.o objs9x/account.o objs9x/debug.o objs9x/filterplugin.o objs9x/main.o objs9x/protoplugin.o objs9x/services.o objs9x/synchro.o objs9x/yamn.o $(RES) +LINKOBJ = objs9x/badconnect.o objs9x/mailbrowser.o objs9x/decode.o objs9x/mails.o objs9x/mime.o objs9x/md5.o objs9x/netlib.o objs9x/pop3.o objs9x/pop3comm.o objs9x/pop3opt.o objs9x/ssl.o objs9x/account.o objs9x/debug.o objs9x/filterplugin.o objs9x/main.o objs9x/protoplugin.o objs9x/services.o objs9x/synchro.o objs9x/yamn.o $(RES) +LIBS = -L"../libs" -lunicows -lkernel32 -luser32 -lshell32 -lmsvcrt -lcomctl32 -lcomdlg32 -lgdi32 -lwsock32 -s +INCS = -I"../../../include" +CXXINCS = -I"../../../include" +BIN = bin9x/yamn.dll +CXXFLAGS = $(CXXINCS) -D__GNUWIN32__ -W -DWIN32 -DNDEBUG -D_WINDOWS -DWIN9X -w -fweb -frename-registers -Os +CFLAGS = $(INCS) -D__GNUWIN32__ -W -DWIN32 -DNDEBUG -D_WINDOWS -DWIN9X -w -fweb -frename-registers -Os +RM = rm -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before bin9x/yamn.dll all-after + + +clean: clean-custom + ${RM} $(OBJ) $(BIN) + +DLLWRAP=dllwrap.exe +DEFFILE=bin9x/libYAMN.def +STATICLIB=bin9x/libYAMN.a + +$(BIN): $(LINKOBJ) +# $(DLLWRAP) --output-def $(DEFFILE) --driver-name c++ --implib $(STATICLIB) $(LINKOBJ) $(LIBS) -o $(BIN) + $(CPP) $(LINKOBJ) $(LIBS) -o $(BIN) -mdll + +objs9x/badconnect.o: ../browser/badconnect.cpp + $(CPP) -c ../browser/badconnect.cpp -o objs9x/badconnect.o $(CXXFLAGS) + +objs9x/mailbrowser.o: ../browser/mailbrowser.cpp + $(CPP) -c ../browser/mailbrowser.cpp -o objs9x/mailbrowser.o $(CXXFLAGS) + +objs9x/decode.o: ../mails/decode.cpp + $(CPP) -c ../mails/decode.cpp -o objs9x/decode.o $(CXXFLAGS) + +objs9x/mails.o: ../mails/mails.cpp + $(CPP) -c ../mails/mails.cpp -o objs9x/mails.o $(CXXFLAGS) + +objs9x/mime.o: ../mails/mime.cpp + $(CPP) -c ../mails/mime.cpp -o objs9x/mime.o $(CXXFLAGS) + +objs9x/md5.o: ../proto/md5.c + $(CC) -c ../proto/md5.c -o objs9x/md5.o $(CFLAGS) + +objs9x/netlib.o: ../proto/netlib.cpp + $(CPP) -c ../proto/netlib.cpp -o objs9x/netlib.o $(CXXFLAGS) + +objs9x/pop3.o: ../proto/pop3/pop3.cpp + $(CPP) -c ../proto/pop3/pop3.cpp -o objs9x/pop3.o $(CXXFLAGS) + +objs9x/pop3comm.o: ../proto/pop3/pop3comm.cpp + $(CPP) -c ../proto/pop3/pop3comm.cpp -o objs9x/pop3comm.o $(CXXFLAGS) + +objs9x/pop3opt.o: ../proto/pop3/pop3opt.cpp + $(CPP) -c ../proto/pop3/pop3opt.cpp -o objs9x/pop3opt.o $(CXXFLAGS) + +objs9x/ssl.o: ../proto/ssl.cpp + $(CPP) -c ../proto/ssl.cpp -o objs9x/ssl.o $(CXXFLAGS) + +objs9x/account.o: ../account.cpp + $(CPP) -c ../account.cpp -o objs9x/account.o $(CXXFLAGS) + +objs9x/debug.o: ../debug.cpp + $(CPP) -c ../debug.cpp -o objs9x/debug.o $(CXXFLAGS) + +objs9x/filterplugin.o: ../filterplugin.cpp + $(CPP) -c ../filterplugin.cpp -o objs9x/filterplugin.o $(CXXFLAGS) + +objs9x/main.o: ../main.cpp + $(CPP) -c ../main.cpp -o objs9x/main.o $(CXXFLAGS) + +objs9x/protoplugin.o: ../protoplugin.cpp + $(CPP) -c ../protoplugin.cpp -o objs9x/protoplugin.o $(CXXFLAGS) + +objs9x/services.o: ../services.cpp + $(CPP) -c ../services.cpp -o objs9x/services.o $(CXXFLAGS) + +objs9x/synchro.o: ../synchro.cpp + $(CPP) -c ../synchro.cpp -o objs9x/synchro.o $(CXXFLAGS) + +objs9x/yamn.o: ../yamn.cpp + $(CPP) -c ../yamn.cpp -o objs9x/yamn.o $(CXXFLAGS) + +objs9x/YAMN.res: ../resources/YAMN.rc + $(WINDRES) -i ../resources/YAMN.rc --input-format=rc -o objs9x/YAMN.res -O coff --include-dir ../resources diff --git a/yamn/mingw/yamn.dev b/yamn/mingw/yamn.dev new file mode 100644 index 0000000..d726894 --- /dev/null +++ b/yamn/mingw/yamn.dev @@ -0,0 +1,469 @@ +[Project] +FileName=yamn.dev +Name=YAMN +Ver=1 +IsCpp=1 +Type=3 +Compiler=-D__GNUWIN32__ -W -DWIN32 -DNDEBUG -D_WINDOWS +CppCompiler=-D__GNUWIN32__ -W -DWIN32 -DNDEBUG -D_WINDOWS +Includes=../../../include +Linker=-lkernel32 -luser32 -lshell32 -lmsvcrt -lcomctl32 -lcomdlg32 -lgdi32 -lwsock32 --image-base "0x60010000" +Libs= +UnitCount=36 +Folders=Documentation,"Resource Files",YAMN,YAMN/Header,YAMN/include,"YAMN/Mail browser, dialogs",YAMN/Mails,"YAMN/POP3 plugin" +ObjFiles= +PrivateResource=YAMN_private.rc +ResourceIncludes=../resources +MakeIncludes= +Icon= +ExeOutput=bin +ObjectOutput=objs +OverrideOutput=0 +OverrideOutputName=YAMN.dll +HostApplication= +CommandLine= +UseCustomMakefile=1 +CustomMakefile=yamn.win +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000001001000000100 + +[Unit1] +FileName=..\browser\badconnect.cpp +Folder=YAMN/Mail browser, dialogs +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit2] +FileName=..\browser\mailbrowser.cpp +Folder=YAMN/Mail browser, dialogs +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=..\mails\decode.cpp +Folder=YAMN/Mails +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=..\mails\mails.cpp +Folder=YAMN/Mails +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=..\mails\mime.cpp +Folder=YAMN/Mails +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=..\proto\md5.c +Folder=YAMN/POP3 plugin +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=..\proto\netlib.cpp +Folder=YAMN/POP3 plugin +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit8] +FileName=..\proto\pop3\pop3.cpp +Folder=YAMN/POP3 plugin +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit9] +FileName=..\proto\pop3\pop3comm.cpp +Folder=YAMN/POP3 plugin +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit10] +FileName=..\proto\pop3\pop3opt.cpp +Folder=YAMN/POP3 plugin +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit11] +FileName=..\proto\ssl.cpp +Folder=YAMN/POP3 plugin +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit12] +FileName=..\debug.h +Folder=YAMN/Header +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit13] +FileName=..\main.h +Folder=YAMN/Header +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit14] +FileName=..\proto\pop3\pop3.h +Folder=YAMN/Header +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit15] +FileName=..\proto\pop3\pop3comm.h +Folder=YAMN/Header +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit16] +FileName=..\proto\pop3\pop3opt.h +Folder=YAMN/Header +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit17] +FileName=..\yamn.h +Folder=YAMN/Header +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit18] +FileName=..\include\m_kbdnotify.h +Folder=YAMN/include +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit19] +FileName=..\include\m_popup.h +Folder=YAMN/include +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit20] +FileName=..\include\m_toptoolbar.h +Folder=YAMN/include +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit21] +FileName=..\include\m_uninstaller.h +Folder=YAMN/include +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit22] +FileName=..\include\m_updater.h +Folder=YAMN/include +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit23] +FileName=..\account.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit24] +FileName=..\ChangeLog.txt +Folder=Documentation +Compile=0 +CompileCpp=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit25] +FileName=..\debug.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit26] +FileName=..\filterplugin.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit27] +FileName=..\main.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit28] +FileName=..\protoplugin.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit29] +FileName=..\services.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit30] +FileName=..\synchro.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit31] +FileName=..\yamn.cpp +Folder=YAMN +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit32] +FileName=..\resources\ttbfcheck.bmp +Folder=Resource Files +Compile=0 +CompileCpp=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit33] +FileName=..\resources\YAMN.rc +Folder=Resource Files +Compile=1 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit34] +FileName=..\docs\language.pop3.txt +Folder=Documentation +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit35] +FileName=..\docs\language.txt +Folder=Documentation +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit36] +FileName=..\m_messages.h +Folder=YAMN/include +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit37] +FileName=..\resources\icoyamn2.ico +Folder=Resource Files +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit38] +FileName=..\resources\icoyamn3.ico +Folder=Resource Files +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit39] +FileName=..\resources\ttbfcheck.bmp +Folder=Resource Files +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit40] +FileName=..\resources\YAMN.rc +Folder=Resource Files +Compile=1 +CompileCpp=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit41] +FileName=..\docs\language.pop3.txt +Folder=Documentation +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit42] +FileName=..\docs\language.txt +Folder=Documentation +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion=0.1 +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename=YAMN.exe +ProductName=YAMN +ProductVersion=0.1 +AutoIncBuildNr=0 + diff --git a/yamn/mingw/yamn.win b/yamn/mingw/yamn.win new file mode 100644 index 0000000..d396e45 --- /dev/null +++ b/yamn/mingw/yamn.win @@ -0,0 +1,92 @@ +# Project: YAMN +# Makefile created by Dev-C++ 4.9.9.2 + +CPP = g++.exe +CC = gcc.exe +WINDRES = windres.exe +RES = objs/YAMN.res +OBJ = objs/badconnect.o objs/mailbrowser.o objs/decode.o objs/mails.o objs/mime.o objs/md5.o objs/netlib.o objs/pop3.o objs/pop3comm.o objs/pop3opt.o objs/ssl.o objs/account.o objs/debug.o objs/filterplugin.o objs/main.o objs/protoplugin.o objs/services.o objs/synchro.o objs/yamn.o $(RES) +LINKOBJ = objs/badconnect.o objs/mailbrowser.o objs/decode.o objs/mails.o objs/mime.o objs/md5.o objs/netlib.o objs/pop3.o objs/pop3comm.o objs/pop3opt.o objs/ssl.o objs/account.o objs/debug.o objs/filterplugin.o objs/main.o objs/protoplugin.o objs/services.o objs/synchro.o objs/yamn.o $(RES) +LIBS = -lkernel32 -luser32 -lshell32 -lmsvcrt -lcomctl32 -lcomdlg32 -lgdi32 -lwsock32 -s +INCS = -I"../../../include" +CXXINCS = -I"../../../include" +BIN = bin/yamn.dll +CXXFLAGS = $(CXXINCS) -D__GNUWIN32__ -W -DWIN32 -DNDEBUG -D_WINDOWS -w -fweb -frename-registers -Os +CFLAGS = $(INCS) -D__GNUWIN32__ -W -DWIN32 -DNDEBUG -D_WINDOWS -w -fweb -frename-registers -Os +RM = rm -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before bin/yamn.dll all-after + + +clean: clean-custom + ${RM} $(OBJ) $(BIN) + +DLLWRAP=dllwrap.exe +DEFFILE=bin/libyamn.def +STATICLIB=bin/libyamn.a + +$(BIN): $(LINKOBJ) +# $(DLLWRAP) --output-def $(DEFFILE) --driver-name c++ --implib $(STATICLIB) $(LINKOBJ) $(LIBS) -o $(BIN) + $(CPP) $(LINKOBJ) $(LIBS) -o $(BIN) -mdll + +objs/badconnect.o: ../browser/badconnect.cpp + $(CPP) -c ../browser/badconnect.cpp -o objs/badconnect.o $(CXXFLAGS) + +objs/mailbrowser.o: ../browser/mailbrowser.cpp + $(CPP) -c ../browser/mailbrowser.cpp -o objs/mailbrowser.o $(CXXFLAGS) + +objs/decode.o: ../mails/decode.cpp + $(CPP) -c ../mails/decode.cpp -o objs/decode.o $(CXXFLAGS) + +objs/mails.o: ../mails/mails.cpp + $(CPP) -c ../mails/mails.cpp -o objs/mails.o $(CXXFLAGS) + +objs/mime.o: ../mails/mime.cpp + $(CPP) -c ../mails/mime.cpp -o objs/mime.o $(CXXFLAGS) + +objs/md5.o: ../proto/md5.c + $(CC) -c ../proto/md5.c -o objs/md5.o $(CFLAGS) + +objs/netlib.o: ../proto/netlib.cpp + $(CPP) -c ../proto/netlib.cpp -o objs/netlib.o $(CXXFLAGS) + +objs/pop3.o: ../proto/pop3/pop3.cpp + $(CPP) -c ../proto/pop3/pop3.cpp -o objs/pop3.o $(CXXFLAGS) + +objs/pop3comm.o: ../proto/pop3/pop3comm.cpp + $(CPP) -c ../proto/pop3/pop3comm.cpp -o objs/pop3comm.o $(CXXFLAGS) + +objs/pop3opt.o: ../proto/pop3/pop3opt.cpp + $(CPP) -c ../proto/pop3/pop3opt.cpp -o objs/pop3opt.o $(CXXFLAGS) + +objs/ssl.o: ../proto/ssl.cpp + $(CPP) -c ../proto/ssl.cpp -o objs/ssl.o $(CXXFLAGS) + +objs/account.o: ../account.cpp + $(CPP) -c ../account.cpp -o objs/account.o $(CXXFLAGS) + +objs/debug.o: ../debug.cpp + $(CPP) -c ../debug.cpp -o objs/debug.o $(CXXFLAGS) + +objs/filterplugin.o: ../filterplugin.cpp + $(CPP) -c ../filterplugin.cpp -o objs/filterplugin.o $(CXXFLAGS) + +objs/main.o: ../main.cpp + $(CPP) -c ../main.cpp -o objs/main.o $(CXXFLAGS) + +objs/protoplugin.o: ../protoplugin.cpp + $(CPP) -c ../protoplugin.cpp -o objs/protoplugin.o $(CXXFLAGS) + +objs/services.o: ../services.cpp + $(CPP) -c ../services.cpp -o objs/services.o $(CXXFLAGS) + +objs/synchro.o: ../synchro.cpp + $(CPP) -c ../synchro.cpp -o objs/synchro.o $(CXXFLAGS) + +objs/yamn.o: ../yamn.cpp + $(CPP) -c ../yamn.cpp -o objs/yamn.o $(CXXFLAGS) + +objs/YAMN.res: ../resources/YAMN.rc + $(WINDRES) -i ../resources/YAMN.rc --input-format=rc -o objs/YAMN.res -O coff --include-dir ../resources diff --git a/yamn/proto/md5.c b/yamn/proto/md5.c new file mode 100644 index 0000000..25546d2 --- /dev/null +++ b/yamn/proto/md5.c @@ -0,0 +1,260 @@ +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ +//#include /* for memcpy() */ +#if defined(_WIN64) + typedef unsigned __int64 size_t; +#else + typedef unsigned int size_t; + #include "../filter/simple/AggressiveOptimize.h" +#endif +void * __cdecl memcpy(void *, const void *, size_t); +void * __cdecl memset(void *, int, size_t); +#include "md5.h" + +#ifndef HIGHFIRST +#define byteReverse(buf, len) /* Nothing */ +#else +void byteReverse(unsigned char *buf, unsigned longs); + +#ifndef ASM_MD5 +/* + * Note: this code is harmless on little-endian machines. + */ +void byteReverse(unsigned char *buf, unsigned longs) +{ + uint32 t; + do { + t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(uint32 *) buf = t; + buf += 4; + } while (--longs); +} +#endif +#endif + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void MD5Init(struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) +{ + uint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void MD5Final(unsigned char digest[16], struct MD5Context *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((uint32 *) ctx->in)[14] = ctx->bits[0]; + ((uint32 *) ctx->in)[15] = ctx->bits[1]; + + MD5Transform(ctx->buf, (uint32 *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +#ifndef ASM_MD5 + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +void MD5Transform(uint32 buf[4], uint32 const in[16]) +{ + register uint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#endif diff --git a/yamn/proto/md5.h b/yamn/proto/md5.h new file mode 100644 index 0000000..e264f68 --- /dev/null +++ b/yamn/proto/md5.h @@ -0,0 +1,27 @@ +#ifndef MD5_H +#define MD5_H + +#ifdef __alpha +typedef unsigned int uint32; +#else +typedef unsigned long uint32; +#endif + +struct MD5Context { + uint32 buf[4]; + uint32 bits[2]; + unsigned char in[64]; +}; + +void MD5Init(struct MD5Context *context); +void MD5Update(struct MD5Context *context, unsigned char const *buf, + unsigned len); +void MD5Final(unsigned char digest[16], struct MD5Context *context); +void MD5Transform(uint32 buf[4], uint32 const in[16]); + +/* + * This is needed to make RSAREF happy on some MS-DOS compilers. + */ +typedef struct MD5Context MD5_CTX; + +#endif /* !MD5_H */ diff --git a/yamn/proto/netclient.h b/yamn/proto/netclient.h new file mode 100644 index 0000000..2414dbd --- /dev/null +++ b/yamn/proto/netclient.h @@ -0,0 +1,22 @@ +#ifndef __CLIENT_H +#define __CLIENT_H + +class CNetClient +{ +public: + CNetClient(): Stopped(FALSE) {} + virtual void Connect(const char* servername,const int port)=0; + virtual void Send(const char *query)=0; + virtual char* Recv(char *buf=NULL,int buflen=65536)=0; + virtual void Disconnect()=0; + virtual BOOL Connected()=0; + virtual void SSLify()=0; + + BOOL Stopped; + int Rcv; + DWORD NetworkError; + DWORD SystemError; + BOOL ifTLSed; +}; + +#endif diff --git a/yamn/proto/netlib.cpp b/yamn/proto/netlib.cpp new file mode 100644 index 0000000..f6f497b --- /dev/null +++ b/yamn/proto/netlib.cpp @@ -0,0 +1,278 @@ +/* + * This code implements communication based on Miranda netlib library + * + * (c) majvan 2002-2004 + */ + +#if !defined(_WIN64) + #include "../filter/simple/AggressiveOptimize.h" +#endif +#include +#include +#include //CallService,UnHookEvent +#include //socket thorugh proxy functions +#include //langpack for "connection" and other words +#include "../debug.h" +#include "netlib.h" + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +BOOL SSLLoaded=FALSE; +HANDLE hNetlibUser=NULL; + +extern PVOID TLSCtx; +extern PVOID SSLCtx; + +void __stdcall SSL_DebugLog(const char *fmt, ...) +{ + char str[ 4096 ]; + va_list vararg; + + va_start( vararg, fmt ); + int tBytes = _vsnprintf( str, sizeof(str)-1, fmt, vararg ); + if ( tBytes == 0 ) + return; + + if ( tBytes > 0 ) + str[ tBytes ] = 0; + else + str[ sizeof(str)-1 ] = 0; + + CallService(MS_NETLIB_LOG, (WPARAM)hNetlibUser, (LPARAM)str); + va_end( vararg ); +} + +HANDLE RegisterNLClient(const char *name) +{ + static NETLIBUSER nlu={0}; + char desc[128]; + + sprintf(desc, TranslateT("%s connection"),name); + +#ifdef DEBUG_COMM + DebugLog(CommFile,""); +#endif + nlu.cbSize = sizeof(nlu); + nlu.flags = NUF_OUTGOING | NUF_HTTPCONNS; + nlu.szDescriptiveName=desc; + nlu.szSettingsModule=(char *)name; + hNetlibUser=(HANDLE)CallService(MS_NETLIB_REGISTERUSER,0,(LPARAM)&nlu); + +#ifdef DEBUG_COMM + if(NULL==hNetlibUser) + DebugLog(CommFile,"\n"); + else + DebugLog(CommFile,"\n"); +#endif + return hNetlibUser; +} + +//Move connection to SSL +void CNLClient::SSLify() throw(DWORD){ +#ifdef DEBUG_COMM + SSL_DebugLog("Staring SSL..."); +#endif + int socket = CallService(MS_NETLIB_GETSOCKET, (WPARAM)hConnection, 0); + if (socket != INVALID_SOCKET) + { +#ifdef DEBUG_COMM + SSL_DebugLog("Staring netlib core SSL"); +#endif + if (CallService(MS_NETLIB_STARTSSL, (WPARAM)hConnection, 0)) + { +#ifdef DEBUG_COMM + SSL_DebugLog("Netlib core SSL started"); +#endif + isTLSed = true; + SSLLoaded = TRUE; + return; + } + } + + //ssl could not be created + throw NetworkError = (DWORD)ESSL_CREATESSL; +} + +//Connects to the server through the sock +//if not success, exception is throwed +void CNLClient::Connect(const char* servername,const int port) throw(DWORD) +{ + NETLIBOPENCONNECTION nloc; + + NetworkError=SystemError=0; + isTLSed = false; + +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + try + { + nloc.cbSize=sizeof(NETLIBOPENCONNECTION); + nloc.szHost=servername; + nloc.wPort=port; + nloc.flags=0; + if(NULL==(hConnection=(HANDLE)CallService(MS_NETLIB_OPENCONNECTION,(WPARAM)hNetlibUser,(LPARAM)&nloc))) + { + SystemError=WSAGetLastError(); + throw NetworkError=(DWORD)ENL_CONNECT; + } +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + return; + } + catch(...) + { +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + throw; + } +} + +//Performs a simple query +// query- command to send +int CNLClient::LocalNetlib_Send(HANDLE hConn,const char *buf,int len,int flags) { + if (isTLSed) + { +#ifdef DEBUG_COMM + SSL_DebugLog("SSL send: %s", buf); +#endif + } + + NETLIBBUFFER nlb={(char*)buf,len,flags}; + return CallService(MS_NETLIB_SEND,(WPARAM)hConn,(LPARAM)&nlb); +} + +void CNLClient::Send(const char *query) throw(DWORD) +{ + unsigned int Sent; + + if(NULL==query) + return; + if(hConnection==NULL) + return; +#ifdef DEBUG_COMM + DebugLog(CommFile,"%s",query); +#endif + try + { + if((SOCKET_ERROR==(Sent=LocalNetlib_Send(hConnection,query,(int)strlen(query),MSG_DUMPASTEXT))) || Sent!=(unsigned int)strlen(query)) + { + SystemError=WSAGetLastError(); + throw NetworkError=(DWORD)ENL_SEND; + } +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + } + catch(...) + { +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + throw; + } +} + +//Reads data from socket +// buf- buffer where to store max. buflen of received characters +// if buf is NULL, creates buffer of buflen size +// buf is NULL by default +//You need free() returned buffer, which can be allocated in this function +//if not success, exception is throwed + +int CNLClient::LocalNetlib_Recv(HANDLE hConn,char *buf,int len,int flags) { + NETLIBBUFFER nlb={buf,len,flags}; + int iReturn = CallService(MS_NETLIB_RECV,(WPARAM)hConn,(LPARAM)&nlb); + if (isTLSed) + { +#ifdef DEBUG_COMM + SSL_DebugLog("SSL recv: %s", buf); +#endif + } + + return iReturn; +} + +char* CNLClient::Recv(char *buf,int buflen) throw(DWORD) +{ +#ifdef DEBUG_COMM + DebugLog(CommFile,""); +#endif + try + { + if(buf==NULL) + buf=(char *)malloc(sizeof(char)*(buflen+1)); + if(buf==NULL) + throw NetworkError=(DWORD)ENL_RECVALLOC; + + if (!isTLSed) + { + NETLIBSELECT nls; + memset(&nls, 0, sizeof(NETLIBSELECT)); + nls.cbSize = sizeof(NETLIBSELECT); + nls.dwTimeout = 60000; + nls.hReadConns[0] = hConnection; + switch (CallService(MS_NETLIB_SELECT, 0, (LPARAM) &nls)) + { + case SOCKET_ERROR: + free(buf); + SystemError=WSAGetLastError(); + throw NetworkError = (DWORD) ENL_RECV; + case 0: // time out! + free(buf); + throw NetworkError = (DWORD) ENL_TIMEOUT; + } + } + + ZeroMemory(buf,buflen); + if(SOCKET_ERROR==(Rcv=LocalNetlib_Recv(hConnection,buf,buflen,MSG_DUMPASTEXT))) + { + free(buf); + SystemError=WSAGetLastError(); + throw NetworkError=(DWORD)ENL_RECV; + } + if(!Rcv) + { + free(buf); + SystemError=WSAGetLastError(); + throw NetworkError=(DWORD)ENL_RECV; + } +#ifdef DEBUG_COMM + *(buf+Rcv)=0; //end the buffer to write it to file + DebugLog(CommFile,"%s",buf); + DebugLog(CommFile,"\n"); +#endif + return(buf); + } + catch(...) + { +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + throw; + } +} + +//Closes netlib connection +void CNLClient::Disconnect() +{ + Netlib_CloseHandle(hConnection); + hConnection=(HANDLE)NULL; +} + +//Uninitializes netlib library +void UnregisterNLClient() +{ +#ifdef DEBUG_COMM + DebugLog(CommFile,""); +#endif + + Netlib_CloseHandle(hNetlibUser); + hNetlibUser=(HANDLE)NULL; +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif +} diff --git a/yamn/proto/netlib.h b/yamn/proto/netlib.h new file mode 100644 index 0000000..90ad361 --- /dev/null +++ b/yamn/proto/netlib.h @@ -0,0 +1,55 @@ +#ifndef __NETLIB_H +#define __NETLIB_H + +#include "netclient.h" + +#pragma warning( disable : 4290 ) + +class CNLClient: public CNetClient +{ +public: + CNLClient(): hConnection(NULL) {} + void Connect(const char* servername,const int port) throw(DWORD); + void Send(const char *query) throw(DWORD); + char* Recv(char *buf=NULL,int buflen=65536) throw(DWORD); + void Disconnect(); + void SSLify()throw(DWORD); + + inline BOOL Connected() {return hConnection!=NULL;} + +protected: + HANDLE hConnection; + BOOL isTLSed; + int LocalNetlib_Send(HANDLE hConn,const char *buf,int len,int flags); + int LocalNetlib_Recv(HANDLE hConn,char *buf,int len,int flags); +}; + +void SSL_DebugLog(const char *fmt, ...); + +enum +{ + ENL_WINSOCKINIT=1, //error initializing socket //only wsock + ENL_GETHOSTBYNAME, //DNS error //only wsock + ENL_CREATESOCKET, //error creating socket //only wsock + ENL_CONNECT, //cannot connect to server + ENL_SEND, //cannot send data + ENL_RECV, //cannot receive data + ENL_RECVALLOC, //cannot allocate memory for received data + ENL_TIMEOUT, //timed out during recv +}; + +enum +{ + ESSL_NOTLOADED=1, //OpenSSL is not loaded + ESSL_WINSOCKINIT, //WinSock 2.0 init failed + ESSL_GETHOSTBYNAME, //DNS error + ESSL_CREATESOCKET, //error creating socket + ESSL_SOCKETCONNECT, //error connecting with socket + ESSL_CREATESSL, //error creating SSL session structure + ESSL_SETSOCKET, //error connect socket with SSL session for bidirect I/O space + ESSL_CONNECT, //cannot connect to server + ESSL_SEND, //cannot send data + ESSL_RECV, //cannot receive data + ESSL_RECVALLOC, //cannot allocate memory for received data +}; +#endif diff --git a/yamn/proto/pop3/pop3.cpp b/yamn/proto/pop3/pop3.cpp new file mode 100644 index 0000000..59b8244 --- /dev/null +++ b/yamn/proto/pop3/pop3.cpp @@ -0,0 +1,374 @@ +/* + * This code implements basics of POP3 protocol + * + * (c) majvan 2002-2004 + */ +/* This was made from the libspopc project + * copyright c 2002 Benoit Rouits + * released under the terms of GNU LGPL + * (GNU Lesser General Public Licence). + * libspopc offers simple API for a pop3 client (MTA). + * See RFC 1725 for pop3 specifications. + * more information on http://brouits.free.fr/libspopc/ + */ +/* + * This file is not original and is changed by majvan + * for mail checker purpose. Please see original web page to + * obtain the original. I rewrote it in C++, but good ideas were, + * I think, unchanged. + * + * Note that this file was not designed to work under Unix. It's + * needed to add Unix-specific features. I was interested only in + * Windows for my project. majvan + * + */ + +#pragma warning( disable : 4290 ) + +#if !defined(_WIN64) + #include "../../filter/simple/AggressiveOptimize.h" +#endif +#include +#include +#include "pop3.h" + +extern "C" { +#include "../md5.h" +} + +extern void __stdcall SSL_DebugLog( const char *fmt, ... ); + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +//Connects to the server through the netlib +//if not success, exception is throwed +//returns welcome string returned by server +//sets AckFlag +char *CPop3Client::Connect(const char* servername,const int port,BOOL UseSSL, BOOL NoTLS) +{ + char *temp = 0; + if(Stopped) //check if we can work with this POP3 client session + throw POP3Error=(DWORD)EPOP3_STOPPED; + + if(NetClient!=NULL) + delete NetClient; + SSL=UseSSL; + NetClient=new CNLClient; + +#ifdef DEBUG_DECODE + DebugLog(DecodeFile,"Connect:servername: %s port:%d\n",servername,port); +#endif + POP3Error=EPOP3_CONNECT; + NetClient->Connect(servername,port); + POP3Error=0; + + if (SSL) + { + try { NetClient->SSLify(); } + catch (...) + { + NetClient->Disconnect(); + return NULL; + } + } + + temp = RecvRest(NetClient->Recv(),POP3_SEARCHACK); + extern BOOL SSLLoaded; + if (!NoTLS & !(SSL)){ + if(NetClient->Stopped) //check if we can work with this POP3 client session + throw POP3Error=(DWORD)EPOP3_STOPPED; + NetClient->Send("STLS\r\n"); + free(temp); + temp=RecvRest(NetClient->Recv(),POP3_SEARCHACK); + if(AckFlag==POP3_FOK){ // Ok, we are going to tls + try { + NetClient->SSLify(); + } catch (...) { + NetClient->Disconnect(); + return NULL; + } +// temp = RecvRest(NetClient->Recv(),POP3_SEARCHACK); + } + } +// SSL_DebugLog("Received: %s",temp); + return temp; +} + +//Receives data to the end of packet +// prev- previous data read (appends to this string next received data) +// mode- mode of packet. +// Packet can end with ack state (+OK or -ERR): set mode to POP3_SEARCHACK +// If packet ends with '.' (end of string), set mode to POP3_SEARCHDOT +// size- received data are stored to memory, but if length of data is more than allocated memory, function allocates +// new memory. New allocated memory has allocated size more bytes +// This value can be selectable: if you think it is better to reallocate by 1kB size, select size to 1024, +// default is 128. You do not need to use this parameter +char* CPop3Client::RecvRest(char* prev,int mode,int size) +{ + int SizeRead=0; + int SizeLeft=size-NetClient->Rcv; + int RcvAll=NetClient->Rcv; + char *LastString,*PrevString=prev; + + AckFlag=0; + + while(((mode==POP3_SEARCHDOT) && !SearchFromEnd(PrevString+RcvAll-1,RcvAll-3,POP3_SEARCHDOT) && !SearchFromStart(PrevString,2,POP3_SEARCHERR)) || //we are looking for dot or -err phrase + ((mode==POP3_SEARCHACK) && (!SearchFromStart(PrevString,RcvAll-3,mode) || !((RcvAll>3) && SearchFromEnd(PrevString+RcvAll-1,1,POP3_SEARCHNL))))) //we are looking for +ok or -err phrase ended with newline + { //if not found + if(NetClient->Stopped) //check if we can work with this POP3 client session + { + if(PrevString!=NULL) + free(PrevString); + throw POP3Error=(DWORD)EPOP3_STOPPED; + } + if(SizeLeft==0) //if block is full + { + SizeRead+=size; + SizeLeft=size; + LastString=NetClient->Recv(NULL,SizeLeft); + PrevString=(char *)realloc(PrevString,sizeof(char)*(SizeRead+size)); + if(PrevString==NULL) + throw POP3Error=(DWORD)EPOP3_RESTALLOC; + memcpy(PrevString+SizeRead,LastString,size); + free(LastString); + } + else + NetClient->Recv(PrevString+RcvAll,SizeLeft); //to Rcv stores received bytes + SizeLeft=SizeLeft-NetClient->Rcv; + RcvAll+=NetClient->Rcv; +// printf("[Read: %s]\n",PrevString); + } + NetClient->Rcv=RcvAll; //at the end, store the number of all bytes, no the number of last received bytes + return PrevString; +} + +// CPop3Client::SearchFromEnd +// returns 1 if substring DOTLINE or ENDLINE found from end in bs bytes +// if you need to add condition for mode, insert it into switch statement +BOOL CPop3Client::SearchFromEnd(char *end,int bs,int mode) +{ + while(bs>=0) + { + switch(mode) + { + case POP3_SEARCHDOT: + if(DOTLINE(end)) + return 1; + break; + case POP3_SEARCHNL: + if(ENDLINE(end)) + return 1; + break; + } + end--; + bs--; + } + return 0; +} + +//Finds for a occurence of some pattern in string +// returns 1 if substring OKLINE, ERRLINE or any of them found from start in bs bytes +//call only this function to retrieve ack status (+OK or -ERR), because it sets flag AckFlag +//if you need to add condition for mode, insert it into switch statement +BOOL CPop3Client::SearchFromStart(char *start,int bs,int mode) +{ + while(bs>=0) + { + switch(mode) + { + case POP3_SEARCHOK: + if(OKLINE(start)) + { + AckFlag=POP3_FOK; + return 1; + } + break; + case POP3_SEARCHERR: + if(ERRLINE(start)) + { + AckFlag=POP3_FERR; + return 1; + } + break; + case POP3_SEARCHACK: + if(ACKLINE(start)) + { + OKLINE(start) ? AckFlag=POP3_FOK : AckFlag=POP3_FERR; + return 1; + } + break; + } + start++; + bs--; + } + return 0; +} + +//Performs "USER" pop query and returns server response +//sets AckFlag +char* CPop3Client::User(char* name) +{ + if(NetClient->Stopped) //check if we can work with this POP3 client session + throw POP3Error=(DWORD)EPOP3_STOPPED; + + char query[128]; + char *Result; + + sprintf(query,"USER %s\r\n",name); + NetClient->Send(query); + Result=RecvRest(NetClient->Recv(),POP3_SEARCHACK); + if(AckFlag==POP3_FERR) + throw POP3Error=(DWORD)EPOP3_BADUSER; + POP3Error=0; + return Result; +} + +//Performs "PASS" pop query and returns server response +//sets AckFlag +char* CPop3Client::Pass(char* pw) +{ + if(NetClient->Stopped) //check if we can work with this POP3 client session + throw POP3Error=(DWORD)EPOP3_STOPPED; + + char query[128]; + char *Result; + + sprintf(query,"PASS %s\r\n",pw); + NetClient->Send(query); + Result=RecvRest(NetClient->Recv(),POP3_SEARCHACK); + if(AckFlag==POP3_FERR) + throw POP3Error=(DWORD)EPOP3_BADPASS; + return Result; +} + +//Performs "APOP" pop query and returns server response +//sets AckFlag +char* CPop3Client::APOP(char* name, char* pw, char* timestamp) +{ + if(NetClient->Stopped) //check if we can work with this POP3 client session + throw POP3Error=(DWORD)EPOP3_STOPPED; + + char query[512]; + char *Result; + unsigned char digest[16]; + char hexdigest[40]; + + if(timestamp==NULL) + throw POP3Error=(DWORD)EPOP3_APOP; + MD5Context ctx; + MD5Init(&ctx); + MD5Update(&ctx,(const unsigned char *)timestamp,(unsigned int)strlen(timestamp)); + MD5Update(&ctx,(const unsigned char *)pw,(unsigned int)strlen(pw)); + MD5Final(digest,&ctx); + hexdigest[0]='\0'; + for(int i=0; i<16; i++) { + char tmp[4]; + sprintf(tmp, "%02x", digest[i]); + strcat(hexdigest, tmp); + } + sprintf(query,"APOP %s %s\r\n",name, hexdigest); + NetClient->Send(query); + Result=RecvRest(NetClient->Recv(),POP3_SEARCHACK); + if(AckFlag==POP3_FERR) + throw POP3Error=(DWORD)EPOP3_BADUSER; + return Result; +} + +//Performs "QUIT" pop query and returns server response +//sets AckFlag +char* CPop3Client::Quit() +{ + char query[]="QUIT\r\n"; + + NetClient->Send(query); + return RecvRest(NetClient->Recv(),POP3_SEARCHACK); +} + +//Performs "STAT" pop query and returns server response +//sets AckFlag +char* CPop3Client::Stat() +{ + if(NetClient->Stopped) //check if we can work with this POP3 client session + throw POP3Error=(DWORD)EPOP3_STOPPED; + + char query[]="STAT\r\n"; + + NetClient->Send(query); + return RecvRest(NetClient->Recv(),POP3_SEARCHACK); +} + +//Performs "LIST" pop query and returns server response +//sets AckFlag +char* CPop3Client::List() +{ + if(NetClient->Stopped) //check if we can work with this POP3 client session + throw POP3Error=(DWORD)EPOP3_STOPPED; + + char query[]="LIST\r\n"; + + NetClient->Send(query); + return RecvRest(NetClient->Recv(),POP3_SEARCHDOT); +} + +//Performs "TOP" pop query and returns server response +//sets AckFlag +char* CPop3Client::Top(int nr, int lines) +{ + if(NetClient->Stopped) //check if we can work with this POP3 client session + throw POP3Error=(DWORD)EPOP3_STOPPED; + + char query[128]; + + sprintf(query,"TOP %d %d\r\n",nr,lines); + NetClient->Send(query); + return RecvRest(NetClient->Recv(),POP3_SEARCHDOT); +} + +//Performs "UIDL" pop query and returns server response +//sets AckFlag +char* CPop3Client::Uidl(int nr) +{ + if(NetClient->Stopped) //check if we can work with this POP3 client session + throw POP3Error=(DWORD)EPOP3_STOPPED; + + char query[128]; + + if(nr) + { + sprintf(query,"UIDL %d\r\n",nr); + NetClient->Send(query); + return RecvRest(NetClient->Recv(),POP3_SEARCHACK); + } + sprintf(query,"UIDL\r\n"); + NetClient->Send(query); + return RecvRest(NetClient->Recv(),POP3_SEARCHDOT); +} + +//Performs "DELE" pop query and returns server response +//sets AckFlag +char* CPop3Client::Dele(int nr) +{ + if(NetClient->Stopped) //check if we can work with this POP3 client session + throw POP3Error=(DWORD)EPOP3_STOPPED; + + char query[128]; + + sprintf(query,"DELE %d\r\n",nr); + NetClient->Send(query); + return RecvRest(NetClient->Recv(),POP3_SEARCHACK); +} +//Performs "RETR" pop query and returns server response +//sets AckFlag +char* CPop3Client::Retr(int nr) +{ + if(NetClient->Stopped) //check if we can work with this POP3 client session + throw POP3Error=(DWORD)EPOP3_STOPPED; + + char query[128]; + + sprintf(query,"RETR %d\r\n",nr); + NetClient->Send(query); + RecvRest(NetClient->Recv(),POP3_SEARCHACK); + return NetClient->Recv(); +} \ No newline at end of file diff --git a/yamn/proto/pop3/pop3.h b/yamn/proto/pop3/pop3.h new file mode 100644 index 0000000..faa6bd6 --- /dev/null +++ b/yamn/proto/pop3/pop3.h @@ -0,0 +1,66 @@ +#ifndef __POP3_H +#define __POP3_H + +#include "../../debug.h" +#include "../netlib.h" //NetLib client + +#define DOTLINE(s) ((((s)[-2]=='\r') || ((s)[-2]=='\n')) && ((s)[-1]=='.') && (((s)[0]=='\r') || ((s)[0]=='\n') || ((s)[0]=='\0'))) // be careful, it's different to ESR's pop3.c ;-) +#define ENDLINE(s) (((s)[0]=='\r') || ((s)[0]=='\n')) //endline +#define OKLINE(s) (((s)[0]=='+') && (((s)[1]=='o') || ((s)[1]=='O')) && (((s)[2]=='k') || ((s)[2]=='K'))) // +OK +#define ERRLINE(s) (((s)[0]=='-') && (((s)[1]=='e') || ((s)[1]=='E')) && (((s)[2]=='r') || ((s)[2]=='R')) && (((s)[3]=='r') || ((s)[3]=='R'))) // -ERR +#define ACKLINE(s) (OKLINE(s) || ERRLINE(s)) + +#define POP3_SEARCHDOT 1 +#define POP3_SEARCHACK 2 +#define POP3_SEARCHOK 3 +#define POP3_SEARCHERR 4 +#define POP3_SEARCHNL 5 + +#define POP3_FOK 1 +#define POP3_FERR 2 + +class CPop3Client +{ +public: + CPop3Client(): NetClient(NULL), Stopped(FALSE) {} + ~CPop3Client() {if(NetClient!=NULL) delete NetClient;} + + char* Connect(const char* servername,const int port=110,BOOL UseSSL=FALSE, BOOL NoTLS=FALSE); + char* RecvRest(char* prev,int mode,int size=65536); + char* User(char* name); + char* Pass(char* pw); + char* APOP(char* name, char* pw, char* timestamp); + char* Quit(); + char* Stat(); + char* List(); + char* Top(int nr, int lines=0); + char* Uidl(int nr=0); + char* Dele(int nr); + char* Retr(int nr); + + unsigned char AckFlag; + BOOL SSL; + BOOL Stopped; + + DWORD POP3Error; + class CNetClient *NetClient; //here the network layout is defined (TCP or SSL+TCP etc.) +private: + BOOL SearchFromEnd(char *end,int bs,int mode); + BOOL SearchFromStart(char *end,int bs,int mode); +}; + +enum +{ + EPOP3_QUEUEALLOC=1, //memory allocation + EPOP3_STOPPED, //stop account + EPOP3_CONNECT, //cannot connect to server + EPOP3_RESTALLOC, //cannot allocate memory for received data + EPOP3_BADUSER, //cannot login because USER command failed + EPOP3_BADPASS, //cannot login because PASS command failed + EPOP3_APOP, //server does not send timestamp for APOP auth + EPOP3_STAT, + EPOP3_LIST, + EPOP3_UIDL, +}; + +#endif diff --git a/yamn/proto/pop3/pop3comm.cpp b/yamn/proto/pop3/pop3comm.cpp new file mode 100644 index 0000000..d80ab20 --- /dev/null +++ b/yamn/proto/pop3/pop3comm.cpp @@ -0,0 +1,1636 @@ +/* + * This code implements POP3 server checking for new mail and so on. + * There's function SynchroPOP3 in this file- for checking and synchronising POP3 account + * and DeleteMailsPOP3- for deleting mails from POP3 server + * + * Note this file acts as main file for internal plugin. + * + * (c) majvan 2002-2004 + * 18/08 +*/ + + +#pragma warning( disable : 4290 ) +#include "../../main.h" +#include "../../yamn.h" +#include "pop3.h" +#include "pop3comm.h" //all we need for POP3 account (POP3 account= YAMN account + some more POP3 specified members) +#include //socket thorugh proxy functions + +#define ERRORSTR_MAXLEN 1024 //in wide-chars + +//- imported --------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +//From main.cpp +void SetDefaultProtocolIcons(); +//From pop3opt.cpp +extern int POP3OptInit(WPARAM wParam,LPARAM lParam); +//From netlib.cpp +extern HANDLE RegisterNLClient(const char *name); +//this is imported because of one bug, should not be imported normally (this POP3 is plugin of YAMN) +extern INT_PTR FilterMailSvc(WPARAM,LPARAM); + +extern char *ProtoName; +extern INT_PTR YAMN_STATUS; +extern PLUGININFO pluginInfo; + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +HANDLE hNetLib = NULL; +PSCOUNTER CPOP3Account::AccountWriterSO = NULL; + +//Creates new CPOP3Account structure +HACCOUNT WINAPI CreatePOP3Account(HYAMNPROTOPLUGIN Plugin,DWORD CAccountVersion); + +//Deletes CPOP3Account structure +void WINAPI DeletePOP3Account(HACCOUNT Which); + +//Sets stop flag to account +void WINAPI StopPOP3Account(HACCOUNT Which); + +//Function registers standard functions for YAMN +int RegisterPOP3Plugin(WPARAM,LPARAM); + +//This should be normally exporeted fcn UninstallEx from plugin DLL, but YAMN has already exported one, so this is the same called from YAMN UninstallEx +//This is used by PluginUninstall +int UninstallPOP3(PLUGINUNINSTALLPARAMS* ppup); + +//Unloads all variables created on heap (delete[]) +DWORD WINAPI UnLoadPOP3(void *); + +//Function writes POP3 accounts using YAMN exported functions +DWORD WINAPI WritePOP3Accounts(); + +//Function stores plugin's data for account to file +DWORD WINAPI WritePOP3Options(HANDLE,HACCOUNT); + +//Function reads plugin's data for account from file +DWORD WINAPI ReadPOP3Options(HACCOUNT,TCHAR **,TCHAR *); + +//Creates new mail for an account +HYAMNMAIL WINAPI CreatePOP3Mail(HACCOUNT Account,DWORD CMimeMailVersion); + +//Function does all needed work when connection failed or any error occured +//Creates structure containing error code, closes internet session, runs "bad connect" function +static void PostErrorProc(HPOP3ACCOUNT ActualAccount,void *ParamToBadConnect,DWORD POP3PluginParam,BOOL UseSSL); + +//Checks POP3 account and stores all info to account. It deletes old mails=> synchro +// WhichTemp- pointer to strucure containing needed information +DWORD WINAPI SynchroPOP3(struct CheckParam *WhichTemp); + +//Deletes mails from POP3 server +// WhichTemp- structure containing needed information (queued messages to delete) +//Function deletes from memory queue in WhichTemp structure +DWORD WINAPI DeleteMailsPOP3(struct DeleteParam *WhichTemp); + +//Function makes readable message about error. It sends it back to YAMN, so YAMN then +//can show it to the message window +WCHAR* WINAPI GetErrorString(DWORD Code); + +//Function deletes string allocated in GetErrorString +void WINAPI DeleteErrorString(LPVOID String); + +//Extracts info from result of POP3's STAT command +// stream- source string +// len- length of source string +// mboxsize- adreess to integer, that receives size of mailbox +// mails- adreess to integer, that receives number of mails +void ExtractStat(char *stream,int len,int *mboxsize,int *mails); + +//Extracts mail ID on mailbox +// stream- source string +// len- length of source string +// queue- address of first message, where first ID will be stored +void ExtractUIDL(char *stream,int len,HYAMNMAIL queue); + +//Extracts mail size on mailbox +// stream- source string +// len- length of source string +// queue- address of first message, where size of message #1 will be stored +void ExtractList(char *stream,int len,HYAMNMAIL queue); + +void ExtractMail(char *stream,int len,HYAMNMAIL queue); + +struct YAMNExportedFcns *pYAMNFcn = NULL; +struct MailExportedFcns *pYAMNMailFcn = NULL; + +YAMN_PROTOIMPORTFCN POP3ProtocolFunctions = +{ + CreatePOP3Account, + DeletePOP3Account, + StopPOP3Account, + WritePOP3Options, + ReadPOP3Options, + SynchroPOP3, + SynchroPOP3, + SynchroPOP3, + DeleteMailsPOP3, + GetErrorString, + NULL, + DeleteErrorString, + WritePOP3Accounts, + NULL, + UnLoadPOP3, +}; + +YAMN_MAILIMPORTFCN POP3MailFunctions = +{ + CreatePOP3Mail, + NULL, + NULL, + NULL, +}; + +PYAMN_VARIABLES pYAMNVar = NULL; +HYAMNPROTOPLUGIN POP3Plugin = NULL; + +YAMN_PROTOREGISTRATION POP3ProtocolRegistration = +{ + "POP3 protocol (internal)", + YAMN_VERSION_C, + "© 2002-2004 majvan | 2005-2007 tweety, yb", + "Mail notifier and browser for Miranda IM. Included POP3 protocol.", + "francois.mean@skynet.be", + "http://forums.miranda-im.org/showthread.php?t=3035", +}; + +WCHAR *FileName = NULL; + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +CPOP3Account::CPOP3Account() +{ +//NOTE! This constructor constructs CAccount structure. If your plugin is not internal, +//you will need these constructors. All you need is in Account.cpp. Just copy to your source code +//constructor and destructor of CAccount. + UseInternetFree=CreateEvent(NULL,FALSE,TRUE,NULL); + InternetQueries=new SCOUNTER; + AbilityFlags=YAMN_ACC_BROWSE | YAMN_ACC_POPUP; + + SetAccountStatus((HACCOUNT)this,TranslateT("Disconnected")); +} + +CPOP3Account::~CPOP3Account() +{ + CloseHandle(UseInternetFree); + if(InternetQueries!=NULL) + delete InternetQueries; +} + +HACCOUNT WINAPI CreatePOP3Account(HYAMNPROTOPLUGIN Plugin,DWORD CAccountVersion) +{ +//First, we should check whether CAccountVersion matches. +//But this is internal plugin, so YAMN's CAccount structure and our CAccount structure are +//the same, so we do not need to test version. Otherwise, if CAccount version does not match +//in your plugin, you should return NULL, like this: +// if(CAccountVersion!=YAMN_ACCOUNTVERSION) return NULL; + +//Now it is needed to construct our POP3 account and return its handle + return (HACCOUNT)new struct CPOP3Account(); +} + +void WINAPI DeletePOP3Account(HACCOUNT Which) +{ + delete (HPOP3ACCOUNT)Which; +} + +void WINAPI StopPOP3Account(HACCOUNT Which) +{ + ((HPOP3ACCOUNT)Which)->Client.Stopped=TRUE; + if(((HPOP3ACCOUNT)Which)->Client.NetClient!=NULL) //we should inform also network client. Usefull only when network client implements this feature + ((HPOP3ACCOUNT)Which)->Client.NetClient->Stopped=TRUE; +} + +//This function is like main function for POP3 internal protocol +int RegisterPOP3Plugin(WPARAM,LPARAM) +{ + + //Get YAMN variables we can use + if(NULL==(pYAMNVar=(PYAMN_VARIABLES)CallService(MS_YAMN_GETVARIABLES,(WPARAM)YAMN_VARIABLESVERSION,(LPARAM)0))) + return 0; + + //We have to get pointers to YAMN exported functions: allocate structure and fill it + if(NULL==(pYAMNFcn=new struct YAMNExportedFcns)) + {UnLoadPOP3(0); return 0;} + + //Register new pop3 user in netlib + if(NULL==(hNetLib=RegisterNLClient("YAMN-POP3"))) + {UnLoadPOP3(0); return 0;} + + pYAMNFcn->SetProtocolPluginFcnImportFcn=(YAMN_SETPROTOCOLPLUGINFCNIMPORTFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SETPROTOCOLPLUGINFCNIMPORTID,(LPARAM)0); + pYAMNFcn->WaitToWriteFcn=(YAMN_WAITTOWRITEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_WAITTOWRITEID,(LPARAM)0); + pYAMNFcn->WriteDoneFcn=(YAMN_WRITEDONEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_WRITEDONEID,(LPARAM)0); + pYAMNFcn->WaitToReadFcn=(YAMN_WAITTOREADFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_WAITTOREADID,(LPARAM)0); + pYAMNFcn->ReadDoneFcn=(YAMN_READDONEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_READDONEID,(LPARAM)0); + pYAMNFcn->SCGetNumberFcn=(YAMN_SCMANAGEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SCGETNUMBERID,(LPARAM)0); + pYAMNFcn->SCIncFcn=(YAMN_SCMANAGEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SCINCID,(LPARAM)0); + pYAMNFcn->SCDecFcn=(YAMN_SCMANAGEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SCDECID,(LPARAM)0); + pYAMNFcn->SetStatusFcn=(YAMN_SETSTATUSFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SETSTATUSID,(LPARAM)0); + pYAMNFcn->GetStatusFcn=(YAMN_GETSTATUSFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_GETSTATUSID,(LPARAM)0); + + if(NULL==(pYAMNMailFcn=new struct MailExportedFcns)) + {UnLoadPOP3(0); return 0;} + + pYAMNMailFcn->SynchroMessagesFcn=(YAMN_SYNCHROMIMEMSGSFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_SYNCHROMIMEMSGSID,(LPARAM)0); + pYAMNMailFcn->TranslateHeaderFcn=(YAMN_TRANSLATEHEADERFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_TRANSLATEHEADERID,(LPARAM)0); + pYAMNMailFcn->AppendQueueFcn=(YAMN_APPENDQUEUEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_APPENDQUEUEID,(LPARAM)0); + pYAMNMailFcn->DeleteMessagesToEndFcn=(YAMN_DELETEMIMEQUEUEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_DELETEMIMEQUEUEID,(LPARAM)0); + pYAMNMailFcn->DeleteMessageFromQueueFcn=(YAMN_DELETEMIMEMESSAGEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_DELETEMIMEMESSAGEID,(LPARAM)0); + pYAMNMailFcn->FindMessageByIDFcn=(YAMN_FINDMIMEMESSAGEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_FINDMIMEMESSAGEID,(LPARAM)0); + pYAMNMailFcn->CreateNewDeleteQueueFcn=(YAMN_CREATENEWDELETEQUEUEFCN)CallService(MS_YAMN_GETFCNPTR,(WPARAM)YAMN_CREATENEWDELETEQUEUEID,(LPARAM)0); + + //set static variable + if(CPOP3Account::AccountWriterSO==NULL) { + if(NULL==(CPOP3Account::AccountWriterSO=new SCOUNTER)) + {UnLoadPOP3(0); return 0;} + } + + //First, we register this plugin + //it is quite impossible this function returns zero (failure) as YAMN and internal plugin structre versions are the same + POP3ProtocolRegistration.Name = Translate("POP3 protocol (internal)"); + POP3ProtocolRegistration.Description = Translate("Mail notifier and browser for Miranda IM. Included POP3 protocol."); + if(NULL==(POP3Plugin=(HYAMNPROTOPLUGIN)CallService(MS_YAMN_REGISTERPROTOPLUGIN,(WPARAM)&POP3ProtocolRegistration,(LPARAM)YAMN_PROTOREGISTRATIONVERSION))) + return 0; + + //Next we set our imported functions for YAMN + if(!SetProtocolPluginFcnImport(POP3Plugin,&POP3ProtocolFunctions,YAMN_PROTOIMPORTFCNVERSION,&POP3MailFunctions,YAMN_MAILIMPORTFCNVERSION)) + return 0; + + //Then, we read all mails for accounts. + //You must first register account, before using this function as YAMN must use CreatePOP3Account function to add new accounts + //But if CreatePOP3Account is not implemented (equals to NULL), YAMN creates account as YAMN's standard HACCOUNT + if(FileName) CallService(MS_YAMN_DELETEFILENAME,(WPARAM)FileName,(LPARAM)0); //shoud not happen (only for secure) + FileName=(WCHAR *)CallService(MS_YAMN_GETFILENAMEA,(WPARAM)"pop3",(LPARAM)0); + + switch(CallService(MS_YAMN_READACCOUNTSW,(WPARAM)POP3Plugin,(LPARAM)FileName)) + { + case EACC_FILEVERSION: + MessageBoxA(NULL,Translate("Found new version of account book, not compatible with this version of YAMN."),Translate(_T("YAMN (internal POP3) read error")),MB_OK); + CallService(MS_YAMN_DELETEFILENAME,(WPARAM)FileName,(LPARAM)0); + return 0; + case EACC_FILECOMPATIBILITY: + MessageBoxA(NULL,Translate("Error reading account file. Account file corrupted."),Translate("YAMN (internal POP3) read error"),MB_OK); + CallService(MS_YAMN_DELETEFILENAME,(WPARAM)FileName,(LPARAM)0); + return 0; + case EACC_ALLOC: + MessageBoxA(NULL,Translate("Memory allocation error while data reading"),Translate("YAMN (internal POP3) read error"),MB_OK); + CallService(MS_YAMN_DELETEFILENAME,(WPARAM)FileName,(LPARAM)0); + return 0; + case EACC_SYSTEM: + if(ERROR_FILE_NOT_FOUND!=GetLastError()) + { + char temp[1024] = {0}; + _snprintf(temp,1024,"%s\n%S",Translate("Reading file error. File already in use?"),FileName); + MessageBoxA(NULL,temp,Translate("YAMN (internal POP3) read error"),MB_OK); + CallService(MS_YAMN_DELETEFILENAME,(WPARAM)FileName,(LPARAM)0); + return 0; + } + break; + } + //HookEvent(ME_OPT_INITIALISE,POP3OptInit); + + HACCOUNT Finder; + HANDLE hContact; + DBVARIANT dbv; + char *szProto; + + for(Finder=POP3Plugin->FirstAccount;Finder!=NULL;Finder=Finder->Next) + { + Finder->hContact = NULL; + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while(hContact) + { + szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if(szProto != NULL && strcmp(szProto, ProtoName)==0) + { + if(!DBGetContactSetting(hContact,ProtoName,"Id",&dbv)) + { + + if( strcmp((char*)dbv.pszVal, Finder->Name)==0) + { + Finder->hContact = hContact; + DBWriteContactSettingWord(Finder->hContact, ProtoName, "Status", ID_STATUS_ONLINE); + DBWriteContactSettingString(Finder->hContact, "CList", "StatusMsg", Translate("No new mail message")); + if((Finder->Flags & YAMN_ACC_ENA) && (Finder->NewMailN.Flags & YAMN_ACC_CONT)) + { + DBDeleteContactSetting(Finder->hContact, "CList", "Hidden"); + } + if(!(Finder->Flags & YAMN_ACC_ENA) || !(Finder->NewMailN.Flags & YAMN_ACC_CONT)) + { + DBWriteContactSettingByte(Finder->hContact, "CList", "Hidden", 1); + } + } + DBFreeVariant(&dbv); + } + + } + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } + if(Finder->hContact == NULL && (Finder->Flags & YAMN_ACC_ENA) && (Finder->NewMailN.Flags & YAMN_ACC_CONT)) + { + //No account contact found, have to create one + Finder->hContact =(HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0); + CallService(MS_PROTO_ADDTOCONTACT,(WPARAM)Finder->hContact,(LPARAM)ProtoName); + DBWriteContactSettingString(Finder->hContact,ProtoName,"Id",Finder->Name); + DBWriteContactSettingString(Finder->hContact,ProtoName,"Nick",Finder->Name); + DBWriteContactSettingString(Finder->hContact,"Protocol","p",ProtoName); + DBWriteContactSettingWord(Finder->hContact, ProtoName, "Status", YAMN_STATUS); + } + + /*//this doesn't work. the function doesn't know which contact to check + //if((Finder->Flags & YAMN_ACC_ENA) && (Finder->NewMailN.Flags & YAMN_ACC_CONT) && DBGetContactSettingByte(NULL, YAMN_DBMODULE, YAMN_SHOWMAINMENU, 0)) + //{ + // mi.cbSize = sizeof(mi); + // mi.position = 0xb0000000; + // mi.flags = CMIM_ICON; + // mi.hIcon = hYamnIcons[1]; + // mi.pszName = Finder->Name; + // mi.pszPopupName = ProtoName; + // mi.pszService = MS_YAMN_CLISTCONTEXT; + // hMenuItemMain = (HANDLE) CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi); + }*/ + + } + + return 0; +} + +int UninstallPOP3(PLUGINUNINSTALLPARAMS* ppup) //Usually UninstallEx, but need different name, because it is registered yet in main.cpp +{ + if(ppup->bDoDeleteSettings) + { + char FileNameA[MAX_PATH+1]; + + PUIRemoveDbModule("YAMN-POP3"); + + if(FileName==NULL) + MessageBox(NULL,"Cannot delete book file when YAMN is not loaded. Please do it manually.","YAMN-POP3 uninstalling",MB_OK|MB_ICONWARNING); + else + { + if(!WideCharToMultiByte(CP_ACP,0,FileName,-1,FileNameA,MAX_PATH+1,NULL,NULL)) + MessageBox(NULL,"Cannot delete book file. Please do it manually.","YAMN-POP3 uninstalling",MB_OK|MB_ICONWARNING); + else + DeleteFile(FileNameA); + } + } + return 0; +} + +DWORD WINAPI UnLoadPOP3(void *) +{ + //pYAMNVar is only a pointr, no need delete or free + if(hNetLib) { + Netlib_CloseHandle(hNetLib); hNetLib = NULL;} + if(CPOP3Account::AccountWriterSO) { + delete CPOP3Account::AccountWriterSO; CPOP3Account::AccountWriterSO = NULL;} + if(pYAMNMailFcn) { + delete pYAMNMailFcn; pYAMNMailFcn = NULL;} + if(pYAMNFcn) { + delete pYAMNFcn; pYAMNFcn = NULL;} + if(FileName) { + CallService(MS_YAMN_DELETEFILENAME,(WPARAM)FileName,(LPARAM)0); FileName = NULL;} + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"UnLoadPOP3:done\n"); + #endif + return 1; +} + +DWORD WINAPI WritePOP3Accounts() +{ +// WCHAR *FileName=(WCHAR *)CallService(MS_YAMN_GETFILENAMEA,(WPARAM)"pop3",(LPARAM)0); + DWORD ReturnValue=CallService(MS_YAMN_WRITEACCOUNTSW,(WPARAM)POP3Plugin,(LPARAM)FileName); + + switch(ReturnValue) + { + case EACC_SYSTEM: + { + char temp[1024] = {0}; + _snprintf(temp,1024,"%s\n%S",Translate("Error while copying data to disk occured. File in use?"),FileName); + MessageBox(NULL,temp,Translate("POP3 plugin- write file error"),MB_OK); + } + break; + case 0: + break; + } +// CallService(MS_YAMN_DELETEFILENAME,(WPARAM)FileName,(LPARAM)0); + return ReturnValue; +} + +DWORD WINAPI WritePOP3Options(HANDLE File,HACCOUNT Which) +{ + DWORD WrittenBytes; + DWORD Ver=POP3_FILEVERSION; + + if((!WriteFile(File,(char *)&Ver,sizeof(DWORD),&WrittenBytes,NULL)) || + (!WriteFile(File,(char *)&((HPOP3ACCOUNT)Which)->CP,sizeof(WORD),&WrittenBytes,NULL))) + return EACC_SYSTEM; + return 0; +} + +DWORD WINAPI ReadPOP3Options(HACCOUNT Which,TCHAR **Parser,TCHAR *End) +{ + DWORD Ver; +#ifdef DEBUG_FILEREAD + TCHAR Debug[256]; +#endif + Ver=*(DWORD *)(*Parser); + (*Parser)+=sizeof(DWORD)/sizeof(TCHAR); + if(*Parser>=End) + return EACC_FILECOMPATIBILITY; + if(Ver!=POP3_FILEVERSION) + return EACC_FILECOMPATIBILITY; + + ((HPOP3ACCOUNT)Which)->CP=*(WORD *)(*Parser); + (*Parser)+=sizeof(WORD)/sizeof(TCHAR); + if(*Parser>=End) + return EACC_FILECOMPATIBILITY; +#ifdef DEBUG_FILEREAD + _stprintf(Debug,_T("CodePage: %d, remaining %d chars"),((HPOP3ACCOUNT)Which)->CP,End-*Parser); + MessageBox(NULL,Debug,_T("debug"),MB_OK); +#endif + return 0; +} + +HYAMNMAIL WINAPI CreatePOP3Mail(HACCOUNT Account,DWORD MailDataVersion) +{ + HYAMNMAIL NewMail; +//First, we should check whether MAILDATA matches. +//But this is internal plugin, so YAMN's MAILDATA structure and our MAILDATA structure are +//the same, so we do not need to test version. Otherwise, if MAILDATA version does not match +//in your plugin, you should return NULL, like this: +// if(MailDataVersion!=YAMN_MAILDATAVERSION) return NULL; + +//Now it is needed to construct our POP3 account and return its handle + if(NULL==(NewMail=new YAMNMAIL)) + return NULL; + + if(NULL==(NewMail->MailData=new MAILDATA)) + { + delete NewMail; + return NULL; + } + NewMail->MailData->CP=((HPOP3ACCOUNT)Account)->CP; + return (HYAMNMAIL)NewMail; +} + +static void SetContactStatus(HACCOUNT account, int status){ + if ((account->hContact) && (account->NewMailN.Flags & YAMN_ACC_CONT)){ + DBWriteContactSettingWord(account->hContact, ProtoName, "Status", status); + } +} + +static void PostErrorProc(HPOP3ACCOUNT ActualAccount,void *ParamToBadConnection,DWORD POP3PluginParam,BOOL UseSSL) +{ + char *DataRX; + +//We create new structure, that we pass to bad connection dialog procedure. This procedure next calls YAMN imported fuction +//from POP3 protocol to determine the description of error. We can describe error from our error code structure, because later, +//when YAMN calls our function, it passes us our error code. This is pointer to structure for POP3 protocol in fact. + PPOP3_ERRORCODE ErrorCode; + +//We store status before we do Quit(), because quit can destroy our errorcode status + if(NULL!=(ErrorCode=new POP3_ERRORCODE)) + { + ErrorCode->SSL=UseSSL; + ErrorCode->AppError=ActualAccount->SystemError; + ErrorCode->POP3Error=ActualAccount->Client.POP3Error; + ErrorCode->NetError=ActualAccount->Client.NetClient->NetworkError; + ErrorCode->SystemError=ActualAccount->Client.NetClient->SystemError; + } + + if(POP3PluginParam==(DWORD)NULL) //if it was normal YAMN call (force check or so on) + { + try + { + DataRX=ActualAccount->Client.Quit(); + if(DataRX!=NULL) + free(DataRX); + } + catch(...) + { + } +//We always close connection if error occured + try + { + ActualAccount->Client.NetClient->Disconnect(); + } + catch(...) + { + } + + SetAccountStatus(ActualAccount,Translate("Disconnected")); + +//If we cannot allocate memory, do nothing + if(ErrorCode==NULL) + { + SetEvent(ActualAccount->UseInternetFree); + return; + } + } + else //else it was called from POP3 plugin, probably error when deleting old mail (POP3 synchro calls POP3 delete) + if(ErrorCode==NULL) + return; + + if((ActualAccount->BadConnectN.Flags & YAMN_ACC_MSG) || (ActualAccount->BadConnectN.Flags & YAMN_ACC_ICO) || (ActualAccount->BadConnectN.Flags & YAMN_ACC_POP)) + { + YAMN_BADCONNECTIONPARAM cp={(HANDLE)0,ActualAccount,(UINT_PTR)ErrorCode,ParamToBadConnection}; + + CallService(MS_YAMN_BADCONNECTION,(WPARAM)&cp,(LPARAM)YAMN_BADCONNECTIONVERSION); + } + if(POP3PluginParam==(DWORD)NULL) //if it was normal YAMN call + SetEvent(ActualAccount->UseInternetFree); +} + +//Checks POP3 account and synchronizes it +DWORD WINAPI SynchroPOP3(struct CheckParam * WhichTemp) +{ + HPOP3ACCOUNT ActualAccount; + CPop3Client *MyClient; + HYAMNMAIL NewMails=NULL,MsgQueuePtr=NULL; + char* DataRX=NULL,*Temp; + int mboxsize,msgs,i; + SYSTEMTIME now; + LPVOID YAMNParam; + DWORD CheckFlags; + BOOL UsingInternet=FALSE; + struct { + char *ServerName; + DWORD ServerPort; + char *ServerLogin; + char *ServerPasswd; + DWORD Flags; + DWORD NFlags; + DWORD NNFlags; + } ActualCopied; + + //First, we should compare our version of CheckParam structure, but here it is not needed, because YAMN and internal plugin + //have the same version. But your plugin should do that in this way: + // if(((struct CheckParam *)WhichTemp)->Ver!=YAMN_CHECKVERSION) + // { + // SetEvent(((struct CheckParam *)WhichTemp)->ThreadRunningEV); //don't forget to unblock YAMN + // return (DWORD)-1; //ok, but we should return value. + // //When our plugin returns e.g. 0xFFFFFFFF (=-1, this is only our plugin value, YAMN does nothing with return value, + // //but only tests if it is nonzero. If yes, it calls GetErrorStringFcn. We know problem occured in YAMN incompatibility + // //and then we can in our GetErrorStringFcn e.g. return string "Uncompatible version of YAMN". + // } + + ActualAccount=(HPOP3ACCOUNT)WhichTemp->AccountParam; //copy address of structure from calling thread to stack of this thread + YAMNParam=WhichTemp->BrowserParam; + CheckFlags=WhichTemp->Flags; + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:Incrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount); + #endif + SCInc(ActualAccount->UsingThreads); + //Unblock YAMN, signal that we have copied all parameters from YAMN thread stack + if(INVALID_HANDLE_VALUE!=WhichTemp->ThreadRunningEV) + SetEvent(WhichTemp->ThreadRunningEV); + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountSO-read wait\n"); + #endif + if(WAIT_OBJECT_0!=WaitToRead(ActualAccount)) + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountSO-read wait failed\n"); + #endif + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:Decrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount); + #endif + SCDec(ActualAccount->UsingThreads); + return 0; + } + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountSO-read enter\n"); + #endif + MyClient=&ActualAccount->Client; + //Now, copy all needed information about account to local variables, so ActualAccount is not blocked in read mode during all connection process, which can last for several minutes. + ActualCopied.ServerName=_strdup(ActualAccount->Server->Name); + ActualCopied.ServerPort=ActualAccount->Server->Port; + ActualCopied.Flags=ActualAccount->Flags; + ActualCopied.ServerLogin=_strdup(ActualAccount->Server->Login); + ActualCopied.ServerPasswd=_strdup(ActualAccount->Server->Passwd); + ActualCopied.NFlags=ActualAccount->NewMailN.Flags; + ActualCopied.NNFlags=ActualAccount->NoNewMailN.Flags; + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountSO-read done\n"); + #endif + ReadDone(ActualAccount); + + SCInc(ActualAccount->InternetQueries); //increment counter, that there is one more thread waiting for connection + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:InternetFreeEV-wait\n"); + #endif + WaitForSingleObject(ActualAccount->UseInternetFree,INFINITE); //wait until we can use connection + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:InternetFreeEV-enter\n"); + #endif + SCDec(ActualAccount->InternetQueries); + + //OK, we enter the "use internet" section. But after we start communication, we can test if we did not enter the "use internet" section only for the reason, + //that previous thread release the internet section because this account has stop signal (we stop account and there are 2 threads: one communicating, + //the second one waiting for network access- the first one ends because we want to stop account, this one is released, but should be stopped as well). + if(!ActualAccount->AbleToWork) + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:stop signal-InternetFreeEV-done\n"); + #endif + SetEvent(ActualAccount->UseInternetFree); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:stop signal-Decrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount); + #endif + SCDec(ActualAccount->UsingThreads); + return 0; + } + UsingInternet=TRUE; + + GetLocalTime(&now); + ActualAccount->SystemError=0; //now we can use internet for this socket. First, clear errorcode. + try + { + SetContactStatus(ActualAccount,ID_STATUS_OCCUPIED); + #ifdef DEBUG_COMM + DebugLog(CommFile,"<--------Communication-------->\n"); + #endif + // if we are already connected, we have open session (another thread left us open session), so we don't need to login + // note that connected state without logging cannot occur, because if we close session, we always close socket too (we must close socket is the right word :) ) + if((MyClient->NetClient==NULL) || !MyClient->NetClient->Connected()) + { + SetAccountStatus(ActualAccount,Translate("Connecting to server")); + + DataRX=MyClient->Connect(ActualCopied.ServerName,ActualCopied.ServerPort,ActualCopied.Flags & YAMN_ACC_SSL23,ActualCopied.Flags & YAMN_ACC_NOTLS); + char *timestamp=NULL; + + if(DataRX!=NULL) + { + if(ActualCopied.Flags & YAMN_ACC_APOP) + { + char *lpos=strchr(DataRX,'<'); + char *rpos=strchr(DataRX,'>'); + if(lpos && rpos && rpos>lpos) { + int sz=(int)(rpos-lpos+2); + timestamp=new char[sz]; + memcpy(timestamp, lpos, sz-1); + timestamp[sz-1]='\0'; + } + } + free(DataRX); + DataRX=NULL; + } + + SetAccountStatus(ActualAccount,Translate("Entering POP3 account")); + + if(ActualCopied.Flags & YAMN_ACC_APOP) + { + DataRX=MyClient->APOP(ActualCopied.ServerLogin,ActualCopied.ServerPasswd,timestamp); + if(DataRX!=NULL) + free(DataRX); + DataRX=NULL; + delete[] timestamp; + } else { + DataRX=MyClient->User(ActualCopied.ServerLogin); + if(DataRX!=NULL) + free(DataRX); + DataRX=NULL; + DataRX=MyClient->Pass(ActualCopied.ServerPasswd); + if(DataRX!=NULL) + free(DataRX); + DataRX=NULL; + } + } + SetAccountStatus(ActualAccount,Translate("Searching for new mail message")); + + DataRX=MyClient->Stat(); + + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"<--------Account checking-------->\n"); + DebugLog(DecodeFile,"\n"); + #endif + ExtractStat(DataRX,MyClient->NetClient->Rcv,&mboxsize,&msgs); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"%d\n",mboxsize); + DebugLog(DecodeFile,"%d\n",msgs); + DebugLog(DecodeFile,"\n"); + #endif + if(DataRX!=NULL) + free(DataRX); + DataRX=NULL; + for(i=0;iNext=(HYAMNMAIL)CallService(MS_YAMN_CREATEACCOUNTMAIL,(WPARAM)ActualAccount,(LPARAM)YAMN_MAILVERSION); + MsgQueuePtr=MsgQueuePtr->Next; + } + if(MsgQueuePtr==NULL) + { + ActualAccount->SystemError=EPOP3_QUEUEALLOC; + throw (DWORD)ActualAccount->SystemError; + } + } + + if(msgs) + { + DataRX=MyClient->List(); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + ExtractList(DataRX,MyClient->NetClient->Rcv,NewMails); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + if(DataRX!=NULL) + free(DataRX); + DataRX=NULL; + + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + DataRX=MyClient->Uidl(); + ExtractUIDL(DataRX,MyClient->NetClient->Rcv,NewMails); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + if(DataRX!=NULL) + free(DataRX); + DataRX=NULL; + } + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write wait\n"); + #endif + if(WAIT_OBJECT_0!=MsgsWaitToWrite(ActualAccount)) + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write wait failed\n"); + #endif + throw (DWORD)(ActualAccount->SystemError=EACC_STOPPED); + } + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write enter\n"); + #endif + ActualAccount->LastChecked=now; + for(MsgQueuePtr=(HYAMNMAIL)ActualAccount->Mails;MsgQueuePtr!=NULL;MsgQueuePtr=MsgQueuePtr->Next){ + if (MsgQueuePtr->Flags&YAMN_MSG_BODYREQUESTED){ + HYAMNMAIL NewMsgsPtr=NULL; + for(NewMsgsPtr=(HYAMNMAIL)NewMails;NewMsgsPtr!=NULL;NewMsgsPtr=NewMsgsPtr->Next){ + if (!strcmp(MsgQueuePtr->ID,NewMsgsPtr->ID)){ + char accstatus[512]; + sprintf(accstatus,Translate("Reading body %s"),NewMsgsPtr->ID); + SetAccountStatus(ActualAccount,accstatus); + DataRX=MyClient->Top(MsgQueuePtr->Number,100); + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + DebugLog(DecodeFile,"
%s
\n",DataRX); + #endif + if(DataRX!=NULL) + { + Temp=DataRX; + while((TempNetClient->Rcv) && (WS(Temp) || ENDLINE(Temp))) Temp++; + + if(OKLINE(DataRX)) + for(Temp=DataRX;(TempNetClient->Rcv) && (!ENDLINE(Temp));Temp++); + while((TempNetClient->Rcv) && ENDLINE(Temp)) Temp++; + } + else + continue; + //delete all the headers of the old mail MsgQueuePtr->MailData->TranslatedHeader + struct CMimeItem *TH = MsgQueuePtr->MailData->TranslatedHeader; + if (TH) for(;MsgQueuePtr->MailData->TranslatedHeader!=NULL;) + { + TH=TH->Next; + if(MsgQueuePtr->MailData->TranslatedHeader->name!=NULL) + delete[] MsgQueuePtr->MailData->TranslatedHeader->name; + if(MsgQueuePtr->MailData->TranslatedHeader->value!=NULL) + delete[] MsgQueuePtr->MailData->TranslatedHeader->value; + delete MsgQueuePtr->MailData->TranslatedHeader; + MsgQueuePtr->MailData->TranslatedHeader=TH; + } + + TranslateHeader(Temp,MyClient->NetClient->Rcv-(Temp-DataRX),&MsgQueuePtr->MailData->TranslatedHeader); + + + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"
\n"); + #endif + MsgQueuePtr->Flags|=YAMN_MSG_BODYRECEIVED; + + if(DataRX!=NULL) + free(DataRX); + DataRX=NULL; + break; + } + } + } + } + + SynchroMessages(ActualAccount,(HYAMNMAIL *)&ActualAccount->Mails,NULL,(HYAMNMAIL *)&NewMails,NULL); //we get only new mails on server! +// NewMails=NULL; + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write done\n"); + #endif + MsgsWriteDone(ActualAccount); + for(MsgQueuePtr=(HYAMNMAIL)ActualAccount->Mails;MsgQueuePtr!=NULL;MsgQueuePtr=MsgQueuePtr->Next){ + if ((MsgQueuePtr->Flags&YAMN_MSG_BODYREQUESTED) && (MsgQueuePtr->Flags&YAMN_MSG_BODYRECEIVED)){ + MsgQueuePtr->Flags&=~YAMN_MSG_BODYREQUESTED; + if (MsgQueuePtr->MsgWindow){ + SendMessage(MsgQueuePtr->MsgWindow,WM_YAMN_CHANGECONTENT,0,0); + } + } + } + + for(msgs=0,MsgQueuePtr=NewMails;MsgQueuePtr!=NULL;MsgQueuePtr=MsgQueuePtr->Next,msgs++); //get number of new mails + + try + { + char accstatus[512]; + + for(i=0,MsgQueuePtr=NewMails;MsgQueuePtr!=NULL;i++) + { + BOOL autoretr = (ActualAccount->Flags & YAMN_ACC_BODY)!=0; + DataRX=MyClient->Top(MsgQueuePtr->Number,autoretr?100:0); + sprintf(accstatus,Translate("Reading new mail messages (%d%% done)"),100*i/msgs); + SetAccountStatus(ActualAccount,accstatus); + + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + DebugLog(DecodeFile,"
%s
\n",DataRX); + #endif + if(DataRX!=NULL) + { + Temp=DataRX; + while((TempNetClient->Rcv) && (WS(Temp) || ENDLINE(Temp))) Temp++; + + if(OKLINE(DataRX)) + for(Temp=DataRX;(TempNetClient->Rcv) && (!ENDLINE(Temp));Temp++); + while((TempNetClient->Rcv) && ENDLINE(Temp)) Temp++; + } + else + continue; + + TranslateHeader(Temp,MyClient->NetClient->Rcv-(Temp-DataRX),&MsgQueuePtr->MailData->TranslatedHeader); + + + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"
\n"); + #endif + MsgQueuePtr->Flags|=YAMN_MSG_NORMALNEW; + if (autoretr) MsgQueuePtr->Flags|=YAMN_MSG_BODYRECEIVED; + + //We are going to filter mail. Warning!- we must not be in read access neither write access to mails when calling this service + //This is done, because the "NewMails" queue is not synchronised. It is because it is new queue. Only this thread uses new queue yet, it is not + //connected to account mail queue. + // CallService(MS_YAMN_FILTERMAIL,(WPARAM)ActualAccount,(LPARAM)MsgQueuePtr); + FilterMailSvc((WPARAM)ActualAccount,(LPARAM)MsgQueuePtr); + + if(DataRX!=NULL) + free(DataRX); + DataRX=NULL; + + //MsgQueuePtr->MailData->Body=MyClient->Retr(MsgQueuePtr->Number); + + MsgQueuePtr=MsgQueuePtr->Next; + + } + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write wait\n"); + #endif + if(WAIT_OBJECT_0!=MsgsWaitToWrite(ActualAccount)) + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write wait failed\n"); + #endif + throw (DWORD)ActualAccount->SystemError==EACC_STOPPED; + } + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write enter\n"); + #endif + if(ActualAccount->Mails==NULL) + ActualAccount->Mails=NewMails; + else + { + ActualAccount->LastMail=ActualAccount->LastChecked; + AppendQueue((HYAMNMAIL)ActualAccount->Mails,NewMails); + } + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write done\n"); + #endif + MsgsWriteDone(ActualAccount); + + // we are going to delete mails having SPAM flag level3 and 4 (see m_mails.h) set + { + struct DeleteParam ParamToDeleteMails={YAMN_DELETEVERSION,INVALID_HANDLE_VALUE,ActualAccount,YAMNParam,(void *)POP3_DELETEFROMCHECK}; + + // Delete mails from server. Here we should not be in write access for account's mails + DeleteMailsPOP3(&ParamToDeleteMails); + } + + // if there is no waiting thread for internet connection close it + // else leave connection open + if(0==SCGetNumber(ActualAccount->InternetQueries)) + { + DataRX=MyClient->Quit(); + if(DataRX!=NULL) + free(DataRX); + DataRX=NULL; + MyClient->NetClient->Disconnect(); + + SetAccountStatus(ActualAccount,Translate("Disconnected")); + } + + UsingInternet=FALSE; + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:InternetFreeEV-done\n"); + #endif + SetEvent(ActualAccount->UseInternetFree); + + ActualAccount->LastSChecked=ActualAccount->LastChecked; + ActualAccount->LastSynchronised=ActualAccount->LastChecked; + } + catch(...) + { + throw; //go to the main exception handling + } + + { + YAMN_MAILBROWSERPARAM Param={(HANDLE)0,ActualAccount,ActualCopied.NFlags,ActualCopied.NNFlags,YAMNParam}; + + if(CheckFlags & YAMN_FORCECHECK) + Param.nnflags|=YAMN_ACC_POP; //if force check, show popup anyway and if mailbrowser was opened, do not close + Param.nnflags|= YAMN_ACC_MSGP; //do not close browser if already open + CallService(MS_YAMN_MAILBROWSER,(WPARAM)&Param,(LPARAM)YAMN_MAILBROWSERVERSION); + } + SetContactStatus(ActualAccount,ActualAccount->isCounting?ID_STATUS_ONLINE:ID_STATUS_OFFLINE); + } + #ifdef DEBUG_COMM + catch(DWORD ErrorCode) + #else + catch(DWORD) + #endif + { + if(ActualAccount->Client.POP3Error==EPOP3_STOPPED) + ActualAccount->SystemError=EACC_STOPPED; + #ifdef DEBUG_COMM + DebugLog(CommFile,"ERROR: %x\n",ErrorCode); + #endif + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write wait\n"); + #endif + if(WAIT_OBJECT_0==MsgsWaitToWrite(ActualAccount)) + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write enter\n"); + #endif + ActualAccount->LastChecked=now; + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write done\n"); + #endif + MsgsWriteDone(ActualAccount); + } + #ifdef DEBUG_SYNCHRO + else + DebugLog(SynchroFile,"CheckPOP3:ActualAccountMsgsSO-write wait failed\n"); + #endif + + DeleteMIMEQueue(ActualAccount,NewMails); + + if(DataRX!=NULL) + free(DataRX); + DataRX=NULL; + switch(ActualAccount->SystemError) + { + case EACC_QUEUEALLOC: + case EACC_STOPPED: + ActualAccount->Client.NetClient->Disconnect(); + break; + default: + PostErrorProc(ActualAccount,YAMNParam,(DWORD)NULL,MyClient->SSL); //it closes internet connection too + } + + if(UsingInternet) //if our thread still uses internet + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:InternetFreeEV-done\n"); + #endif + SetEvent(ActualAccount->UseInternetFree); + } + SetContactStatus(ActualAccount,ID_STATUS_NA); + } + free(ActualCopied.ServerName); + free(ActualCopied.ServerLogin); + free(ActualCopied.ServerPasswd); + #ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); + #endif +// WriteAccounts(); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:Decrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount); + #endif + SCDec(ActualAccount->UsingThreads); + return 0; +} + +DWORD WINAPI DeleteMailsPOP3(struct DeleteParam *WhichTemp) +{ + HPOP3ACCOUNT ActualAccount; + LPVOID YAMNParam; + UINT_PTR POP3PluginParam; + CPop3Client *MyClient; + HYAMNMAIL DeleteMails,NewMails=NULL,MsgQueuePtr; + char* DataRX=NULL; + int mboxsize,msgs,i; + BOOL UsingInternet=FALSE; + struct { + char *ServerName; + DWORD ServerPort; + char *ServerLogin; + char *ServerPasswd; + DWORD Flags; + DWORD NFlags; + DWORD NNFlags; + } ActualCopied; + + //First, we should compare our version of DeleteParam structure, but here it is not needed, because YAMN and internal plugin + //have the same version. But your plugin should do that in this way: + // if(((struct DeleteParam *)WhichTemp)->Ver!=YAMN_DELETEVERSION) + // { + // SetEvent(((struct DeleteParam *)WhichTemp)->ThreadRunningEV); //don't forget to unblock YAMN + // return (DWORD)-1; //ok, but we should return value. + // //When our plugin returns e.g. 0xFFFFFFFF (this is only our plugin value, YAMN does nothing with return value, + // //but only tests if it is nonzero. If yes, it calls GetErrorStringFcn), we know problem occured in YAMN incompatibility + // //and then we can in our GetErrorStringFcn e.g. return string "Uncompatible version of YAMN". + // } + + ActualAccount=(HPOP3ACCOUNT)((struct DeleteParam *)WhichTemp)->AccountParam; //copy address of structure from calling thread to stack of this thread + YAMNParam=((struct DeleteParam *)WhichTemp)->BrowserParam; + POP3PluginParam=(UINT_PTR)((struct DeleteParam *)WhichTemp)->CustomParam; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:Incrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount); +#endif + SCInc(ActualAccount->UsingThreads); + if(INVALID_HANDLE_VALUE!=WhichTemp->ThreadRunningEV) + SetEvent(WhichTemp->ThreadRunningEV); + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountSO-read wait\n"); +#endif + if(WAIT_OBJECT_0!=WaitToRead(ActualAccount)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountSO-read wait failed\n"); +#endif +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:Decrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount); +#endif + SCDec(ActualAccount->UsingThreads); + return 0; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountSO-read enter\n"); +#endif + if(NULL==(DeleteMails=(HYAMNMAIL)CreateNewDeleteQueue((HYAMNMAIL)ActualAccount->Mails))) //if there's no mail for deleting, return + { + if(POP3_DELETEFROMCHECK!=POP3PluginParam) //We do not wait for free internet when calling from SynchroPOP3. It is because UseInternetFree is blocked + { + YAMN_MAILBROWSERPARAM Param={(HANDLE)0,ActualAccount,YAMN_ACC_MSGP,YAMN_ACC_MSGP,YAMNParam}; //Just update the window + + CallService(MS_YAMN_MAILBROWSER,(WPARAM)&Param,(LPARAM)YAMN_MAILBROWSERVERSION); + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountSO-read done\n"); +#endif + ReadDone(ActualAccount); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:Decrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount); +#endif + SCDec(ActualAccount->UsingThreads); + + return NO_MAIL_FOR_DELETE; + } + MyClient=&(ActualAccount->Client); + +//Now, copy all needed information about account to local variables, so ActualAccount is not blocked in read mode during all connection process, which can last for several minutes. + ActualCopied.ServerName=_strdup(ActualAccount->Server->Name); + ActualCopied.ServerPort=ActualAccount->Server->Port; + ActualCopied.Flags=ActualAccount->Flags; + ActualCopied.ServerLogin=_strdup(ActualAccount->Server->Login); + ActualCopied.ServerPasswd=_strdup(ActualAccount->Server->Passwd); + ActualCopied.NFlags=ActualAccount->NewMailN.Flags; + ActualCopied.NNFlags=ActualAccount->NoNewMailN.Flags; + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountSO-read done\n"); +#endif + ReadDone(ActualAccount); + + SCInc(ActualAccount->InternetQueries); //This is POP3-internal SCOUNTER, we set another thread wait for this account to be connected to inet + if(POP3_DELETEFROMCHECK!=POP3PluginParam) //We do not wait for free internet when calling from SynchroPOP3. It is because UseInternetFree is blocked + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:InternetFreeEV-wait\n"); +#endif + WaitForSingleObject(ActualAccount->UseInternetFree,INFINITE); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:InternetFreeEV-enter\n"); +#endif + } + SCDec(ActualAccount->InternetQueries); + UsingInternet=TRUE; + + try + { + SetContactStatus(ActualAccount,ID_STATUS_OCCUPIED); +#ifdef DEBUG_COMM + DebugLog(CommFile,"<--------Communication-------->\n"); +#endif + if((MyClient->NetClient==NULL) || !MyClient->NetClient->Connected()) + { + SetAccountStatus(ActualAccount,Translate("Connecting to server")); + + DataRX=MyClient->Connect(ActualCopied.ServerName,ActualCopied.ServerPort,ActualCopied.Flags & YAMN_ACC_SSL23,ActualCopied.Flags & YAMN_ACC_NOTLS); + + char *timestamp=NULL; + if(DataRX!=NULL) { + if(ActualAccount->Flags & YAMN_ACC_APOP) { + char *lpos=strchr(DataRX,'<'); + char *rpos=strchr(DataRX,'>'); + if(lpos && rpos && rpos>lpos) { + int sz=(int)(rpos-lpos+2); + timestamp=new char[sz]; + memcpy(timestamp, lpos, sz-1); + timestamp[sz-1]='\0'; + } + } + free(DataRX); + DataRX=NULL; + } + SetAccountStatus(ActualAccount,Translate("Entering POP3 account")); + + if(ActualAccount->Flags & YAMN_ACC_APOP) + { + DataRX=MyClient->APOP(ActualCopied.ServerLogin,ActualCopied.ServerPasswd,timestamp); + if(DataRX!=NULL) + free(DataRX); + DataRX=NULL; + delete[] timestamp; + } else { + DataRX=MyClient->User(ActualCopied.ServerLogin); + if(DataRX!=NULL) + free(DataRX); + DataRX=NULL; + DataRX=MyClient->Pass(ActualCopied.ServerPasswd); + if(DataRX!=NULL) + free(DataRX); + DataRX=NULL; + } + } + +#ifdef DEBUG_DECODE + DebugLog(DecodeFile,"<--------Deleting requested mails-------->\n"); +#endif + if(POP3_DELETEFROMCHECK!=POP3PluginParam) //We do not need to get mails on server as we have already it from check function + { + SetAccountStatus(ActualAccount,Translate("Deleting requested mails")); + + DataRX=MyClient->Stat(); + +#ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); +#endif + ExtractStat(DataRX,MyClient->NetClient->Rcv,&mboxsize,&msgs); +#ifdef DEBUG_DECODE + DebugLog(DecodeFile,"%d\n",mboxsize); + DebugLog(DecodeFile,"%d\n",msgs); + DebugLog(DecodeFile,"\n"); +#endif + if(DataRX!=NULL) + free(DataRX); + DataRX=NULL; + for(i=0;iNext=(HYAMNMAIL)CallService(MS_YAMN_CREATEACCOUNTMAIL,(WPARAM)ActualAccount,(LPARAM)YAMN_MAILVERSION); + MsgQueuePtr=MsgQueuePtr->Next; + } + if(MsgQueuePtr==NULL) + { + ActualAccount->SystemError=EPOP3_QUEUEALLOC; + throw (DWORD)ActualAccount->SystemError; + } + } + + if(msgs) + { +#ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); +#endif + DataRX=MyClient->Uidl(); + ExtractUIDL(DataRX,MyClient->NetClient->Rcv,NewMails); +#ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); +#endif + if(DataRX!=NULL) + free(DataRX); + DataRX=NULL; +// we get "new mails" on server (NewMails will contain all mails on server not found in DeleteMails) +// but also in DeleteMails we get only those, which are still on server with their responsable numbers + SynchroMessages(ActualAccount,(HYAMNMAIL *)&DeleteMails,NULL,(HYAMNMAIL *)&NewMails,NULL); + } + } + else + SetAccountStatus(ActualAccount,Translate("Deleting spam")); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountMsgsSO-write wait\n"); +#endif + if(WAIT_OBJECT_0!=MsgsWaitToWrite(ActualAccount)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountMsgsSO-write wait failed\n"); +#endif + throw (DWORD)EACC_STOPPED; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountMsgsSO-write enter\n"); +#endif + if(msgs || POP3_DELETEFROMCHECK==POP3PluginParam) + { + try + { + HYAMNMAIL Temp; + + for(i=0,MsgQueuePtr=DeleteMails;MsgQueuePtr!=NULL;i++) + { + if(!(MsgQueuePtr->Flags & YAMN_MSG_VIRTUAL)) //of course we can only delete real mails, not virtual + { + DataRX=MyClient->Dele(MsgQueuePtr->Number); + Temp=MsgQueuePtr->Next; + if(POP3_FOK==MyClient->AckFlag) //if server answers that mail was deleted + { + DeleteMIMEMessage((HYAMNMAIL *)&DeleteMails,MsgQueuePtr); + HYAMNMAIL DeletedMail=FindMIMEMessageByID((HYAMNMAIL)ActualAccount->Mails,MsgQueuePtr->ID); + if((MsgQueuePtr->Flags & YAMN_MSG_MEMDELETE)) //if mail should be deleted from memory (or disk) + { + DeleteMIMEMessage((HYAMNMAIL *)&ActualAccount->Mails,DeletedMail); //remove from queue + CallService(MS_YAMN_DELETEACCOUNTMAIL,(WPARAM)POP3Plugin,(LPARAM)DeletedMail); + } + else //else mark it only as "deleted mail" + { + DeletedMail->Flags |= (YAMN_MSG_VIRTUAL | YAMN_MSG_DELETED); + DeletedMail->Flags &= ~(YAMN_MSG_NEW | YAMN_MSG_USERDELETE | YAMN_MSG_AUTODELETE); //clear "new mail" + } + delete MsgQueuePtr->MailData; + delete[] MsgQueuePtr->ID; + delete MsgQueuePtr; + } + MsgQueuePtr=Temp; + + if(DataRX!=NULL) + free(DataRX); + DataRX=NULL; + } + else + MsgQueuePtr=MsgQueuePtr->Next; + } + } + catch(...) //if any exception in the code where we have write-access to account occured, don't forget to leave write-access + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountMsgsSO-write done\n"); +#endif + MsgsWriteDone(ActualAccount); + throw; //and go to the main exception handling + } + + if(NewMails!=NULL) +// in ActualAccount->Mails we have all mails stored before calling this function +// in NewMails we have all mails not found in DeleteMails (in other words: we performed new ID checking and we +// stored all mails found on server, then we deleted the ones we wanted to delete in this function +// and NewMails queue now contains actual state of mails on server). But we will not use NewMails as actual state, because NewMails does not contain header data (subject, from...) +// We perform deleting from ActualAccount->Mails: we remove from original queue (ActualAccount->Mails) all deleted mails + SynchroMessages(ActualAccount,(HYAMNMAIL *)&ActualAccount->Mails,NULL,(HYAMNMAIL *)&NewMails,NULL); +// Now ActualAccount->Mails contains all mails when calling this function except the ones, we wanted to delete (these are in DeleteMails) +// And in NewMails we have new mails (if any) + else if(POP3_DELETEFROMCHECK!=POP3PluginParam) + { + DeleteMIMEQueue(ActualAccount,(HYAMNMAIL)ActualAccount->Mails); + ActualAccount->Mails=NULL; + } + } + else + { + DeleteMIMEQueue(ActualAccount,(HYAMNMAIL)ActualAccount->Mails); + ActualAccount->Mails=NULL; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:ActualAccountMsgsSO-write done\n"); +#endif + MsgsWriteDone(ActualAccount); +#ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); +#endif + +// TODO: now, we have in NewMails new mails. If NewMails is not NULL, we found some new mails, so Checking for new mail should be performed +// now, we do not call CheckPOP3 + +// if there is no waiting thread for internet connection close it +// else leave connection open +// if this functin was called from SynchroPOP3, then do not try to disconnect + if(POP3_DELETEFROMCHECK!=POP3PluginParam) + { + YAMN_MAILBROWSERPARAM Param={(HANDLE)0,ActualAccount,ActualCopied.NFlags,YAMN_ACC_MSGP,YAMNParam}; + + CallService(MS_YAMN_MAILBROWSER,(WPARAM)&Param,(LPARAM)YAMN_MAILBROWSERVERSION); + + if(0==SCGetNumber(ActualAccount->InternetQueries)) + { + DataRX=MyClient->Quit(); + if(DataRX!=NULL) + free(DataRX); + DataRX=NULL; + MyClient->NetClient->Disconnect(); + + SetAccountStatus(ActualAccount,Translate("Disconnected")); + } + + UsingInternet=FALSE; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:InternetFreeEV-done\n"); +#endif + SetEvent(ActualAccount->UseInternetFree); + } + SetContactStatus(ActualAccount,ActualAccount->isCounting?ID_STATUS_ONLINE:ID_STATUS_OFFLINE); + } +#ifdef DEBUG_COMM + catch(DWORD ErrorCode) +#else + catch(DWORD) +#endif + { + if(ActualAccount->Client.POP3Error==EPOP3_STOPPED) + ActualAccount->SystemError=EACC_STOPPED; +#ifdef DEBUG_COMM + DebugLog(CommFile,"ERROR %x\n",ErrorCode); +#endif + if(DataRX!=NULL) + free(DataRX); + switch(ActualAccount->SystemError) + { + case EACC_QUEUEALLOC: + case EACC_STOPPED: + ActualAccount->Client.NetClient->Disconnect(); + break; + default: + PostErrorProc(ActualAccount,YAMNParam,POP3PluginParam,MyClient->SSL); //it closes internet connection too + } + + if(UsingInternet && (POP3_DELETEFROMCHECK!=POP3PluginParam)) //if our thread still uses internet and it is needed to release internet + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"CheckPOP3:InternetFreeEV-done\n"); +#endif + SetEvent(ActualAccount->UseInternetFree); + } + } + + free(ActualCopied.ServerName); + free(ActualCopied.ServerLogin); + free(ActualCopied.ServerPasswd); + + DeleteMIMEQueue(ActualAccount,NewMails); + DeleteMIMEQueue(ActualAccount,DeleteMails); + +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif +// WriteAccounts(); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"DeleteMailsPOP3:Decrementing \"using threads\" %x (account %x)\n",ActualAccount->UsingThreads,ActualAccount); +#endif + SCDec(ActualAccount->UsingThreads); + return 0; +} + +void ExtractStat(char *stream,int len,int *mboxsize,int *mails) +{ + char *finder=stream; + while(WS(finder) || ENDLINE(finder)) finder++; + if(ACKLINE(finder)) + { + while(!WS(finder)) finder++; + while(WS(finder)) finder++; + } + if(1!=sscanf(finder,"%d",mails)) + throw (DWORD)EPOP3_STAT; + while(!WS(finder)) finder++; + while(WS(finder)) finder++; + if(1!=sscanf(finder,"%d",mboxsize)) + throw (DWORD)EPOP3_STAT; +} +void ExtractMail(char *stream,int len,HYAMNMAIL queue) +{ + char *finder=stream; + char *finderend; + int msgnr,i; + HYAMNMAIL queueptr=queue; + + while(WS(finder) || ENDLINE(finder)) finder++; + while(!ACKLINE(finder)) finder++; + while(!ENDLINE(finder)) finder++; //now we at the end of first ack line + while(finder<=(stream+len)) + { + while(ENDLINE(finder)) finder++; //go to the new line + if(DOTLINE(finder+1)) //at the end of stream + break; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + while(WS(finder)) finder++; //jump whitespace + if(1!=sscanf(finder,"%d",&msgnr)) + throw (DWORD)EPOP3_UIDL; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"%d\n",msgnr); + #endif +// for(i=1,queueptr=queue;(queueptr->Next!=NULL) && (iNext,i++); +// if(i!=msgnr) +// throw (DWORD)EPOP3_UIDL; + while(!WS(finder)) finder++; //jump characters + while(WS(finder)) finder++; //jump whitespace + finderend=finder+1; + while(!WS(finderend) && !ENDLINE(finderend)) finderend++; + queueptr->ID=new char[finderend-finder+1]; + for(i=0;finder!=finderend;finder++,i++) + queueptr->MailData->Body[i]=*finder; + queueptr->MailData->Body[i]=0; //ends string + queueptr->Number=msgnr; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"%s\n",queueptr->MailData->Body); + DebugLog(DecodeFile,"\n"); + #endif + queueptr=queueptr->Next; + while(!ENDLINE(finder)) finder++; + } +} + +void ExtractUIDL(char *stream,int len,HYAMNMAIL queue) +{ + char *finder=stream; + char *finderend; + int msgnr,i; + HYAMNMAIL queueptr=queue; + + while(WS(finder) || ENDLINE(finder)) finder++; + while(!ACKLINE(finder)) finder++; + while(!ENDLINE(finder)) finder++; //now we at the end of first ack line + while(finder<=(stream+len)) + { + while(ENDLINE(finder)) finder++; //go to the new line + if(DOTLINE(finder+1)) //at the end of stream + break; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n"); + #endif + while(WS(finder)) finder++; //jump whitespace + if(1!=sscanf(finder,"%d",&msgnr)) + throw (DWORD)EPOP3_UIDL; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"%d\n",msgnr); + #endif +// for(i=1,queueptr=queue;(queueptr->Next!=NULL) && (iNext,i++); +// if(i!=msgnr) +// throw (DWORD)EPOP3_UIDL; + while(!WS(finder)) finder++; //jump characters + while(WS(finder)) finder++; //jump whitespace + finderend=finder+1; + while(!WS(finderend) && !ENDLINE(finderend)) finderend++; + queueptr->ID=new char[finderend-finder+1]; + for(i=0;finder!=finderend;finder++,i++) + queueptr->ID[i]=*finder; + queueptr->ID[i]=0; //ends string + queueptr->Number=msgnr; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"%s\n",queueptr->ID); + DebugLog(DecodeFile,"\n"); + #endif + queueptr=queueptr->Next; + while(!ENDLINE(finder)) finder++; + } +} + +void ExtractList(char *stream,int len,HYAMNMAIL queue) +{ + char *finder=stream; + char *finderend; + int msgnr,i; + HYAMNMAIL queueptr; + + while(WS(finder) || ENDLINE(finder)) finder++; + while(!ACKLINE(finder)) finder++; + while(!ENDLINE(finder)) finder++; //now we at the end of first ack line + while(finder<=(stream+len)) + { + while(ENDLINE(finder)) finder++; //go to the new line + if(DOTLINE(finder+1)) //at the end of stream + break; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"\n",NULL,0); + #endif + while(WS(finder)) finder++; //jump whitespace + if(1!=sscanf(finder,"%d",&msgnr)) //message nr. + throw (DWORD)EPOP3_LIST; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"%d\n",msgnr); + #endif + + for(i=1,queueptr=queue;(queueptr->Next!=NULL) && (iNext,i++); + if(i!=msgnr) + throw (DWORD)EPOP3_LIST; + while(!WS(finder)) finder++; //jump characters + while(WS(finder)) finder++; //jump whitespace + finderend=finder+1; + if(1!=sscanf(finder,"%d",&queueptr->MailData->Size)) + throw (DWORD)EPOP3_LIST; + #ifdef DEBUG_DECODE + DebugLog(DecodeFile,"%d\n",queueptr->MailData->Size); + #endif + while(!ENDLINE(finder)) finder++; + } +} + +WCHAR* WINAPI GetErrorString(DWORD Code) +{ + static char *POP3Errors[]= + { + "Memory allocation error.", //memory allocation + "Account is about to be stopped.", //stop account + "Cannot connect to POP3 server.", + "Cannot allocate memory for received data.", + "Cannot login to POP3 server.", + "Bad user or password.", + "Server does not support APOP authorization.", + "Error while executing POP3 command.", + "Error while executing POP3 command.", + "Error while executing POP3 command.", + }; + + static char *NetlibErrors[]= + { + "Cannot connect to server with NetLib.", + "Cannot send data.", + "Cannot receive data.", + "Cannot allocate memory for received data.", + }; + + static char *SSLErrors[]= + { + "OpenSSL not loaded.", + "Windows socket 2.0 init failed.", + "DNS lookup error.", + "Error while creating base socket.", + "Error connecting to server with socket.", + "Error while creating SSL structure.", + "Error connecting socket with SSL.", + "Server rejected connection with SSL.", + "Cannot write SSL data.", + "Cannot read SSL data.", + "Cannot allocate memory for received data.", + }; + + char *ErrorStringA=new char[ERRORSTR_MAXLEN]; + WCHAR *ErrorStringW=new WCHAR[ERRORSTR_MAXLEN]; + POP3_ERRORCODE *ErrorCode=(POP3_ERRORCODE *)(UINT_PTR)Code; + + sprintf(ErrorStringA,Translate("Error %d-%d-%d-%d:"),ErrorCode->AppError,ErrorCode->POP3Error,ErrorCode->NetError,ErrorCode->SystemError); + if(ErrorCode->POP3Error) + sprintf(ErrorStringA,"%s\n%s",ErrorStringA,Translate(POP3Errors[ErrorCode->POP3Error-1])); + if(ErrorCode->NetError) + if(ErrorCode->SSL) + sprintf(ErrorStringA,"%s\n%s",ErrorStringA,Translate(SSLErrors[ErrorCode->NetError-1])); + else + sprintf(ErrorStringA,"%s\n%s",ErrorStringA,Translate(NetlibErrors[ErrorCode->NetError-4])); + +#ifdef DEBUG_COMM + DebugLog(CommFile,"%s\n",ErrorStringA); +#endif + MultiByteToWideChar(CP_ACP,MB_USEGLYPHCHARS,ErrorStringA,-1,ErrorStringW,(int)strlen(ErrorStringA)+1); + delete[] ErrorStringA; //we delete ErrorStringA, used to get error string, because Translate() doesn't works in unicode + delete ErrorCode; //now we can delete ErrorCode, that will not be used anymore + return ErrorStringW; +} + +void WINAPI DeleteErrorString(LPVOID String) +{ + delete (char *)String; +} diff --git a/yamn/proto/pop3/pop3comm.h b/yamn/proto/pop3/pop3comm.h new file mode 100644 index 0000000..0d30e5d --- /dev/null +++ b/yamn/proto/pop3/pop3comm.h @@ -0,0 +1,97 @@ +#ifndef __POP3COMM_H +#define __POP3COMM_H + +#include +#include "pop3.h" + +#include "../../m_protoplugin.h" +//We can use synchro.h because this is internal plugin. If you use external plugin, +//and you want to use SO for your plugin, you can use YAMN's SO. +//All you need is to include synchro.h and use YAMN's exported synchronization functions. +#include "../../m_synchro.h" + +//For mail exported functions defintions +#include "../../mails/m_mails.h" + +#include "../../debug.h" + +#define POP3_FILEVERSION 1 //Version of aditional information stored in book file + +typedef struct CPOP3Account: public CAccount +{ +// We can use SCOUNTER structure, because this is internal plugin. +// This SO is used to determine if any POP3 account is in "write access" mode + static PSCOUNTER AccountWriterSO; + +// It is usefull to have client structure in account. With this structure we have access to account's socket. +// This is related to InternetQueries and UseInternetFree +// This member should be synchronized with UseInternetFree + class CPop3Client Client; + +// This member is usefull for MIME headers. It is default codepage, if no other codepage found + WORD CP; //access only through AccountAccessSO + +// In this memeber last error code is stored + DWORD SystemError; //access through UseInternetFree + +// We use only counter from this object and it is # of threads waiting to work on internet. +// We use event UseInternet to access critical sections. +// It is usefull in 2 ways: we have mutual exclusion that only one thread works with account on internet. +// Thread, which has done its work with account on internet can close socket, but it is not needed, when any other +// thread wants to work (e.g. we have deleted mails, but when deleting, another thread wants to check new mail, so +// we delete all needed mails and check if there's thread that wants to work. If yes, we do not need to quit session, +// we leave socket open, and leave internet. Another thread then start checking and does not connect, does not send +// user and password... because socket is open- it continues) + PSCOUNTER InternetQueries; + HANDLE UseInternetFree; + + CPOP3Account(); + ~CPOP3Account(); + +} POP3ACCOUNT,*HPOP3ACCOUNT; + +typedef struct POP3LayeredError +{ + BOOL SSL; + DWORD AppError; + DWORD POP3Error; + DWORD NetError; + DWORD SystemError; +} POP3_ERRORCODE,*PPOP3_ERRORCODE; + +struct YAMNExportedFcns +{ + YAMN_SETPROTOCOLPLUGINFCNIMPORTFCN SetProtocolPluginFcnImportFcn; + YAMN_WAITTOWRITEFCN WaitToWriteFcn; + YAMN_WRITEDONEFCN WriteDoneFcn; + YAMN_WAITTOREADFCN WaitToReadFcn; + YAMN_READDONEFCN ReadDoneFcn; + YAMN_SCMANAGEFCN SCGetNumberFcn; + YAMN_SCMANAGEFCN SCIncFcn; + YAMN_SCMANAGEFCN SCDecFcn; + YAMN_SETSTATUSFCN SetStatusFcn; + YAMN_GETSTATUSFCN GetStatusFcn; +}; + +struct MailExportedFcns +{ + YAMN_SYNCHROMIMEMSGSFCN SynchroMessagesFcn; + YAMN_TRANSLATEHEADERFCN TranslateHeaderFcn; + YAMN_APPENDQUEUEFCN AppendQueueFcn; + YAMN_DELETEMIMEQUEUEFCN DeleteMessagesToEndFcn; + YAMN_DELETEMIMEMESSAGEFCN DeleteMessageFromQueueFcn; + YAMN_FINDMIMEMESSAGEFCN FindMessageByIDFcn; + YAMN_CREATENEWDELETEQUEUEFCN CreateNewDeleteQueueFcn; +}; + +enum +{ + EACC_QUEUEALLOC=1, //memory allocation + EACC_STOPPED, //stop account +}; + +#define NO_MAIL_FOR_DELETE 1 + +#define POP3_DELETEFROMCHECK 1 + +#endif diff --git a/yamn/proto/pop3/pop3opt.cpp b/yamn/proto/pop3/pop3opt.cpp new file mode 100644 index 0000000..004d2aa --- /dev/null +++ b/yamn/proto/pop3/pop3opt.cpp @@ -0,0 +1,1671 @@ +/* + * This code implements POP3 options window handling + * + * (c) majvan 2002-2003 +*/ + +/* +#include +#include +#include +#include +#include +#include "../../../../../SDK/headers_c/newpluginapi.h" +//#include "../../../../random/utils/m_utils.h" //for window broadcasting +#include "../../../../../SDK/headers_c/m_langpack.h" +#include "../../../../../SDK/headers_c/m_options.h" +#include "../../../../../SDK/headers_c/m_utils.h" +#include "../../SDK/import/m_popup.h" +#include "../../m_protoplugin.h" +#include "../../m_synchro.h" +#include "../../m_messages.h" +#include "../../resources/resource.h" +#include "../../m_yamn.h" +#include "../../debug.h" +*/ +#include "../../yamn.h" +#include "../../main.h" +#include "pop3comm.h" +#include "pop3opt.h" +#include "uxtheme.h" + +//- imported --------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +extern PLUGINLINK *pluginLink; +extern PYAMN_VARIABLES pYAMNVar; +extern HYAMNPROTOPLUGIN POP3Plugin; +extern struct YAMNExportedFcns *pYAMNFcn; +extern YAMN_VARIABLES YAMNVar; + +extern HICON hYamnIcons[]; + +extern DWORD WINAPI WritePOP3Accounts(); +extern DWORD HotKeyThreadID; +extern LPCRITICAL_SECTION PluginRegCS; +//From filterplugin.cpp +extern PYAMN_FILTERPLUGINQUEUE FirstFilterPlugin; +//From protoplugin.cpp +extern PYAMN_PROTOPLUGINQUEUE FirstProtoPlugin; +//for XP themes +extern BOOL (WINAPI *MyEnableThemeDialogTexture)(HANDLE, DWORD); + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + + +BOOL Check0,Check1,Check2,Check3,Check4,Check5,Check6,Check7,Check8,Check9; +TCHAR DlgInput[MAX_PATH]; + +//Fuction took from Miranda +void WordToModAndVk(WORD w,UINT *mod,UINT *vk); + +//Initializes YAMN general options for Miranda +int YAMNOptInitSvc(WPARAM wParam,LPARAM lParam); + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +void WordToModAndVk(WORD w,UINT *mod,UINT *vk) +{ + *mod=0; + if(HIBYTE(w)&HOTKEYF_CONTROL) *mod|=MOD_CONTROL; + if(HIBYTE(w)&HOTKEYF_SHIFT) *mod|=MOD_SHIFT; + if(HIBYTE(w)&HOTKEYF_ALT) *mod|=MOD_ALT; + if(HIBYTE(w)&HOTKEYF_EXT) *mod|=MOD_WIN; + *vk=LOBYTE(w); +} + + +INT_PTR CALLBACK DlgProcYAMNOpt(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam) +{ + switch(msg) + { + case WM_INITDIALOG: + TranslateDialogDefault(hDlg); + CheckDlgButton(hDlg,IDC_CHECKTTB,DBGetContactSettingByte(NULL,YAMN_DBMODULE,YAMN_TTBFCHECK,1) ? BST_CHECKED : BST_UNCHECKED); + SendDlgItemMessage(hDlg,IDC_HKFORCE,HKM_SETHOTKEY,DBGetContactSettingWord(NULL,YAMN_DBMODULE,YAMN_HKCHECKMAIL,YAMN_DEFAULTHK),0); + CheckDlgButton(hDlg,IDC_LONGDATE,(optDateTime&SHOWDATELONG) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_SMARTDATE,(optDateTime&SHOWDATENOTODAY) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_NOSECONDS,(optDateTime&SHOWDATENOSECONDS) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_MAINMENU,DBGetContactSettingByte(NULL, YAMN_DBMODULE, YAMN_SHOWMAINMENU, 0)); + CheckDlgButton(hDlg,IDC_YAMNASPROTO,DBGetContactSettingByte(NULL, YAMN_DBMODULE, YAMN_SHOWASPROTO, 0)); + CheckDlgButton(hDlg,IDC_CLOSEONDELETE,DBGetContactSettingByte(NULL, YAMN_DBMODULE, YAMN_CLOSEDELETE, 0)); + + break; + case WM_COMMAND: + { + WORD wNotifyCode = HIWORD(wParam); + switch(LOWORD(wParam)) + { + case IDC_YAMNASPROTO: + case IDC_MAINMENU: + case IDC_CHECKTTB: + case IDC_HKFORCE: + case IDC_CLOSEONDELETE: + case IDC_LONGDATE: + case IDC_SMARTDATE: + case IDC_NOSECONDS: + SendMessage(GetParent(hDlg),PSM_CHANGED,0,0); + break; + + } + break; + } + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->idFrom) + { + case 0: + switch(((LPNMHDR)lParam)->code) + { + case PSN_APPLY: + { + WORD ForceHotKey =(WORD)SendDlgItemMessage(hDlg,IDC_HKFORCE,HKM_GETHOTKEY,0,0); + BYTE TTBFCheck =(BYTE)IsDlgButtonChecked(hDlg,IDC_CHECKTTB); + BYTE MainMenu = (BYTE)IsDlgButtonChecked(hDlg,IDC_MAINMENU); + BYTE CloseDelete = (BYTE)IsDlgButtonChecked(hDlg,IDC_CLOSEONDELETE); + BYTE ShowAsProto = (BYTE)IsDlgButtonChecked(hDlg,IDC_YAMNASPROTO); + UINT mod,vk; + + DBWriteContactSettingByte(NULL,YAMN_DBMODULE,YAMN_SHOWASPROTO,ShowAsProto); + DBWriteContactSettingWord(NULL,YAMN_DBMODULE,YAMN_HKCHECKMAIL,ForceHotKey); + DBWriteContactSettingByte(NULL,YAMN_DBMODULE,YAMN_TTBFCHECK,TTBFCheck); + DBWriteContactSettingByte(NULL,YAMN_DBMODULE,YAMN_SHOWMAINMENU,MainMenu); + DBWriteContactSettingByte(NULL,YAMN_DBMODULE,YAMN_CLOSEDELETE,CloseDelete); + WordToModAndVk(ForceHotKey,&mod,&vk); + PostThreadMessage(HotKeyThreadID,WM_YAMN_CHANGEHOTKEY,(WPARAM)mod,(LPARAM)vk); + + optDateTime = 0; + if (IsDlgButtonChecked(hDlg,IDC_LONGDATE))optDateTime |= SHOWDATELONG; + if (IsDlgButtonChecked(hDlg,IDC_SMARTDATE))optDateTime |= SHOWDATENOTODAY; + if (IsDlgButtonChecked(hDlg,IDC_NOSECONDS))optDateTime |= SHOWDATENOSECONDS; + DBWriteContactSettingByte(NULL,YAMN_DBMODULE,YAMN_DBTIMEOPTIONS,optDateTime); + } + } + } + break; + } + + return FALSE; +} + +INT_PTR CALLBACK DlgProcPluginOpt(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam) +{ + switch(msg) + { + case WM_INITDIALOG: + TranslateDialogDefault(hDlg); + break; + case WM_COMMAND: + { + WORD wNotifyCode = HIWORD(wParam); + switch(LOWORD(wParam)) + { + case IDC_COMBOPLUGINS: + if(wNotifyCode==CBN_SELCHANGE) + { + HWND hCombo=GetDlgItem(hDlg,IDC_COMBOPLUGINS); + PYAMN_PROTOPLUGINQUEUE PParser; + PYAMN_FILTERPLUGINQUEUE FParser; + int index,id; + + if(CB_ERR==(index=SendMessage(hCombo,CB_GETCURSEL,0,0))) + break; + id=SendMessage(hCombo,CB_GETITEMDATA,(WPARAM)index,(LPARAM)0); + EnterCriticalSection(PluginRegCS); + for(PParser=FirstProtoPlugin;PParser!=NULL;PParser=PParser->Next) + if(id==(INT_PTR)PParser->Plugin) + { + SetDlgItemText(hDlg,IDC_STVER,PParser->Plugin->PluginInfo->Ver); + SetDlgItemText(hDlg,IDC_STDESC,PParser->Plugin->PluginInfo->Description == NULL ? "" : PParser->Plugin->PluginInfo->Description); + SetDlgItemText(hDlg,IDC_STCOPY,PParser->Plugin->PluginInfo->Copyright == NULL ? "" : PParser->Plugin->PluginInfo->Copyright); + SetDlgItemText(hDlg,IDC_STMAIL,PParser->Plugin->PluginInfo->Email == NULL ? "" : PParser->Plugin->PluginInfo->Email); + SetDlgItemText(hDlg,IDC_STWWW,PParser->Plugin->PluginInfo->WWW == NULL ? "" : PParser->Plugin->PluginInfo->WWW); + break; + } + for(FParser=FirstFilterPlugin;FParser!=NULL;FParser=FParser->Next) + if(id==(INT_PTR)FParser->Plugin) + { + SetDlgItemText(hDlg,IDC_STVER,FParser->Plugin->PluginInfo->Ver); + SetDlgItemText(hDlg,IDC_STDESC,FParser->Plugin->PluginInfo->Description == NULL ? "" : FParser->Plugin->PluginInfo->Description); + SetDlgItemText(hDlg,IDC_STCOPY,FParser->Plugin->PluginInfo->Copyright == NULL ? "" : FParser->Plugin->PluginInfo->Copyright); + SetDlgItemText(hDlg,IDC_STMAIL,FParser->Plugin->PluginInfo->Email == NULL ? "" : FParser->Plugin->PluginInfo->Email); + SetDlgItemText(hDlg,IDC_STWWW,FParser->Plugin->PluginInfo->WWW == NULL ? "" : FParser->Plugin->PluginInfo->WWW); + break; + } + LeaveCriticalSection(PluginRegCS); + } + break; + case IDC_STWWW: + { + char str[1024]; + + GetDlgItemText(hDlg,IDC_STWWW,str,sizeof(str)); + CallService(MS_UTILS_OPENURL,1,(LPARAM)str); + break; + } + + } + break; + } + case WM_SHOWWINDOW: + if(TRUE==(BOOL)wParam) + { + PYAMN_PROTOPLUGINQUEUE PParser; + PYAMN_FILTERPLUGINQUEUE FParser; + int index; + + EnterCriticalSection(PluginRegCS); + for(PParser=FirstProtoPlugin;PParser!=NULL;PParser=PParser->Next) + { + index=SendDlgItemMessage(hDlg,IDC_COMBOPLUGINS,CB_ADDSTRING,0,(LPARAM)PParser->Plugin->PluginInfo->Name); + index=SendDlgItemMessage(hDlg,IDC_COMBOPLUGINS,CB_SETITEMDATA,(WPARAM)index,(LPARAM)PParser->Plugin); + } + for(FParser=FirstFilterPlugin;FParser!=NULL;FParser=FParser->Next) + { + index=SendDlgItemMessage(hDlg,IDC_COMBOPLUGINS,CB_ADDSTRING,0,(LPARAM)FParser->Plugin->PluginInfo->Name); + index=SendDlgItemMessage(hDlg,IDC_COMBOPLUGINS,CB_SETITEMDATA,(WPARAM)index,(LPARAM)FParser->Plugin); + } + + LeaveCriticalSection(PluginRegCS); + SendDlgItemMessage(hDlg,IDC_COMBOPLUGINS,CB_SETCURSEL,(WPARAM)0,(LPARAM)0); + SendMessage(hDlg,WM_COMMAND,MAKELONG(IDC_COMBOPLUGINS,CBN_SELCHANGE),(LPARAM)NULL); + break; + } + else //delete all items in combobox + { + int cbn=SendDlgItemMessage(hDlg,IDC_COMBOPLUGINS,CB_GETCOUNT,(WPARAM)0,(LPARAM)0); + + for(int i=0;iStatusFlags & YAMN_ACC_ST0 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST1,ActualAccount->StatusFlags & YAMN_ACC_ST1 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST2,ActualAccount->StatusFlags & YAMN_ACC_ST2 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST3,ActualAccount->StatusFlags & YAMN_ACC_ST3 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST4,ActualAccount->StatusFlags & YAMN_ACC_ST4 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST5,ActualAccount->StatusFlags & YAMN_ACC_ST5 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST6,ActualAccount->StatusFlags & YAMN_ACC_ST6 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST7,ActualAccount->StatusFlags & YAMN_ACC_ST7 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST8,ActualAccount->StatusFlags & YAMN_ACC_ST8 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST9,ActualAccount->StatusFlags & YAMN_ACC_ST9 ? BST_CHECKED : BST_UNCHECKED); + ReadDone(ActualAccount); + } + else + { + CheckDlgButton(hDlg,IDC_CHECKST0,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST1,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKST2,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST3,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST4,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST5,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST6,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST7,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKST8,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKST9,BST_CHECKED); + } + return TRUE; +} +BOOL DlgShowAccountPopup(HWND hDlg,WPARAM wParam,LPARAM lParam) +{ + HPOP3ACCOUNT ActualAccount=(HPOP3ACCOUNT)lParam; + + if((DWORD)wParam==M_SHOWACTUAL) + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:SHOWACCOUNT:ActualAccountSO-read wait\n"); + #endif + WaitToRead(ActualAccount); //we do not need to check if account is deleted. It is not deleted, because only thread that can delete account is this thread + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:SHOWACCOUNT:ActualAccountSO-read enter\n"); + #endif + SetDlgItemInt(hDlg,IDC_EDITPOPS,ActualAccount->NewMailN.PopUpTime,FALSE); + SetDlgItemInt(hDlg,IDC_EDITNPOPS,ActualAccount->NoNewMailN.PopUpTime,FALSE); + SetDlgItemInt(hDlg,IDC_EDITFPOPS,ActualAccount->BadConnectN.PopUpTime,FALSE); + + + CheckDlgButton(hDlg,IDC_CHECKPOP,ActualAccount->NewMailN.Flags & YAMN_ACC_POP ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKCOL,ActualAccount->NewMailN.Flags & YAMN_ACC_POPC ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKNPOP,ActualAccount->NoNewMailN.Flags & YAMN_ACC_POP ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKNCOL,ActualAccount->NoNewMailN.Flags & YAMN_ACC_POPC ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKFPOP,ActualAccount->BadConnectN.Flags & YAMN_ACC_POP ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKFCOL,ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_RADIOPOPN,ActualAccount->Flags & YAMN_ACC_POPN ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_RADIOPOP1,ActualAccount->Flags & YAMN_ACC_POPN ? BST_UNCHECKED : BST_CHECKED); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:SHOWACCOUNT:ActualAccountSO-read done\n"); + #endif + ReadDone(ActualAccount); + } + else //default + { + + SetDlgItemInt(hDlg,IDC_EDITPOPS,0,FALSE); + SetDlgItemInt(hDlg,IDC_EDITNPOPS,0,FALSE); + SetDlgItemInt(hDlg,IDC_EDITFPOPS,0,FALSE); + CheckDlgButton(hDlg,IDC_CHECKPOP,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKCOL,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKNPOP,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKNCOL,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKFPOP,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKFCOL,BST_CHECKED); + CheckDlgButton(hDlg,IDC_RADIOPOPN,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_RADIOPOP1,BST_CHECKED); + } + return TRUE; +} +BOOL DlgShowAccount(HWND hDlg,WPARAM wParam,LPARAM lParam) +{ + HPOP3ACCOUNT ActualAccount=(HPOP3ACCOUNT)lParam; + int i; + + if((DWORD)wParam==M_SHOWACTUAL) + { + TCHAR accstatus[256]; + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:SHOWACCOUNT:ActualAccountSO-read wait\n"); + #endif + WaitToRead(ActualAccount); //we do not need to check if account is deleted. It is not deleted, because only thread that can delete account is this thread + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:SHOWACCOUNT:ActualAccountSO-read enter\n"); + #endif + DlgSetItemText(hDlg,(WPARAM)IDC_EDITSERVER,(LPARAM)ActualAccount->Server->Name); + DlgSetItemText(hDlg,(WPARAM)IDC_EDITNAME,(LPARAM)ActualAccount->Name); + DlgSetItemText(hDlg,(WPARAM)IDC_EDITLOGIN,(LPARAM)ActualAccount->Server->Login); + DlgSetItemText(hDlg,(WPARAM)IDC_EDITPASS,(LPARAM)ActualAccount->Server->Passwd); + DlgSetItemTextW(hDlg,(WPARAM)IDC_EDITAPP,(LPARAM)ActualAccount->NewMailN.App); + DlgSetItemTextW(hDlg,(WPARAM)IDC_EDITAPPPARAM,(LPARAM)ActualAccount->NewMailN.AppParam); + SetDlgItemInt(hDlg,IDC_EDITPORT,ActualAccount->Server->Port,FALSE); + SetDlgItemInt(hDlg,IDC_EDITINTERVAL,ActualAccount->Interval/60,FALSE); + SetDlgItemInt(hDlg,IDC_EDITPOPS,ActualAccount->NewMailN.PopUpTime,FALSE); + SetDlgItemInt(hDlg,IDC_EDITNPOPS,ActualAccount->NoNewMailN.PopUpTime,FALSE); + SetDlgItemInt(hDlg,IDC_EDITFPOPS,ActualAccount->BadConnectN.PopUpTime,FALSE); + for(i=0;i<=CPLENSUPP;i++) + if((iCP)) + { + SendMessage(GetDlgItem(hDlg,IDC_COMBOCP),CB_SETCURSEL,(WPARAM)i,(LPARAM)0); + break; + } + if(i==CPLENSUPP) + SendMessage(GetDlgItem(hDlg,IDC_COMBOCP),CB_SETCURSEL,(WPARAM)CPDEFINDEX,(LPARAM)0); + + CheckDlgButton(hDlg,IDC_CHECK,ActualAccount->Flags & YAMN_ACC_ENA ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKSND,ActualAccount->NewMailN.Flags & YAMN_ACC_SND ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKMSG,ActualAccount->NewMailN.Flags & YAMN_ACC_MSG ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKICO,ActualAccount->NewMailN.Flags & YAMN_ACC_ICO ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKPOP,ActualAccount->NewMailN.Flags & YAMN_ACC_POP ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKCOL,ActualAccount->NewMailN.Flags & YAMN_ACC_POPC ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKAPP,ActualAccount->NewMailN.Flags & YAMN_ACC_APP ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKKBN,ActualAccount->NewMailN.Flags & YAMN_ACC_KBN ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKNPOP,ActualAccount->NoNewMailN.Flags & YAMN_ACC_POP ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKNCOL,ActualAccount->NoNewMailN.Flags & YAMN_ACC_POPC ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKNMSGP,ActualAccount->NoNewMailN.Flags & YAMN_ACC_MSGP ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKFSND,ActualAccount->BadConnectN.Flags & YAMN_ACC_SND ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKFMSG,ActualAccount->BadConnectN.Flags & YAMN_ACC_MSG ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKFICO,ActualAccount->BadConnectN.Flags & YAMN_ACC_ICO ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKFPOP,ActualAccount->BadConnectN.Flags & YAMN_ACC_POP ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKFCOL,ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_RADIOPOPN,ActualAccount->Flags & YAMN_ACC_POPN ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_RADIOPOP1,ActualAccount->Flags & YAMN_ACC_POPN ? BST_UNCHECKED : BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKSSL,ActualAccount->Flags & YAMN_ACC_SSL23 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKNOTLS,ActualAccount->Flags & YAMN_ACC_NOTLS ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKAPOP,ActualAccount->Flags & YAMN_ACC_APOP ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_AUTOBODY,ActualAccount->Flags & YAMN_ACC_BODY ? BST_CHECKED : BST_UNCHECKED); + /*CheckDlgButton(hDlg,IDC_CHECKST0,ActualAccount->StatusFlags & YAMN_ACC_ST0 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST1,ActualAccount->StatusFlags & YAMN_ACC_ST1 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST2,ActualAccount->StatusFlags & YAMN_ACC_ST2 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST3,ActualAccount->StatusFlags & YAMN_ACC_ST3 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST4,ActualAccount->StatusFlags & YAMN_ACC_ST4 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST5,ActualAccount->StatusFlags & YAMN_ACC_ST5 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST6,ActualAccount->StatusFlags & YAMN_ACC_ST6 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST7,ActualAccount->StatusFlags & YAMN_ACC_ST7 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST8,ActualAccount->StatusFlags & YAMN_ACC_ST8 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST9,ActualAccount->StatusFlags & YAMN_ACC_ST9 ? BST_CHECKED : BST_UNCHECKED);*/ + Check0=ActualAccount->StatusFlags & YAMN_ACC_ST0; + Check1=ActualAccount->StatusFlags & YAMN_ACC_ST1; + Check2=ActualAccount->StatusFlags & YAMN_ACC_ST2; + Check3=ActualAccount->StatusFlags & YAMN_ACC_ST3; + Check4=ActualAccount->StatusFlags & YAMN_ACC_ST4; + Check5=ActualAccount->StatusFlags & YAMN_ACC_ST5; + Check6=ActualAccount->StatusFlags & YAMN_ACC_ST6; + Check7=ActualAccount->StatusFlags & YAMN_ACC_ST7; + Check8=ActualAccount->StatusFlags & YAMN_ACC_ST8; + Check9=ActualAccount->StatusFlags & YAMN_ACC_ST9; + CheckDlgButton(hDlg,IDC_CHECKSTART,ActualAccount->StatusFlags & YAMN_ACC_STARTS ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKFORCE,ActualAccount->StatusFlags & YAMN_ACC_FORCE ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKCONTACT,ActualAccount->NewMailN.Flags & YAMN_ACC_CONT ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKCONTACTNICK,ActualAccount->NewMailN.Flags & YAMN_ACC_CONTNICK ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKCONTACTNOEVENT,ActualAccount->NewMailN.Flags & YAMN_ACC_CONTNOEVENT ? BST_CHECKED : BST_UNCHECKED); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:SHOWACCOUNT:ActualAccountSO-read done\n"); +#endif + GetAccountStatus(ActualAccount,accstatus); + SetDlgItemText(hDlg,IDC_STSTATUS,accstatus); + ReadDone(ActualAccount); + } + else //default + { + DlgSetItemText(hDlg,(WPARAM)IDC_EDITSERVER,(LPARAM)NULL); + DlgSetItemText(hDlg,(WPARAM)IDC_EDITNAME,(LPARAM)NULL); + DlgSetItemText(hDlg,(WPARAM)IDC_EDITLOGIN,(LPARAM)NULL); + DlgSetItemText(hDlg,(WPARAM)IDC_EDITPASS,(LPARAM)NULL); + DlgSetItemText(hDlg,(WPARAM)IDC_EDITAPP,(LPARAM)NULL); + DlgSetItemText(hDlg,(WPARAM)IDC_EDITAPPPARAM,(LPARAM)NULL); + DlgSetItemText(hDlg,(WPARAM)IDC_STTIMELEFT,(LPARAM)NULL); + SetDlgItemInt(hDlg,IDC_EDITPORT,110,FALSE); + SetDlgItemInt(hDlg,IDC_EDITINTERVAL,10,FALSE); + SetDlgItemInt(hDlg,IDC_EDITPOPS,0,FALSE); + SetDlgItemInt(hDlg,IDC_EDITNPOPS,0,FALSE); + SetDlgItemInt(hDlg,IDC_EDITFPOPS,0,FALSE); + SendMessage(GetDlgItem(hDlg,IDC_COMBOCP),CB_SETCURSEL,(WPARAM)CPDEFINDEX,(LPARAM)0); + CheckDlgButton(hDlg,IDC_CHECK,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKSND,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKMSG,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKICO,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKPOP,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKCOL,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKAPP,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKPOP,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKCOL,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKFSND,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKFMSG,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKFICO,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKFPOP,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKFCOL,BST_CHECKED); + /*CheckDlgButton(hDlg,IDC_CHECKST0,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST1,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKST2,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST3,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST4,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST5,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST6,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKST7,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKST8,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKST9,BST_CHECKED);*/ + CheckDlgButton(hDlg,IDC_CHECKSTART,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKFORCE,BST_CHECKED); + CheckDlgButton(hDlg,IDC_RADIOPOPN,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_RADIOPOP1,BST_CHECKED); + CheckDlgButton(hDlg,IDC_CHECKSSL,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKNOTLS,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CHECKAPOP,BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_AUTOBODY,BST_UNCHECKED); + + SetDlgItemText(hDlg,IDC_STSTATUS,TranslateT("No account selected")); + } + return TRUE; +} + +BOOL DlgShowAccountColors(HWND hDlg,WPARAM wParam,LPARAM lParam) +{ + HPOP3ACCOUNT ActualAccount=(HPOP3ACCOUNT)lParam; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:SHOWACCOUNTCOLORS:ActualAccountSO-read wait\n"); +#endif + WaitToRead(ActualAccount); //we do not need to check if account is deleted. It is not deleted, because only thread that can delete account is this thread +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:SHOWACCOUNTCOLORS:ActualAccountSO-read enter\n"); +#endif + if(ActualAccount->NewMailN.Flags & YAMN_ACC_POPC) + { + SendDlgItemMessage(hDlg,IDC_CPB,CPM_SETCOLOUR,0,(LPARAM)ActualAccount->NewMailN.PopUpB); + SendDlgItemMessage(hDlg,IDC_CPT,CPM_SETCOLOUR,0,(LPARAM)ActualAccount->NewMailN.PopUpT); + } + else + { + SendDlgItemMessage(hDlg,IDC_CPB,CPM_SETCOLOUR,0,(LPARAM)GetSysColor(COLOR_BTNFACE)); + SendDlgItemMessage(hDlg,IDC_CPT,CPM_SETCOLOUR,0,(LPARAM)GetSysColor(COLOR_WINDOWTEXT)); + } + if(ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC) + { + SendDlgItemMessage(hDlg,IDC_CPFB,CPM_SETCOLOUR,0,(LPARAM)ActualAccount->BadConnectN.PopUpB); + SendDlgItemMessage(hDlg,IDC_CPFT,CPM_SETCOLOUR,0,(LPARAM)ActualAccount->BadConnectN.PopUpT); + } + else + { + SendDlgItemMessage(hDlg,IDC_CPFB,CPM_SETCOLOUR,0,(LPARAM)GetSysColor(COLOR_BTNFACE)); + SendDlgItemMessage(hDlg,IDC_CPFT,CPM_SETCOLOUR,0,(LPARAM)GetSysColor(COLOR_WINDOWTEXT)); + } + if(ActualAccount->NoNewMailN.Flags & YAMN_ACC_POPC) + { + SendDlgItemMessage(hDlg,IDC_CPNB,CPM_SETCOLOUR,0,(LPARAM)ActualAccount->NoNewMailN.PopUpB); + SendDlgItemMessage(hDlg,IDC_CPNT,CPM_SETCOLOUR,0,(LPARAM)ActualAccount->NoNewMailN.PopUpT); + } + else + { + SendDlgItemMessage(hDlg,IDC_CPNB,CPM_SETCOLOUR,0,(LPARAM)GetSysColor(COLOR_BTNFACE)); + SendDlgItemMessage(hDlg,IDC_CPNT,CPM_SETCOLOUR,0,(LPARAM)GetSysColor(COLOR_WINDOWTEXT)); + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:SHOWACCOUNTCOLORS:ActualAccountSO-read done\n"); +#endif + ReadDone(ActualAccount); //we do not need to check if account is deleted. It is not deleted, because only thread that can delete account is this thread + return TRUE; +} + +BOOL DlgSetItemText(HWND hDlg,WPARAM wParam,LPARAM lParam) +{ + if((TCHAR*)lParam==NULL) + SetDlgItemText(hDlg,(UINT)wParam,_T("")); + else + SetDlgItemText(hDlg,(UINT)wParam,(TCHAR *)lParam); + return TRUE; +} + +BOOL DlgSetItemTextW(HWND hDlg,WPARAM wParam,LPARAM lParam) +{ + if((WCHAR*)lParam==NULL) + SetDlgItemTextW(hDlg,(UINT)wParam,(LPWSTR)L""); + else + SetDlgItemTextW(hDlg,(UINT)wParam,(LPWSTR)lParam); + return TRUE; +} + +BOOL CALLBACK DlgProcPOP3AccStatusOpt(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam) +{ + static HPOP3ACCOUNT ActualAccount; + switch(msg) + { + case WM_INITDIALOG: + { + ActualAccount=(HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)DlgInput); + if(ActualAccount != NULL) + { + DlgShowAccountStatus(hDlg,(WPARAM)M_SHOWACTUAL,(LPARAM)ActualAccount); + DlgEnableAccountStatus(hDlg,(WPARAM)TRUE,(LPARAM)TRUE); + } + TranslateDialogDefault(hDlg); + SendMessage(GetParent(hDlg),PSM_UNCHANGED,(WPARAM)hDlg,0); + return TRUE; + break; + } + case WM_COMMAND: + { + + WORD wNotifyCode = HIWORD(wParam); + switch(LOWORD(wParam)) + { + case IDOK: + Check0=(IsDlgButtonChecked(hDlg,IDC_CHECKST0)==BST_CHECKED); + Check1=(IsDlgButtonChecked(hDlg,IDC_CHECKST1)==BST_CHECKED); + Check2=(IsDlgButtonChecked(hDlg,IDC_CHECKST2)==BST_CHECKED); + Check3=(IsDlgButtonChecked(hDlg,IDC_CHECKST3)==BST_CHECKED); + Check4=(IsDlgButtonChecked(hDlg,IDC_CHECKST4)==BST_CHECKED); + Check5=(IsDlgButtonChecked(hDlg,IDC_CHECKST5)==BST_CHECKED); + Check6=(IsDlgButtonChecked(hDlg,IDC_CHECKST6)==BST_CHECKED); + Check7=(IsDlgButtonChecked(hDlg,IDC_CHECKST7)==BST_CHECKED); + Check8=(IsDlgButtonChecked(hDlg,IDC_CHECKST8)==BST_CHECKED); + Check9=(IsDlgButtonChecked(hDlg,IDC_CHECKST9)==BST_CHECKED); + WindowList_BroadcastAsync(YAMNVar.MessageWnds,WM_YAMN_CHANGESTATUSOPTION,(WPARAM)0,(LPARAM)0); + EndDialog(hDlg,0); + DestroyWindow(hDlg); + break; + + case IDCANCEL: + EndDialog(hDlg,0); + DestroyWindow(hDlg); + break; + + default: + break; + } + } + default: + break; + } + return FALSE; +} + + +INT_PTR CALLBACK DlgProcPOP3AccOpt(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam) +{ + BOOL Changed=FALSE; + static BOOL InList=FALSE; + static HPOP3ACCOUNT ActualAccount; + static UCHAR ActualStatus; +// static struct CPOP3Options POP3Options; + + switch(msg) + { + case WM_INITDIALOG: + { + int i; + + EnableWindow(GetDlgItem(hDlg,IDC_BTNDEL),FALSE); + + DlgEnableAccount(hDlg,(WPARAM)FALSE,(LPARAM)FALSE); + DlgShowAccount(hDlg,(WPARAM)M_SHOWDEFAULT,0); + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:INITDIALOG:AccountBrowserSO-read wait\n"); + #endif + WaitToReadSO(POP3Plugin->AccountBrowserSO); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:INITDIALOG:AccountBrowserSO-read enter\n"); + #endif + //SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_ADDSTRING,0,(LPARAM)""); //this was in YAMN.rc initialisation but seems to be useless + if(POP3Plugin->FirstAccount!=NULL) + for(ActualAccount=(HPOP3ACCOUNT)POP3Plugin->FirstAccount;ActualAccount!=NULL;ActualAccount=(HPOP3ACCOUNT)ActualAccount->Next) + if(ActualAccount->Name!=NULL) + SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_ADDSTRING,0,(LPARAM)ActualAccount->Name); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:INITDIALOG:AccountBrowserSO-read done\n"); + #endif + ReadDoneSO(POP3Plugin->AccountBrowserSO); + SendDlgItemMessage(hDlg,IDC_COMBOCP,CB_ADDSTRING,0,(LPARAM)TranslateT("Default")); + for(i=1;iMessageWnds,hDlg); + SendMessage(GetParent(hDlg),PSM_UNCHANGED,(WPARAM)hDlg,(LPARAM)0); + } + else + WindowList_Add(pYAMNVar->MessageWnds,hDlg,NULL); + return TRUE; + case WM_YAMN_CHANGESTATUS: + { + char accstatus[256]; + + if((HPOP3ACCOUNT)wParam!=ActualAccount) + break; + GetAccountStatus(ActualAccount,accstatus); + SetDlgItemTextA(hDlg,IDC_STSTATUS,accstatus); + return TRUE; + } + + case WM_YAMN_CHANGESTATUSOPTION: + { + Changed=TRUE; + SendMessage(GetParent(hDlg),PSM_CHANGED,0,0); + return TRUE; + } + + case WM_YAMN_CHANGETIME: + if((HPOP3ACCOUNT)wParam==ActualAccount) + { + TCHAR Text[256]; + _stprintf(Text,Translate("Time left to next check [s]: %d"),(DWORD)lParam); + SetDlgItemText(hDlg,IDC_STTIMELEFT,Text); + } + return TRUE; + case WM_COMMAND: + { + WORD wNotifyCode = HIWORD(wParam); + switch(LOWORD(wParam)) + { + LONG Result; + case IDC_COMBOACCOUNT: + switch(wNotifyCode) + { + case CBN_EDITCHANGE : + ActualAccount=NULL; + DlgSetItemText(hDlg,(WPARAM)IDC_STTIMELEFT,(LPARAM)NULL); + + if(GetDlgItemText(hDlg,IDC_COMBOACCOUNT,DlgInput,sizeof(DlgInput)/sizeof(TCHAR))) + DlgEnableAccount(hDlg,(WPARAM)TRUE,(LPARAM)FALSE); + else + DlgEnableAccount(hDlg,(WPARAM)FALSE,(LPARAM)FALSE); + break; + case CBN_KILLFOCUS: + GetDlgItemText(hDlg,IDC_COMBOACCOUNT,DlgInput,sizeof(DlgInput)/sizeof(TCHAR)); + if(NULL==(ActualAccount=(HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)DlgInput))) + { + DlgSetItemText(hDlg,(WPARAM)IDC_STTIMELEFT,(LPARAM)NULL); + EnableWindow(GetDlgItem(hDlg,IDC_BTNDEL),FALSE); + if(lstrlen(DlgInput)) + DlgEnableAccount(hDlg,(WPARAM)TRUE,(LPARAM)TRUE); + else + DlgEnableAccount(hDlg,(WPARAM)FALSE,(LPARAM)FALSE); + } + else + { + DlgShowAccount(hDlg,(WPARAM)M_SHOWACTUAL,(LPARAM)ActualAccount); + DlgEnableAccount(hDlg,(WPARAM)TRUE,(LPARAM)TRUE); + EnableWindow(GetDlgItem(hDlg,IDC_BTNDEL),TRUE); + } + break; + case CBN_SELCHANGE: + if(CB_ERR!=(Result=SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_GETCURSEL,0,0))) + SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_GETLBTEXT,(WPARAM)Result,(LPARAM)DlgInput); + + if((Result==CB_ERR) || (NULL==(ActualAccount=(HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)DlgInput)))) + { + DlgSetItemText(hDlg,(WPARAM)IDC_STTIMELEFT,(LPARAM)NULL); + EnableWindow(GetDlgItem(hDlg,IDC_BTNDEL),FALSE); + } + else + { + DlgShowAccount(hDlg,(WPARAM)M_SHOWACTUAL,(LPARAM)ActualAccount); + DlgEnableAccount(hDlg,(WPARAM)TRUE,(LPARAM)FALSE); + EnableWindow(GetDlgItem(hDlg,IDC_BTNDEL),TRUE); + } + break; + } + break; + case IDC_COMBOCP: + { + int sel = SendDlgItemMessage(hDlg,IDC_COMBOCP,CB_GETCURSEL,0,0); + CPINFOEX info; GetCPInfoEx(CodePageNamesSupp[sel].CP,0,&info); + DlgSetItemText(hDlg,(WPARAM)IDC_STSTATUS,(LPARAM)info.CodePageName); + } + case IDC_CHECK: + case IDC_CHECKSND: + case IDC_CHECKMSG: + case IDC_CHECKICO: + case IDC_CHECKFSND: + case IDC_CHECKFMSG: + case IDC_CHECKFICO: + case IDC_CHECKST0: + case IDC_CHECKST1: + case IDC_CHECKST2: + case IDC_CHECKST3: + case IDC_CHECKST4: + case IDC_CHECKST5: + case IDC_CHECKST6: + case IDC_CHECKST7: + case IDC_CHECKST8: + case IDC_CHECKST9: + case IDC_CHECKSTART: + case IDC_CHECKFORCE: + case IDC_EDITAPPPARAM: + case IDC_CHECKAPOP: + case IDC_AUTOBODY: + case IDC_CHECKCONTACTNICK: + case IDC_CHECKCONTACTNOEVENT: + case IDC_CHECKNOTLS: + Changed=TRUE; + break; + case IDC_CHECKCONTACT: + Changed=IsDlgButtonChecked(hDlg,IDC_CHECKCONTACT)==BST_CHECKED; + EnableWindow(GetDlgItem(hDlg,IDC_CHECKCONTACTNICK),Changed); + EnableWindow(GetDlgItem(hDlg,IDC_CHECKCONTACTNOEVENT),Changed); + Changed=TRUE; + break; + case IDC_CHECKSSL: + { + BOOL SSLC=(IsDlgButtonChecked(hDlg,IDC_CHECKSSL)==BST_CHECKED); + SetDlgItemInt(hDlg,IDC_EDITPORT,SSLC ? 995 : 110,FALSE); + EnableWindow(GetDlgItem(hDlg,IDC_CHECKNOTLS),SSLC?0:1); + } + Changed=TRUE; + break; + case IDC_CPB: + case IDC_CPT: + case IDC_CPFB: + case IDC_CPFT: + case IDC_CPNB: + case IDC_CPNT: + if(HIWORD(wParam)!=CPN_COLOURCHANGED) + break; + case IDC_CHECKKBN: + Changed=TRUE; + break; + case IDC_CHECKAPP: + Changed=TRUE; + EnableWindow(GetDlgItem(hDlg,IDC_BTNAPP),IsDlgButtonChecked(hDlg,IDC_CHECKAPP)==BST_CHECKED); + EnableWindow(GetDlgItem(hDlg,IDC_EDITAPP),IsDlgButtonChecked(hDlg,IDC_CHECKAPP)==BST_CHECKED); + EnableWindow(GetDlgItem(hDlg,IDC_EDITAPPPARAM),IsDlgButtonChecked(hDlg,IDC_CHECKAPP)==BST_CHECKED); + break; + case IDC_BTNSTATUS: + { + DialogBoxParamW(pYAMNVar->hInst,MAKEINTRESOURCEW(IDD_CHOOSESTATUSMODES),hDlg,(DLGPROC)DlgProcPOP3AccStatusOpt,(LPARAM)NULL); + break; + } + + case IDC_BTNADD: + { + int index=0; + DlgSetItemText(hDlg,(WPARAM)IDC_STTIMELEFT,(LPARAM)NULL); + DlgShowAccount(hDlg,(WPARAM)M_SHOWDEFAULT,0); + DlgEnableAccount(hDlg,(WPARAM)TRUE,(LPARAM)TRUE); + EnableWindow(GetDlgItem(hDlg,IDC_BTNDEL),FALSE); + DlgSetItemText(hDlg,(WPARAM)IDC_EDITNAME,(LPARAM)TranslateT("New Account")); + index=SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_ADDSTRING,0,(LPARAM)TranslateT("New Account")); + + if((index==CB_ERR) || (index==CB_ERRSPACE)) + break; + SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_SETCURSEL,(WPARAM)index,(LPARAM)TranslateT("New Account")); + break; + } + + case IDC_BTNAPP: + { + OPENFILENAME OFNStruct; + + memset(&OFNStruct,0,sizeof(OPENFILENAME)); + OFNStruct.lStructSize=sizeof(OPENFILENAME); + OFNStruct.hwndOwner=hDlg; + OFNStruct.lpstrFilter=_T("Executables (*.exe;*.bat;*.cmd;*.com)\0*.exe;*.bat;*.cmd;*.com\0All Files (*.*)\0*.*\0"); + OFNStruct.nFilterIndex=1; + OFNStruct.nMaxFile=MAX_PATH; + OFNStruct.lpstrFile=new TCHAR[MAX_PATH]; + OFNStruct.lpstrFile[0]=(TCHAR)0; + OFNStruct.lpstrTitle=Translate("Select executable used for notification"); + OFNStruct.Flags=OFN_FILEMUSTEXIST | OFN_NONETWORKBUTTON | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR; + if(!GetOpenFileName(&OFNStruct)) + { + if(CommDlgExtendedError()) + MessageBox(hDlg,_T("Dialog box error"),_T("Failed"),MB_OK); + } + else + DlgSetItemText(hDlg,(WPARAM)IDC_EDITAPP,(LPARAM)OFNStruct.lpstrFile); + delete[] OFNStruct.lpstrFile; + break; + } + case IDC_BTNDEFAULT: + DlgShowAccount(hDlg,(WPARAM)M_SHOWDEFAULT,0); +// DlgShowAccountColors(hDlg,0,(LPARAM)ActualAccount); + break; + case IDC_BTNDEL: + GetDlgItemText(hDlg,IDC_COMBOACCOUNT,DlgInput,sizeof(DlgInput)/sizeof(TCHAR)); + EnableWindow(GetDlgItem(hDlg,IDC_BTNDEL),FALSE); + if((CB_ERR==(Result=SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_GETCURSEL,0,0))) + || (NULL==(ActualAccount=(HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)DlgInput)))) + return TRUE; + + if(IDOK!=MessageBox(hDlg,Translate("Do you really want to delete this account?"),Translate("Delete account confirmation"),MB_OKCANCEL | MB_ICONWARNING)) + return TRUE; + + DlgSetItemText(hDlg,(WPARAM)IDC_STTIMELEFT,(LPARAM)Translate("Please wait while no account is in use.")); + + if(ActualAccount->hContact != NULL) + CallService(MS_DB_CONTACT_DELETE,(WPARAM)(HANDLE) ActualAccount->hContact, 0); + + CallService(MS_YAMN_DELETEACCOUNT,(WPARAM)POP3Plugin,(LPARAM)ActualAccount); + + //We can consider our account as deleted. + + SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_DELETESTRING,(WPARAM)Result,0); + DlgSetItemText(hDlg,(WPARAM)IDC_COMBOACCOUNT,(LPARAM)NULL); + DlgEnableAccount(hDlg,(WPARAM)FALSE,0); + DlgShowAccount(hDlg,(WPARAM)M_SHOWDEFAULT,0); +// Beep(100,50); + break; + case IDC_BTNRESET: + if(ActualAccount!=NULL) + ActualAccount->TimeLeft=ActualAccount->Interval; + return 1; + } + if(HIWORD(wParam)==EN_CHANGE) + Changed=TRUE; + break; + } + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->idFrom) + { + case 0: + switch(((LPNMHDR)lParam)->code) + { + case PSN_APPLY: + { + TCHAR Text[MAX_PATH]; + WCHAR TextW[MAX_PATH]; + BOOL Translated,NewAcc=FALSE,Check,CheckMsg,CheckSnd,CheckIco,CheckApp, CheckAPOP; + BOOL CheckNMsgP,CheckFMsg,CheckFSnd,CheckFIco; + BOOL CheckKBN, CheckContact,CheckContactNick,CheckContactNoEvent; + BOOL CheckSSL, CheckABody, CheckNoTLS; + //BOOL Check0,Check1,Check2,Check3,Check4,Check5,Check6,Check7,Check8,Check9, + BOOL CheckStart,CheckForce; + size_t Length,index; + UINT Port,Interval; + + if(GetDlgItemText(hDlg,IDC_COMBOACCOUNT,Text,sizeof(Text)/sizeof(TCHAR))) + { + Check=(IsDlgButtonChecked(hDlg,IDC_CHECK)==BST_CHECKED); + CheckSSL=(IsDlgButtonChecked(hDlg,IDC_CHECKSSL)==BST_CHECKED); + CheckNoTLS=(IsDlgButtonChecked(hDlg,IDC_CHECKNOTLS)==BST_CHECKED); + CheckAPOP=(IsDlgButtonChecked(hDlg,IDC_CHECKAPOP)==BST_CHECKED); + + CheckABody=(IsDlgButtonChecked(hDlg,IDC_AUTOBODY)==BST_CHECKED); + CheckMsg=(IsDlgButtonChecked(hDlg,IDC_CHECKMSG)==BST_CHECKED); + CheckSnd=(IsDlgButtonChecked(hDlg,IDC_CHECKSND)==BST_CHECKED); + CheckIco=(IsDlgButtonChecked(hDlg,IDC_CHECKICO)==BST_CHECKED); + + CheckApp=(IsDlgButtonChecked(hDlg,IDC_CHECKAPP)==BST_CHECKED); + CheckKBN=(IsDlgButtonChecked(hDlg,IDC_CHECKKBN)==BST_CHECKED); + CheckContact=(IsDlgButtonChecked(hDlg,IDC_CHECKCONTACT)==BST_CHECKED); + CheckContactNick=(IsDlgButtonChecked(hDlg,IDC_CHECKCONTACTNICK)==BST_CHECKED); + CheckContactNoEvent=(IsDlgButtonChecked(hDlg,IDC_CHECKCONTACTNOEVENT)==BST_CHECKED); + + CheckFSnd=(IsDlgButtonChecked(hDlg,IDC_CHECKFSND)==BST_CHECKED); + CheckFMsg=(IsDlgButtonChecked(hDlg,IDC_CHECKFMSG)==BST_CHECKED); + CheckFIco=(IsDlgButtonChecked(hDlg,IDC_CHECKFICO)==BST_CHECKED); + + CheckNMsgP=(IsDlgButtonChecked(hDlg,IDC_CHECKNMSGP)==BST_CHECKED); + + Port=GetDlgItemInt(hDlg,IDC_EDITPORT,&Translated,FALSE); + if(!Translated) + { + MessageBox(hDlg,Translate("This is not a valid number value"),Translate("Input error"),MB_OK); + SetFocus(GetDlgItem(hDlg,IDC_EDITPORT)); + break; + } + Interval=GetDlgItemInt(hDlg,IDC_EDITINTERVAL,&Translated,FALSE); + if(!Translated) + { + MessageBox(hDlg,Translate("This is not a valid number value"),Translate("Input error"),MB_OK); + SetFocus(GetDlgItem(hDlg,IDC_EDITINTERVAL)); + break; + } + + GetDlgItemText(hDlg,IDC_EDITAPP,Text,sizeof(Text)/sizeof(TCHAR)); + if(CheckApp && !(Length=_tcslen(Text))) + { + MessageBox(hDlg,TranslateT("Please select application to run"),TranslateT("Input error"),MB_OK); + break; + } + + GetDlgItemText(hDlg,IDC_COMBOACCOUNT,Text,sizeof(Text)/sizeof(TCHAR)); + if(!(Length=_tcslen(Text))) + GetDlgItemText(hDlg,IDC_EDITNAME,Text,sizeof(Text)/sizeof(TCHAR)); + if(!(Length=_tcslen(Text))) + break; + + DlgSetItemText(hDlg,(WPARAM)IDC_STTIMELEFT,(LPARAM)TranslateT("Please wait while no account is in use.")); + + if(NULL==(ActualAccount=(HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)Text))) + { + NewAcc=TRUE; + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:APPLY:AccountBrowserSO-write wait\n"); + #endif + WaitToWriteSO(POP3Plugin->AccountBrowserSO); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:APPLY:AccountBrowserSO-write enter\n"); + #endif + if(NULL==(ActualAccount=(HPOP3ACCOUNT)CallService(MS_YAMN_GETNEXTFREEACCOUNT,(WPARAM)POP3Plugin,(LPARAM)YAMN_ACCOUNTVERSION))) + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:APPLY:AccountBrowserSO-write done\n"); + #endif + WriteDoneSO(POP3Plugin->AccountBrowserSO); + MessageBox(hDlg,Translate("Cannot allocate memory space for new account"),Translate("Memory error"),MB_OK); + break; + } + } + else + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:APPLY:AccountBrowserSO-write wait\n"); + #endif + //We have to get full access to AccountBrowser, so other iterating thrads cannot get new account until new account is right set + WaitToWriteSO(POP3Plugin->AccountBrowserSO); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:APPLY:AccountBrowserSO-write enter\n"); + #endif + } + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:APPLY:ActualAccountSO-write wait\n"); + #endif + if(WAIT_OBJECT_0!=WaitToWrite(ActualAccount)) + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:APPLY:ActualAccountSO-write wait failed\n"); + #endif + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:APPLY:ActualBrowserSO-write done\n"); + #endif + WriteDoneSO(POP3Plugin->AccountBrowserSO); + + } + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:APPLY:ActualAccountSO-write enter\n"); + #endif + +// Beep(1000,100);Sleep(200); + GetDlgItemText(hDlg,IDC_EDITNAME,Text,sizeof(Text)/sizeof(TCHAR)); + if(!(Length=_tcslen(Text))) + break; + if(NULL==ActualAccount->Name) + ActualAccount->Name=new TCHAR[Length+1]; + _tcscpy(ActualAccount->Name,Text); + + + +// Beep(1000,100);Sleep(200); + GetDlgItemText(hDlg,IDC_EDITSERVER,Text,sizeof(Text)/sizeof(TCHAR)); + if(NULL!=ActualAccount->Server->Name) + delete[] ActualAccount->Server->Name; + ActualAccount->Server->Name=new TCHAR[_tcslen(Text)+1]; + _tcscpy(ActualAccount->Server->Name,Text); + +// Beep(1000,100);Sleep(200); + GetDlgItemText(hDlg,IDC_EDITLOGIN,Text,sizeof(Text)/sizeof(TCHAR)); + if(NULL!=ActualAccount->Server->Login) + delete[] ActualAccount->Server->Login; + ActualAccount->Server->Login=new TCHAR[_tcslen(Text)+1]; + _tcscpy(ActualAccount->Server->Login,Text); + +// Beep(1000,100);Sleep(200); + GetDlgItemText(hDlg,IDC_EDITPASS,Text,sizeof(Text)/sizeof(TCHAR)); + if(NULL!=ActualAccount->Server->Passwd) + delete[] ActualAccount->Server->Passwd; + ActualAccount->Server->Passwd=new TCHAR[_tcslen(Text)+1]; + _tcscpy(ActualAccount->Server->Passwd,Text); + +// Beep(1000,100);Sleep(200); + GetDlgItemTextW(hDlg,IDC_EDITAPP,TextW,sizeof(TextW)/sizeof(WCHAR)); + if(NULL!=ActualAccount->NewMailN.App) + delete[] ActualAccount->NewMailN.App; + ActualAccount->NewMailN.App=new WCHAR[wcslen(TextW)+1]; + wcscpy(ActualAccount->NewMailN.App,TextW); + +// Beep(1000,100);Sleep(200); + GetDlgItemTextW(hDlg,IDC_EDITAPPPARAM,TextW,sizeof(TextW)/sizeof(WCHAR)); + if(NULL!=ActualAccount->NewMailN.AppParam) + delete[] ActualAccount->NewMailN.AppParam; + ActualAccount->NewMailN.AppParam=new WCHAR[wcslen(TextW)+1]; + wcscpy(ActualAccount->NewMailN.AppParam,TextW); + + ActualAccount->Server->Port=Port; + ActualAccount->Interval=Interval*60; + +// Beep(1000,100);Sleep(200); + if(CB_ERR==(index=SendDlgItemMessage(hDlg,IDC_COMBOCP,CB_GETCURSEL,0,0))) + index=CPDEFINDEX; + ActualAccount->CP=CodePageNamesSupp[index].CP; + +// Beep(1000,100);Sleep(200); + if(NewAcc) + ActualAccount->TimeLeft=Interval*60; + + CheckStart=(IsDlgButtonChecked(hDlg,IDC_CHECKSTART)==BST_CHECKED); + CheckForce=(IsDlgButtonChecked(hDlg,IDC_CHECKFORCE)==BST_CHECKED); + + ActualAccount->Flags= + (Check ? YAMN_ACC_ENA : 0) | + (CheckSSL ? YAMN_ACC_SSL23 : 0) | + (CheckNoTLS ? YAMN_ACC_NOTLS : 0) | + (CheckAPOP ? YAMN_ACC_APOP : 0) | + (CheckABody ? YAMN_ACC_BODY : 0) | + (ActualAccount->Flags & YAMN_ACC_POPN); + + ActualAccount->StatusFlags= + (Check0 ? YAMN_ACC_ST0 : 0) | + (Check1 ? YAMN_ACC_ST1 : 0) | + (Check2 ? YAMN_ACC_ST2 : 0) | + (Check3 ? YAMN_ACC_ST3 : 0) | + (Check4 ? YAMN_ACC_ST4 : 0) | + (Check5 ? YAMN_ACC_ST5 : 0) | + (Check6 ? YAMN_ACC_ST6 : 0) | + (Check7 ? YAMN_ACC_ST7 : 0) | + (Check8 ? YAMN_ACC_ST8 : 0) | + (Check9 ? YAMN_ACC_ST9 : 0) | + (CheckStart ? YAMN_ACC_STARTS : 0) | + (CheckForce ? YAMN_ACC_FORCE : 0); + + ActualAccount->NewMailN.Flags= + (CheckSnd ? YAMN_ACC_SND : 0) | + (CheckMsg ? YAMN_ACC_MSG : 0) | + (CheckIco ? YAMN_ACC_ICO : 0) | + (ActualAccount->NewMailN.Flags & YAMN_ACC_POP) | + (ActualAccount->NewMailN.Flags & YAMN_ACC_POPC) | + (CheckApp ? YAMN_ACC_APP : 0) | + (CheckKBN ? YAMN_ACC_KBN : 0) | + (CheckContact ? YAMN_ACC_CONT : 0) | + (CheckContactNick ? YAMN_ACC_CONTNICK : 0) | + (CheckContactNoEvent ? YAMN_ACC_CONTNOEVENT : 0) | + YAMN_ACC_MSGP; //this is default: when new mail arrives and window was displayed, leave it displayed. + + ActualAccount->NoNewMailN.Flags= + (ActualAccount->NoNewMailN.Flags & YAMN_ACC_POP) | + (ActualAccount->NoNewMailN.Flags & YAMN_ACC_POPC) | + (CheckNMsgP ? YAMN_ACC_MSGP : 0); + + ActualAccount->BadConnectN.Flags= + (CheckFSnd ? YAMN_ACC_SND : 0) | + (CheckFMsg ? YAMN_ACC_MSG : 0) | + (CheckFIco ? YAMN_ACC_ICO : 0) | + (ActualAccount->BadConnectN.Flags & YAMN_ACC_POP) | + (ActualAccount->BadConnectN.Flags & YAMN_ACC_POPC); + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:APPLY:ActualAccountSO-write done\n"); + #endif + WriteDone(ActualAccount); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:APPLY:AccountBrowserSO-write done\n"); + #endif + WriteDoneSO(POP3Plugin->AccountBrowserSO); + + EnableWindow(GetDlgItem(hDlg,IDC_BTNDEL),TRUE); + + DlgSetItemText(hDlg,(WPARAM)IDC_STTIMELEFT,(LPARAM)NULL); + + + index = SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_GETCURSEL,(WPARAM)0,(LPARAM)0); + + + HPOP3ACCOUNT temp = ActualAccount; + + SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_RESETCONTENT,0,(LPARAM)0); + if(POP3Plugin->FirstAccount!=NULL) + for(ActualAccount=(HPOP3ACCOUNT)POP3Plugin->FirstAccount;ActualAccount!=NULL;ActualAccount=(HPOP3ACCOUNT)ActualAccount->Next) + if(ActualAccount->Name!=NULL) + SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_ADDSTRING,0,(LPARAM)ActualAccount->Name); + + ActualAccount = temp; + SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_SETCURSEL,(WPARAM)index,(LPARAM)ActualAccount->Name); + +// if(0==WritePOP3Accounts()) +// Beep(500,100); + WritePOP3Accounts(); + RefreshContact(); + return TRUE; + } + } + break; + } + break; + } + break; + } + if(Changed) + SendMessage(GetParent(hDlg),PSM_CHANGED,0,0); + return FALSE; +} + +INT_PTR CALLBACK DlgProcPOP3AccPopup(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam) +{ + BOOL Changed=FALSE; + static BOOL InList=FALSE; + static HPOP3ACCOUNT ActualAccount; + static UCHAR ActualStatus; +// static struct CPOP3Options POP3Options; + + switch(msg) + { + case WM_INITDIALOG: + { + DlgEnableAccountPopup(hDlg,(WPARAM)FALSE,(LPARAM)FALSE); + DlgShowAccountPopup(hDlg,(WPARAM)M_SHOWDEFAULT,0); + //DlgShowAccountColors(hDlg,0,(LPARAM)ActualAccount); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:INITDIALOG:AccountBrowserSO-read wait\n"); + #endif + WaitToReadSO(POP3Plugin->AccountBrowserSO); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:INITDIALOG:AccountBrowserSO-read enter\n"); + #endif + if(POP3Plugin->FirstAccount!=NULL) + for(ActualAccount=(HPOP3ACCOUNT)POP3Plugin->FirstAccount;ActualAccount!=NULL;ActualAccount=(HPOP3ACCOUNT)ActualAccount->Next) + if(ActualAccount->Name!=NULL) + SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_ADDSTRING,0,(LPARAM)ActualAccount->Name); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:INITDIALOG:AccountBrowserSO-read done\n"); + #endif + ReadDoneSO(POP3Plugin->AccountBrowserSO); + ActualAccount=NULL; + + + TranslateDialogDefault(hDlg); + SendMessage(GetParent(hDlg),PSM_UNCHANGED,(WPARAM)hDlg,0); + return TRUE; + } + + case WM_SHOWWINDOW: + if((BOOL)wParam==FALSE) + { + WindowList_Remove(pYAMNVar->MessageWnds,hDlg); + SendMessage(GetParent(hDlg),PSM_UNCHANGED,(WPARAM)hDlg,(LPARAM)0); + } + else + { + WindowList_Add(pYAMNVar->MessageWnds,hDlg,NULL); + + int index = SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_GETCURSEL,(WPARAM)0,(LPARAM)0); + HPOP3ACCOUNT temp = ActualAccount; + SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_RESETCONTENT,0,(LPARAM)0); + + if(POP3Plugin->FirstAccount!=NULL) + for(ActualAccount=(HPOP3ACCOUNT)POP3Plugin->FirstAccount;ActualAccount!=NULL;ActualAccount=(HPOP3ACCOUNT)ActualAccount->Next) + if(ActualAccount->Name!=NULL) + SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_ADDSTRING,0,(LPARAM)ActualAccount->Name); + + ActualAccount = temp; + + if(ActualAccount != NULL) + { + SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_SETCURSEL,(WPARAM)index,(LPARAM)ActualAccount->Name); + DlgShowAccount(hDlg,(WPARAM)M_SHOWACTUAL,(LPARAM)ActualAccount); + DlgShowAccountColors(hDlg,0,(LPARAM)ActualAccount); + DlgEnableAccountPopup(hDlg,(WPARAM)TRUE,(LPARAM)FALSE); + } + else + { + DlgShowAccountPopup(hDlg,(WPARAM)M_SHOWDEFAULT,0); + DlgEnableAccountPopup(hDlg,(WPARAM)FALSE,(LPARAM)FALSE); + } + + } + return TRUE; + + case WM_COMMAND: + { + WORD wNotifyCode = HIWORD(wParam); + switch(LOWORD(wParam)) + { + LONG Result; + case IDC_COMBOACCOUNT: + switch(wNotifyCode) + { + + case CBN_KILLFOCUS: + GetDlgItemText(hDlg,IDC_COMBOACCOUNT,DlgInput,sizeof(DlgInput)/sizeof(TCHAR)); + if(NULL==(ActualAccount=(HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)DlgInput))) + { + DlgSetItemText(hDlg,(WPARAM)IDC_STTIMELEFT,(LPARAM)NULL); + if(lstrlen(DlgInput)) + DlgEnableAccountPopup(hDlg,(WPARAM)TRUE,(LPARAM)TRUE); + else + DlgEnableAccountPopup(hDlg,(WPARAM)FALSE,(LPARAM)FALSE); + } + else + { + DlgShowAccount(hDlg,(WPARAM)M_SHOWACTUAL,(LPARAM)ActualAccount); + DlgShowAccountColors(hDlg,0,(LPARAM)ActualAccount); + DlgEnableAccountPopup(hDlg,(WPARAM)TRUE,(LPARAM)TRUE); + } + break; + case CBN_SELCHANGE: + if(CB_ERR!=(Result=SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_GETCURSEL,0,0))) + SendDlgItemMessage(hDlg,IDC_COMBOACCOUNT,CB_GETLBTEXT,(WPARAM)Result,(LPARAM)DlgInput); + if((Result==CB_ERR) || (NULL==(ActualAccount=(HPOP3ACCOUNT)CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)DlgInput)))) + { + DlgSetItemText(hDlg,(WPARAM)IDC_STTIMELEFT,(LPARAM)NULL); + } + else + { + DlgShowAccount(hDlg,(WPARAM)M_SHOWACTUAL,(LPARAM)ActualAccount); + DlgShowAccountColors(hDlg,0,(LPARAM)ActualAccount); + DlgEnableAccountPopup(hDlg,(WPARAM)TRUE,(LPARAM)FALSE); + } + break; + } + break; + case IDC_COMBOCP: + { + int sel = SendDlgItemMessage(hDlg,IDC_COMBOCP,CB_GETCURSEL,0,0); + CPINFOEX info; GetCPInfoEx(CodePageNamesSupp[sel].CP,0,&info); + DlgSetItemText(hDlg,(WPARAM)IDC_STSTATUS,(LPARAM)info.CodePageName); + } + case IDC_RADIOPOPN: + case IDC_RADIOPOP1: + Changed=TRUE; + break; + case IDC_CPB: + case IDC_CPT: + case IDC_CPFB: + case IDC_CPFT: + case IDC_CPNB: + case IDC_CPNT: + if(HIWORD(wParam)!=CPN_COLOURCHANGED) + break; + case IDC_CHECKCOL: + case IDC_CHECKFCOL: + case IDC_CHECKNCOL: + EnableWindow(GetDlgItem(hDlg,IDC_CPB),(IsDlgButtonChecked(hDlg,IDC_CHECKCOL)==BST_CHECKED) && (IsDlgButtonChecked(hDlg,IDC_CHECKPOP)==BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg,IDC_CPT),(IsDlgButtonChecked(hDlg,IDC_CHECKCOL)==BST_CHECKED) && (IsDlgButtonChecked(hDlg,IDC_CHECKPOP)==BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg,IDC_CPNB),(IsDlgButtonChecked(hDlg,IDC_CHECKNCOL)==BST_CHECKED) && (IsDlgButtonChecked(hDlg,IDC_CHECKNPOP)==BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg,IDC_CPNT),(IsDlgButtonChecked(hDlg,IDC_CHECKNCOL)==BST_CHECKED) && (IsDlgButtonChecked(hDlg,IDC_CHECKNPOP)==BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg,IDC_CPFB),(IsDlgButtonChecked(hDlg,IDC_CHECKFCOL)==BST_CHECKED) && (IsDlgButtonChecked(hDlg,IDC_CHECKFPOP)==BST_CHECKED) && wParam); + EnableWindow(GetDlgItem(hDlg,IDC_CPFT),(IsDlgButtonChecked(hDlg,IDC_CHECKFCOL)==BST_CHECKED) && (IsDlgButtonChecked(hDlg,IDC_CHECKFPOP)==BST_CHECKED) && wParam); + Changed=TRUE; + break; + + case IDC_PREVIEW: + { + POPUPDATA Tester; + POPUPDATA TesterF; + POPUPDATA TesterN; + BOOL TesterC=(IsDlgButtonChecked(hDlg,IDC_CHECKCOL)==BST_CHECKED); + BOOL TesterFC=(IsDlgButtonChecked(hDlg,IDC_CHECKFCOL)==BST_CHECKED); + BOOL TesterNC=(IsDlgButtonChecked(hDlg,IDC_CHECKNCOL)==BST_CHECKED); + + ZeroMemory(&Tester,sizeof(Tester)); + ZeroMemory(&TesterF,sizeof(TesterF)); + ZeroMemory(&TesterF,sizeof(TesterN)); + Tester.lchContact=NULL; + TesterF.lchContact=NULL; + TesterN.lchContact=NULL; + Tester.lchIcon=hYamnIcons[2]; + TesterF.lchIcon=hYamnIcons[3]; + TesterN.lchIcon=hYamnIcons[1]; + + lstrcpy(Tester.lpzContactName,Translate("Account Test")); + lstrcpy(TesterF.lpzContactName,Translate("Account Test (failed)")); + lstrcpy(TesterN.lpzContactName,Translate("Account Test")); + lstrcpy(Tester.lpzText,Translate("You have N new mail messages")); + lstrcpy(TesterF.lpzText,Translate("Connection failed message")); + lstrcpy(TesterN.lpzText,Translate("No new mail message")); + if(TesterC) + { + Tester.colorBack=SendDlgItemMessage(hDlg,IDC_CPB,CPM_GETCOLOUR,0,0); + Tester.colorText=SendDlgItemMessage(hDlg,IDC_CPT,CPM_GETCOLOUR,0,0); + } + else + { + Tester.colorBack=GetSysColor(COLOR_BTNFACE); + Tester.colorText=GetSysColor(COLOR_WINDOWTEXT); + } + if(TesterFC) + { + TesterF.colorBack=SendDlgItemMessage(hDlg,IDC_CPFB,CPM_GETCOLOUR,0,0); + TesterF.colorText=SendDlgItemMessage(hDlg,IDC_CPFT,CPM_GETCOLOUR,0,0); + } + else + { + TesterF.colorBack=GetSysColor(COLOR_BTNFACE); + TesterF.colorText=GetSysColor(COLOR_WINDOWTEXT); + } + if(TesterNC) + { + TesterN.colorBack=SendDlgItemMessage(hDlg,IDC_CPNB,CPM_GETCOLOUR,0,0); + TesterN.colorText=SendDlgItemMessage(hDlg,IDC_CPNT,CPM_GETCOLOUR,0,0); + } + else + { + TesterN.colorBack=GetSysColor(COLOR_BTNFACE); + TesterN.colorText=GetSysColor(COLOR_WINDOWTEXT); + } + Tester.PluginWindowProc=(WNDPROC)NULL; + TesterF.PluginWindowProc=(WNDPROC)NULL; + TesterN.PluginWindowProc=(WNDPROC)NULL; + Tester.PluginData=NULL; + TesterF.PluginData=NULL; + TesterN.PluginData=NULL; + + if(IsDlgButtonChecked(hDlg,IDC_CHECKPOP)==BST_CHECKED) + CallService(MS_POPUP_ADDPOPUP,(WPARAM)&Tester,0); + if(IsDlgButtonChecked(hDlg,IDC_CHECKFPOP)==BST_CHECKED) + CallService(MS_POPUP_ADDPOPUP,(WPARAM)&TesterF,0); + if(IsDlgButtonChecked(hDlg,IDC_CHECKNPOP)==BST_CHECKED) + CallService(MS_POPUP_ADDPOPUP,(WPARAM)&TesterN,0); + Changed=TRUE; + } + break; + case IDC_CHECKKBN: + Changed=TRUE; + break; + case IDC_CHECKPOP: + Changed=TRUE; + EnableWindow(GetDlgItem(hDlg,IDC_CHECKCOL),IsDlgButtonChecked(hDlg,IDC_CHECKPOP)==BST_CHECKED); + EnableWindow(GetDlgItem(hDlg,IDC_CPB),(IsDlgButtonChecked(hDlg,IDC_CHECKCOL)==BST_CHECKED) && IsDlgButtonChecked(hDlg,IDC_CHECKPOP)==BST_CHECKED); + EnableWindow(GetDlgItem(hDlg,IDC_CPT),(IsDlgButtonChecked(hDlg,IDC_CHECKCOL)==BST_CHECKED) && IsDlgButtonChecked(hDlg,IDC_CHECKPOP)==BST_CHECKED); + EnableWindow(GetDlgItem(hDlg,IDC_RADIOPOPN),(IsDlgButtonChecked(hDlg,IDC_CHECKPOP)==BST_CHECKED)); + EnableWindow(GetDlgItem(hDlg,IDC_RADIOPOP1),(IsDlgButtonChecked(hDlg,IDC_CHECKPOP)==BST_CHECKED)); + EnableWindow(GetDlgItem(hDlg,IDC_EDITPOPS),(IsDlgButtonChecked(hDlg,IDC_CHECKPOP)==BST_CHECKED)); + break; + case IDC_CHECKFPOP: + Changed=TRUE; + EnableWindow(GetDlgItem(hDlg,IDC_CHECKFCOL),IsDlgButtonChecked(hDlg,IDC_CHECKFPOP)==BST_CHECKED); + EnableWindow(GetDlgItem(hDlg,IDC_CPFB),(IsDlgButtonChecked(hDlg,IDC_CHECKFCOL)==BST_CHECKED) && IsDlgButtonChecked(hDlg,IDC_CHECKFPOP)==BST_CHECKED); + EnableWindow(GetDlgItem(hDlg,IDC_CPFT),(IsDlgButtonChecked(hDlg,IDC_CHECKFCOL)==BST_CHECKED) && IsDlgButtonChecked(hDlg,IDC_CHECKFPOP)==BST_CHECKED); + EnableWindow(GetDlgItem(hDlg,IDC_EDITFPOPS),(IsDlgButtonChecked(hDlg,IDC_CHECKFPOP)==BST_CHECKED)); + break; + case IDC_CHECKNPOP: + Changed=TRUE; + EnableWindow(GetDlgItem(hDlg,IDC_CHECKNCOL),IsDlgButtonChecked(hDlg,IDC_CHECKNPOP)==BST_CHECKED); + EnableWindow(GetDlgItem(hDlg,IDC_CPNB),(IsDlgButtonChecked(hDlg,IDC_CHECKNCOL)==BST_CHECKED) && IsDlgButtonChecked(hDlg,IDC_CHECKNPOP)==BST_CHECKED); + EnableWindow(GetDlgItem(hDlg,IDC_CPNT),(IsDlgButtonChecked(hDlg,IDC_CHECKNCOL)==BST_CHECKED) && IsDlgButtonChecked(hDlg,IDC_CHECKNPOP)==BST_CHECKED); + EnableWindow(GetDlgItem(hDlg,IDC_EDITNPOPS),(IsDlgButtonChecked(hDlg,IDC_CHECKNPOP)==BST_CHECKED)); + break; + + } + if(HIWORD(wParam)==EN_CHANGE) + Changed=TRUE; + break; + } + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->idFrom) + { + case 0: + switch(((LPNMHDR)lParam)->code) + { + case PSN_APPLY: + { + TCHAR Text[MAX_PATH]; + BOOL Translated,NewAcc=FALSE,CheckPopup,CheckPopupW; + BOOL CheckNPopup,CheckNPopupW,CheckFPopup,CheckFPopupW; + BOOL CheckPopN; + UINT Time,TimeN,TimeF; + + if(GetDlgItemText(hDlg,IDC_COMBOACCOUNT,Text,sizeof(Text)/sizeof(TCHAR))) + { + CheckPopup=(IsDlgButtonChecked(hDlg,IDC_CHECKPOP)==BST_CHECKED); + CheckPopupW=(IsDlgButtonChecked(hDlg,IDC_CHECKCOL)==BST_CHECKED); + + CheckFPopup=(IsDlgButtonChecked(hDlg,IDC_CHECKFPOP)==BST_CHECKED); + CheckFPopupW=(IsDlgButtonChecked(hDlg,IDC_CHECKFCOL)==BST_CHECKED); + + CheckNPopup=(IsDlgButtonChecked(hDlg,IDC_CHECKNPOP)==BST_CHECKED); + CheckNPopupW=(IsDlgButtonChecked(hDlg,IDC_CHECKNCOL)==BST_CHECKED); + + CheckPopN=(IsDlgButtonChecked(hDlg,IDC_RADIOPOPN)==BST_CHECKED); + + + Time=GetDlgItemInt(hDlg,IDC_EDITPOPS,&Translated,FALSE); + if(!Translated) + { + MessageBox(hDlg,Translate("This is not a valid number value"),Translate("Input error"),MB_OK); + SetFocus(GetDlgItem(hDlg,IDC_EDITPOPS)); + break; + } + TimeN=GetDlgItemInt(hDlg,IDC_EDITNPOPS,&Translated,FALSE); + if(!Translated) + { + MessageBox(hDlg,Translate("This is not a valid number value"),Translate("Input error"),MB_OK); + SetFocus(GetDlgItem(hDlg,IDC_EDITNPOPS)); + break; + } + TimeF=GetDlgItemInt(hDlg,IDC_EDITFPOPS,&Translated,FALSE); + if(!Translated) + { + MessageBox(hDlg,Translate("This is not a valid number value"),Translate("Input error"),MB_OK); + SetFocus(GetDlgItem(hDlg,IDC_EDITFPOPS)); + break; + } + + + DlgSetItemText(hDlg,(WPARAM)IDC_STTIMELEFT,(LPARAM)Translate("Please wait while no account is in use.")); + + ActualAccount->Flags= + (ActualAccount->Flags & YAMN_ACC_ENA) | + (ActualAccount->Flags & YAMN_ACC_SSL23) | + (ActualAccount->Flags & YAMN_ACC_NOTLS) | + (ActualAccount->Flags & YAMN_ACC_APOP) | + (ActualAccount->Flags & YAMN_ACC_BODY) | + (CheckPopN ? YAMN_ACC_POPN : 0); + + ActualAccount->NewMailN.Flags= + (ActualAccount->NewMailN.Flags & YAMN_ACC_SND) | + (ActualAccount->NewMailN.Flags & YAMN_ACC_MSG) | + (ActualAccount->NewMailN.Flags & YAMN_ACC_ICO) | + (CheckPopup ? YAMN_ACC_POP : 0) | + (CheckPopupW ? YAMN_ACC_POPC : 0) | + (ActualAccount->NewMailN.Flags & YAMN_ACC_APP) | + (ActualAccount->NewMailN.Flags & YAMN_ACC_KBN) | + (ActualAccount->NewMailN.Flags & YAMN_ACC_CONT) | + (ActualAccount->NewMailN.Flags & YAMN_ACC_CONTNICK) | + (ActualAccount->NewMailN.Flags & YAMN_ACC_CONTNOEVENT) | + YAMN_ACC_MSGP; + + ActualAccount->NoNewMailN.Flags= + (CheckNPopup ? YAMN_ACC_POP : 0) | + (CheckNPopupW ? YAMN_ACC_POPC : 0) | + (ActualAccount->NoNewMailN.Flags & YAMN_ACC_MSGP); + + ActualAccount->BadConnectN.Flags= + (ActualAccount->BadConnectN.Flags & YAMN_ACC_SND) | + (ActualAccount->BadConnectN.Flags & YAMN_ACC_MSG) | + (ActualAccount->BadConnectN.Flags & YAMN_ACC_ICO) | + (CheckFPopup ? YAMN_ACC_POP : 0) | + (CheckFPopupW ? YAMN_ACC_POPC : 0); + + ActualAccount->NewMailN.PopUpB=SendDlgItemMessage(hDlg,IDC_CPB,CPM_GETCOLOUR,0,0); + ActualAccount->NewMailN.PopUpT=SendDlgItemMessage(hDlg,IDC_CPT,CPM_GETCOLOUR,0,0); + ActualAccount->NewMailN.PopUpTime=Time; + + ActualAccount->NoNewMailN.PopUpB=SendDlgItemMessage(hDlg,IDC_CPNB,CPM_GETCOLOUR,0,0); + ActualAccount->NoNewMailN.PopUpT=SendDlgItemMessage(hDlg,IDC_CPNT,CPM_GETCOLOUR,0,0); + ActualAccount->NoNewMailN.PopUpTime=TimeN; + + ActualAccount->BadConnectN.PopUpB=SendDlgItemMessage(hDlg,IDC_CPFB,CPM_GETCOLOUR,0,0); + ActualAccount->BadConnectN.PopUpT=SendDlgItemMessage(hDlg,IDC_CPFT,CPM_GETCOLOUR,0,0); + ActualAccount->BadConnectN.PopUpTime=TimeF; + + + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:APPLY:ActualAccountSO-write done\n"); + #endif + WriteDone(ActualAccount); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Options:APPLY:AccountBrowserSO-write done\n"); + #endif + WriteDoneSO(POP3Plugin->AccountBrowserSO); + +// if(0==WritePOP3Accounts()) +// Beep(500,100); + WritePOP3Accounts(); + RefreshContact(); + return TRUE; + } + } + break; + } + break; + } + break; + } + if(Changed) + SendMessage(GetParent(hDlg),PSM_CHANGED,0,0); + return FALSE; +} + diff --git a/yamn/proto/pop3/pop3opt.h b/yamn/proto/pop3/pop3opt.h new file mode 100644 index 0000000..291ff03 --- /dev/null +++ b/yamn/proto/pop3/pop3opt.h @@ -0,0 +1,38 @@ +#ifndef __OPTIONS_H +#define __OPTIONS_H + +#define M_SHOWACTUAL 0 +#define M_SHOWDEFAULT 1 + + +//Enables account in options +BOOL DlgEnableAccount(HWND hDlg,WPARAM wParam,LPARAM lParam); + +//Sets dialog controls to match current account +BOOL DlgShowAccount(HWND hDlg,WPARAM wParam,LPARAM lParam); + +//Sets colors to match colors of actual account +BOOL DlgShowAccountColors(HWND hDlg,WPARAM wParam,LPARAM lParam); + +//Sets dialog item text +BOOL DlgSetItemText(HWND hDlg,WPARAM wParam,LPARAM lParam); + +//Sets dialog item text in Unicode +BOOL DlgSetItemTextW(HWND hDlg,WPARAM wParam,LPARAM lParam); + +//Options dialog procedure +INT_PTR CALLBACK DlgProcPOP3AccOpt(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +//Options dialog procedure +BOOL CALLBACK DlgProcPOP3AccStatusOpt(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +//Options dialog procedure +INT_PTR CALLBACK DlgProcYAMNOpt(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +//Options dialog procedure +INT_PTR CALLBACK DlgProcPOP3AccPopup(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +//Initializes POP3 options for Miranda +int POP3OptInit(WPARAM wParam,LPARAM lParam); + +#endif diff --git a/yamn/proto/ssl.cpp b/yamn/proto/ssl.cpp new file mode 100644 index 0000000..2865e91 --- /dev/null +++ b/yamn/proto/ssl.cpp @@ -0,0 +1,344 @@ +/* + * This code implements communication based on OpenSSL library + * + * (c) majvan 2002,2004 + */ + +#include "../filter/simple/AggressiveOptimize.h" +#include +#include +#include //CallService,UnHookEvent +#include //socket thorugh proxy functions +#include //langpack for "connection" and other words +#include "../debug.h" +#ifdef SSLTHRUNETLIB + #include "netlib.h" //yes, we want to use netlib connection +#endif +#include "ssl.h" + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +PFN_SSL_int_void SSL_library_init; // int SSL_library_init() +PFN_SSL_pvoid_void SSLv23_client_method; // SSL_METHOD *SSLv23_client_method() +PFN_SSL_pvoid_void TLSv1_client_method; // SSL_METHOD *TLSv1_client_method() +PFN_SSL_pvoid_pvoid SSL_CTX_new; // SSL_CTX *SSL_CTX_new(SSL_METHOD *method) +PFN_SSL_void_pvoid SSL_CTX_free; // void SSL_CTX_free(SSL_CTX *ctx); +PFN_SSL_pvoid_pvoid SSL_new; // SSL *SSL_new(SSL_CTX *ctx) +PFN_SSL_void_pvoid SSL_free; // void SSL_free(SSL *ssl); +PFN_SSL_int_pvoid_int SSL_set_fd; // int SSL_set_fd(SSL *ssl, int fd); +PFN_SSL_int_pvoid SSL_connect; // int SSL_connect(SSL *ssl); +PFN_SSL_int_pvoid_pvoid_int SSL_read; // int SSL_read(SSL *ssl, void *buffer, int bufsize) +PFN_SSL_int_pvoid_pvoid_int SSL_write; // int SSL_write(SSL *ssl, void *buffer, int bufsize) +PFN_SSL_int_pvoid_int SSL_get_error; // int SSL_write(SSL *ssl, int ret) + +BOOL SSLLoaded=FALSE; +HINSTANCE hSSLLibrary=(HINSTANCE)NULL; +PVOID SSLCtx=NULL; +PVOID TLSCtx=NULL; + +//PVOID CSSLClient::SSLCtx=NULL; +//BOOL CSSLClient::SSLLoaded=FALSE; +//HINSTANCE CSSLClient::hSSLLibrary=(HINSTANCE)NULL; +extern HANDLE hNetlibUser; + +void __stdcall SSL_DebugLog( const char *fmt, ... ) +{ + char str[ 4096 ]; + va_list vararg; + + va_start( vararg, fmt ); + int tBytes = _vsnprintf( str, sizeof(str)-1, fmt, vararg ); + if ( tBytes == 0 ) + return; + + if ( tBytes > 0 ) + str[ tBytes ] = 0; + else + str[ sizeof(str)-1 ] = 0; + + CallService( MS_NETLIB_LOG, ( WPARAM )hNetlibUser, ( LPARAM )str ); + va_end( vararg ); +} + +#define SSLstr "SSL support" +#define SSLconnstr "SSL connection" + +int RegisterSSL() +{ +#ifdef DEBUG_COMM + DebugLog(CommFile,""); +#endif + SSL_DebugLog("%s %sing...",SSLstr,"register"); + if(NULL==(hSSLLibrary=LoadLibrary("ssleay32.dll"))) + if(NULL==(hSSLLibrary=LoadLibrary("libssl32.dll"))) //try to load library using the old OpenSSL filename + { +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + SSL_DebugLog("%s failed.",SSLstr); + return 0; + } + + if(NULL!=(SSL_library_init=(PFN_SSL_int_void)GetProcAddress(hSSLLibrary,"SSL_library_init"))) + if(NULL!=(SSLv23_client_method=(PFN_SSL_pvoid_void)GetProcAddress(hSSLLibrary,"SSLv23_client_method"))) + if(NULL!=(SSL_CTX_new=(PFN_SSL_pvoid_pvoid)GetProcAddress(hSSLLibrary,"SSL_CTX_new"))) + if(NULL!=(SSL_CTX_free=(PFN_SSL_void_pvoid)GetProcAddress(hSSLLibrary,"SSL_CTX_free"))) + if(NULL!=(SSL_new=(PFN_SSL_pvoid_pvoid)GetProcAddress(hSSLLibrary,"SSL_new"))) + if(NULL!=(SSL_free=(PFN_SSL_void_pvoid)GetProcAddress(hSSLLibrary,"SSL_free"))) + if(NULL!=(SSL_set_fd=(PFN_SSL_int_pvoid_int)GetProcAddress(hSSLLibrary,"SSL_set_fd"))) + if(NULL!=(SSL_connect=(PFN_SSL_int_pvoid)GetProcAddress(hSSLLibrary,"SSL_connect"))) + if(NULL!=(SSL_read=(PFN_SSL_int_pvoid_pvoid_int)GetProcAddress(hSSLLibrary,"SSL_read"))) + if(NULL!=(SSL_write=(PFN_SSL_int_pvoid_pvoid_int)GetProcAddress(hSSLLibrary,"SSL_write"))) + if(NULL!=(SSL_get_error=(PFN_SSL_int_pvoid_int)GetProcAddress(hSSLLibrary,"SSL_get_error"))) + { + TLSv1_client_method=(PFN_SSL_pvoid_void)GetProcAddress(hSSLLibrary,"TLSv1_client_method"); + if (TLSv1_client_method) { + TLSCtx=SSL_CTX_new(TLSv1_client_method()); //TLS1 only used + } else { + SSL_DebugLog("TLSv1 not available"); + } + SSL_library_init(); + SSLCtx=SSL_CTX_new(SSLv23_client_method()); //SSL2,3 & TLS1 used +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + SSLLoaded=TRUE; + SSL_DebugLog("%s %sed.",SSLstr,"register"); + return 1; + } + + FreeLibrary(hSSLLibrary); + hSSLLibrary=(HINSTANCE)NULL; +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + SSL_DebugLog("%s failed: %s not compatible",SSLstr,"ssleay32.dll"); + return 0; +} + +//Connects to the server through the sock +//if not success, exception is throwed +void CSSLClient::Connect(const char* servername,const int port) throw(DWORD) +{ + WSADATA wsaData; + + NetworkError=SystemError=0; + + if(!SSLLoaded) + throw NetworkError=ESSL_NOTLOADED; + try + { +#ifdef SSLTHRUNETLIB + NETLIBOPENCONNECTION nloc; + + nloc.cbSize=sizeof(NETLIBOPENCONNECTION); + nloc.szHost=servername; + nloc.wPort=port; + nloc.flags=0; + #ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); + #endif + if(NULL==(hNLConn=(HANDLE)CallService(MS_NETLIB_OPENCONNECTION,(WPARAM)hNetlibUser,(LPARAM)&nloc))) + { + #ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); + #endif + sock=INVALID_SOCKET; + } + else + { + #ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); + #endif + sock=CallService(MS_NETLIB_GETSOCKET,(WPARAM)hNLConn,0); + } +#endif + + if(sock==INVALID_SOCKET) + { + if(0!=WSAStartup(MAKEWORD(2,0),&wsaData)) + { + SystemError=WSAGetLastError(); + throw NetworkError=(DWORD)ESSL_WINSOCKINIT; + } + ZeroMemory(&connection,sizeof(struct sockaddr_in)); +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + if(NULL==(server=gethostbyname(servername))) + { + SystemError=WSAGetLastError(); + throw NetworkError=(DWORD)ESSL_GETHOSTBYNAME; + } + memmove((char*)&(connection.sin_addr.s_addr),server->h_addr,server->h_length); + connection.sin_family=AF_INET; + connection.sin_port=htons((unsigned short int)port); /* integral size mismatch in argument - htons(port)*/ + if(INVALID_SOCKET==(sock=socket(AF_INET,SOCK_STREAM,0))) + { + SystemError=WSAGetLastError(); + throw NetworkError=(DWORD)ESSL_CREATESOCKET; + } + if(-1==connect(sock,(struct sockaddr*)&connection,sizeof(connection))) + { + SystemError=WSAGetLastError(); + throw NetworkError=(DWORD)ESSL_SOCKETCONNECT; + } +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + } + +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + if(NULL==(hConnection=SSL_new(SSLCtx))) + throw NetworkError=(DWORD)ESSL_CREATESSL; + if(SSL_set_fd(hConnection,sock)<1) + throw NetworkError=(DWORD)ESSL_SETSOCKET; + if(SSL_connect(hConnection)<1) + throw NetworkError=(DWORD)ESSL_CONNECT; + ConEstablished=TRUE; +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + SSL_DebugLog("%s to %s:%d %s.",SSLconnstr,servername,port,"established"); + return; + } + catch(...) + { +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + SSL_DebugLog("%s to %s:%d %s.",SSLconnstr,servername,port,"failed"); + throw; + } +} + +void CSSLClient::SSLify() throw(DWORD) +{ + SSL_DebugLog("Hmm... Trying to start TLS in SSL... This should be a bug."); +} + +//Performs a simple query +// query- command to send +void CSSLClient::Send(const char *query) throw(DWORD) +{ + unsigned int Sent; + + if(NULL==query) + return; +#ifdef DEBUG_COMM + DebugLog(CommFile,"%s",query); +#endif + try + { + if(!ConEstablished) + throw NetworkError=(DWORD)ESSL_SEND; + SSL_DebugLog("SSL send %s",query); + Sent=SSL_write(hConnection,(PVOID)query,strlen(query)); + if(Sent!=strlen(query)) + { + SystemError=SSL_get_error(hConnection,Sent); + throw NetworkError=(DWORD)ESSL_SEND; + } +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + } + catch(...) + { +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + if (ConEstablished) SSL_DebugLog("SSL send %s","failed"); + throw; + } +} + +//Reads data from SSL socket +// buf- buffer where to store max. buflen of received characters +// if buf is NULL, creates buffer of buflen size +// buf is NULL by default +//You need free() returned buffer, which can be allocated in this function +//if not success, exception is throwed +char* CSSLClient::Recv(char *buf,int buflen) throw(DWORD) +{ +#ifdef DEBUG_COMM + DebugLog(CommFile,""); +#endif + try + { + if(!ConEstablished) + throw NetworkError=(DWORD)ESSL_RECV; + if(buf==NULL) + buf=(char *)malloc(sizeof(char)*(buflen+1)); + if(buf==NULL) + throw NetworkError=(DWORD)ESSL_RECVALLOC; + ZeroMemory(buf,buflen); + if (hConnection){ + Rcv=SSL_read(hConnection,buf,buflen); + } else { + Rcv=0; + SSL_DebugLog("SSL connection is lost"); + } + if(Rcv<1) + { + SystemError=SSL_get_error(hConnection,Rcv); + throw NetworkError=(DWORD)ESSL_RECV; + } +#ifdef DEBUG_COMM + *(buf+Rcv)=0; //end the buffer to write it to file + DebugLog(CommFile,"%s",buf); + DebugLog(CommFile,"\n"); +#endif + SSL_DebugLog("SSL recv %s",buf); + return(buf); + } + catch(...) + { +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + if (ConEstablished) SSL_DebugLog("SSL recv %s","failed."); + throw; + } +} + +//Closes SSL connection +void CSSLClient::Disconnect() +{ +#ifdef SSLTHRUNETLIB + if((HANDLE)NULL!=hNLConn) + Netlib_CloseHandle(hNLConn); + else +#endif + if(INVALID_SOCKET!=sock) + closesocket(sock); + + if(hConnection!=(HANDLE)NULL) + SSL_free(hConnection); + hConnection=(HANDLE)NULL; + sock=INVALID_SOCKET; + hNLConn=(HANDLE)NULL; + if (ConEstablished) SSL_DebugLog("%s %s.",SSLconnstr,"closed"); + ConEstablished=FALSE; +} + +void UnregisterSSL() +{ + if(SSLLoaded) + { +#ifdef DEBUG_COMM + DebugLog(CommFile,""); +#endif + SSL_CTX_free(SSLCtx); + if (TLSCtx) SSL_CTX_free(TLSCtx); + FreeLibrary(hSSLLibrary); + hSSLLibrary=(HINSTANCE)NULL; +#ifdef DEBUG_COMM + DebugLog(CommFile,"\n"); +#endif + SSL_DebugLog("%s unregistered.",SSLstr); + } +} diff --git a/yamn/proto/ssl.h b/yamn/proto/ssl.h new file mode 100644 index 0000000..2a61551 --- /dev/null +++ b/yamn/proto/ssl.h @@ -0,0 +1,61 @@ +#ifndef __SSL_H +#define __SSL_H + +#include "netclient.h" + +#pragma warning( disable : 4290 ) +#define SSLTHRUNETLIB //performs netlib connection before normal winsock connection + + +typedef int (*PFN_SSL_int_void)(void); +typedef PVOID (*PFN_SSL_pvoid_void)(void); +typedef PVOID (*PFN_SSL_pvoid_pvoid)(PVOID); +typedef void (*PFN_SSL_void_pvoid)(PVOID); +typedef int (*PFN_SSL_int_pvoid_int)(PVOID, int); +typedef int (*PFN_SSL_int_pvoid)(PVOID); +typedef int (*PFN_SSL_int_pvoid_pvoid_int)(PVOID, PVOID, int); + +class CSSLClient: public CNetClient +{ +public: + CSSLClient(): hConnection(NULL), sock(INVALID_SOCKET), ConEstablished(FALSE) {} + void Connect(const char* servername,const int port) throw(DWORD); + void Send(const char *query) throw(DWORD); + char* Recv(char *buf=NULL,int buflen=65536) throw(DWORD); + void Disconnect(); + void SSLify()throw(DWORD); + + inline BOOL Connected() {return ConEstablished;} + + //static BOOL SSLLoaded; + //static HINSTANCE hSSLLibrary; + //static PVOID SSLCtx; +protected: + HANDLE hConnection; +#ifdef SSLTHRUNETLIB + HANDLE hNLConn; +#endif + + int sock; + struct hostent *server; + struct sockaddr_in connection; + + BOOL ConEstablished; +}; + +enum +{ + ESSL_NOTLOADED=1, //OpenSSL is not loaded + ESSL_WINSOCKINIT, //WinSock 2.0 init failed + ESSL_GETHOSTBYNAME, //DNS error + ESSL_CREATESOCKET, //error creating socket + ESSL_SOCKETCONNECT, //error connecting with socket + ESSL_CREATESSL, //error creating SSL session structure + ESSL_SETSOCKET, //error connect socket with SSL session for bidirect I/O space + ESSL_CONNECT, //cannot connect to server + ESSL_SEND, //cannot send data + ESSL_RECV, //cannot receive data + ESSL_RECVALLOC, //cannot allocate memory for received data +}; + +#endif diff --git a/yamn/protoplugin.cpp b/yamn/protoplugin.cpp new file mode 100644 index 0000000..e89b879 --- /dev/null +++ b/yamn/protoplugin.cpp @@ -0,0 +1,258 @@ +/* + * YAMN plugin export functions for protocols + * + * (c) majvan 2002-2004 + */ + +#if !defined(_WIN64) + #include "filter/simple/AggressiveOptimize.h" +#endif +#include +#include +#include +#include +#include +#include "m_yamn.h" +#include "m_protoplugin.h" +#include "m_synchro.h" +#include "debug.h" + +//- imported --------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +extern WCHAR *UserDirectory; //e.g. "F:\WINNT\Profiles\UserXYZ" +extern WCHAR *ProfileName; //e.g. "majvan" +extern SWMRG *AccountBrowserSO; +extern LPCRITICAL_SECTION PluginRegCS; +extern YAMN_VARIABLES YAMNVar; +//From synchro.cpp +extern BOOL WINAPI SWMRGInitialize(PSWMRG,TCHAR *); +extern void WINAPI SWMRGDelete(PSWMRG); +extern DWORD WINAPI SWMRGWaitToWrite(PSWMRG pSWMRG,DWORD dwTimeout); +extern void WINAPI SWMRGDoneWriting(PSWMRG pSWMRG); +extern DWORD WINAPI SWMRGWaitToRead(PSWMRG pSWMRG, DWORD dwTimeout); +extern void WINAPI SWMRGDoneReading(PSWMRG pSWMRG); +//From account.cpp +extern int StopAccounts(HYAMNPROTOPLUGIN Plugin); +extern int DeleteAccounts(HYAMNPROTOPLUGIN Plugin); +extern int WaitForAllAccounts(HYAMNPROTOPLUGIN Plugin,BOOL GetAccountBrowserAccess); + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +WCHAR FileName2[]=L"%s\\yamn-accounts.%s.%s.book"; //UserDirectory\\yamn-accounts.PluginName.UserProfileName.book +PYAMN_PROTOPLUGINQUEUE FirstProtoPlugin=NULL; + +INT_PTR RegisterProtocolPluginSvc(WPARAM,LPARAM); + +//Removes plugin from queue and deletes registration structures +INT_PTR UnregisterProtocolPlugin(HYAMNPROTOPLUGIN Plugin); + +INT_PTR UnregisterProtocolPluginSvc(WPARAM,LPARAM); + +//Removes plugins from queue and deletes registration structures +INT_PTR UnregisterProtoPlugins(); + +//Sets imported functions for an plugin and therefore it starts plugin to be registered and running +// Plugin- plugin, which wants to set its functions +// YAMNFcn- pointer to imported functions with accounts +// YAMNFcnVer- version of YAMN_PROTOIMPORTFCN, use YAMN_PROTOIMPORTFCNVERSION +// YAMNMailFcn- pointer to imported functions with mails +// YAMNMailFcnVer- version of YAMN_MAILIMPORTFCN, use YAMN_MAILIMPORTFCNVERSION +// returns nonzero if success +int WINAPI SetProtocolPluginFcnImportFcn(HYAMNPROTOPLUGIN Plugin,PYAMN_PROTOIMPORTFCN YAMNFcn,DWORD YAMNFcnVer,PYAMN_MAILIMPORTFCN YAMNMailFcn,DWORD YAMNMailFcnVer); + +INT_PTR GetFileNameWSvc(WPARAM,LPARAM); +INT_PTR GetFileNameASvc(WPARAM,LPARAM); +INT_PTR DeleteFileNameSvc(WPARAM,LPARAM); + +struct CExportedFunctions ProtoPluginExportedFcn[]= +{ + {YAMN_SETPROTOCOLPLUGINFCNIMPORTID,(void *)SetProtocolPluginFcnImportFcn}, +}; + +struct CExportedServices ProtoPluginExportedSvc[]= +{ + {MS_YAMN_REGISTERPROTOPLUGIN,RegisterProtocolPluginSvc}, + {MS_YAMN_UNREGISTERPROTOPLUGIN,UnregisterProtocolPluginSvc}, + {MS_YAMN_GETFILENAMEA,GetFileNameASvc}, + {MS_YAMN_GETFILENAMEW,GetFileNameWSvc}, + {MS_YAMN_DELETEFILENAME,DeleteFileNameSvc}, +}; + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +INT_PTR RegisterProtocolPluginSvc(WPARAM wParam,LPARAM lParam) +{ + PYAMN_PROTOREGISTRATION Registration=(PYAMN_PROTOREGISTRATION)wParam; + HYAMNPROTOPLUGIN Plugin; + + if(lParam!=YAMN_PROTOREGISTRATIONVERSION) + return 0; + if((Registration->Name==NULL) || (Registration->Ver==NULL)) + return (INT_PTR)NULL; + if(NULL==(Plugin=new YAMN_PROTOPLUGIN)) + return (INT_PTR)NULL; + + Plugin->PluginInfo=Registration; + + Plugin->FirstAccount=NULL; + + Plugin->AccountBrowserSO=new SWMRG; + SWMRGInitialize(Plugin->AccountBrowserSO,NULL); + + Plugin->Fcn=NULL; + Plugin->MailFcn=NULL; + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"::: YAMN- new protocol registered: %0x (%s) :::\n",Plugin,Registration->Name); +#endif + return (INT_PTR)Plugin; +} + +int WINAPI SetProtocolPluginFcnImportFcn(HYAMNPROTOPLUGIN Plugin,PYAMN_PROTOIMPORTFCN YAMNFcn,DWORD YAMNFcnVer,PYAMN_MAILIMPORTFCN YAMNMailFcn,DWORD YAMNMailFcnVer) +{ + PYAMN_PROTOPLUGINQUEUE Parser; + + if(YAMNFcnVer!=YAMN_PROTOIMPORTFCNVERSION) + return 0; + if(YAMNMailFcnVer!=YAMN_MAILIMPORTFCNVERSION) + return 0; + if(YAMNFcn==NULL) + return 0; + if(YAMNMailFcn==NULL) + return 0; + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"::: YAMN- protocol %0x import succeed :::\n",Plugin); +#endif + Plugin->Fcn=YAMNFcn; + Plugin->MailFcn=YAMNMailFcn; + + EnterCriticalSection(PluginRegCS); +//We add protocol to the protocol list + for(Parser=FirstProtoPlugin;Parser!=NULL && Parser->Next!=NULL;Parser=Parser->Next); + if(Parser==NULL) + { + FirstProtoPlugin=new YAMN_PROTOPLUGINQUEUE; + Parser=FirstProtoPlugin; + } + else + { + Parser->Next=new YAMN_PROTOPLUGINQUEUE; + Parser=Parser->Next; + } + + Parser->Plugin=Plugin; + Parser->Next=NULL; + + LeaveCriticalSection(PluginRegCS); + return 1; +} + +INT_PTR UnregisterProtocolPlugin(HYAMNPROTOPLUGIN Plugin) +{ + PYAMN_PROTOPLUGINQUEUE Parser,Found; + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Entering UnregisterProtocolPlugin\n"); +#endif + if(FirstProtoPlugin->Plugin==Plugin) + { + Found=FirstProtoPlugin; + FirstProtoPlugin=FirstProtoPlugin->Next; + } + else + { + for(Parser=FirstProtoPlugin;(Parser->Next!=NULL) && (Plugin!=Parser->Next->Plugin);Parser=Parser->Next); + if(Parser->Next!=NULL) + { + Found=Parser->Next; + Parser->Next=Parser->Next->Next; + } + else + Found=NULL; + } + if(Found!=NULL) + { + StopAccounts(Plugin); + DeleteAccounts(Plugin); + if(Plugin->Fcn->UnLoadFcn!=NULL) + Plugin->Fcn->UnLoadFcn((void *)0); + + delete Found->Plugin->AccountBrowserSO; + delete Found->Plugin; + delete Found; + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"::: YAMN- protocol %0x unregistered :::\n",Plugin); +#endif + } + else + return 0; + return 1; +} + +INT_PTR UnregisterProtocolPluginSvc(WPARAM wParam,LPARAM lParam) +{ + HYAMNPROTOPLUGIN Plugin=(HYAMNPROTOPLUGIN)wParam; + + EnterCriticalSection(PluginRegCS); + UnregisterProtocolPlugin(Plugin); + LeaveCriticalSection(PluginRegCS); + return 1; + +} + +INT_PTR UnregisterProtoPlugins() +{ + EnterCriticalSection(PluginRegCS); +//We remove protocols from the protocol list + while(FirstProtoPlugin!=NULL) + UnregisterProtocolPlugin(FirstProtoPlugin->Plugin); + LeaveCriticalSection(PluginRegCS); + return 1; +} + +INT_PTR GetFileNameWSvc(WPARAM wParam,LPARAM) +{ + WCHAR *FileName; + + if(NULL==(FileName=new WCHAR[MAX_PATH])) + return NULL; + swprintf(FileName,FileName2,UserDirectory,(WCHAR *)wParam,ProfileName); +// MessageBoxW(NULL,FileName,L"GetFileNameW",MB_OK); + return (INT_PTR)FileName; +} + +INT_PTR GetFileNameASvc(WPARAM wParam,LPARAM) +{ + WCHAR *ConvertedInput; + WCHAR *FileName; + + if(NULL==(FileName=new WCHAR[MAX_PATH])) + return NULL; + if(NULL==(ConvertedInput=new WCHAR[MAX_PATH])) + { + delete[] FileName; + return NULL; + } + +// Convert input string to unicode + MultiByteToWideChar(CP_ACP,MB_USEGLYPHCHARS,(char *)wParam,-1,ConvertedInput,(int)strlen((char *)wParam)+1); + + swprintf(FileName,FileName2,UserDirectory,ConvertedInput,ProfileName); +// MessageBoxW(NULL,FileName,L"GetFileNameA",MB_OK); + delete[] ConvertedInput; + + return (INT_PTR)FileName; +} + +INT_PTR DeleteFileNameSvc(WPARAM wParam,LPARAM) +{ + if((WCHAR *)wParam!=NULL) + delete[] (WCHAR *)wParam; + + return 0; +} diff --git a/yamn/resources/YAMN.rc b/yamn/resources/YAMN.rc new file mode 100644 index 0000000..9269bf8 --- /dev/null +++ b/yamn/resources/YAMN.rc @@ -0,0 +1,383 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1252) +#endif //_WIN32 + +#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 + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_DLGVIEWMESSAGES, DIALOG + BEGIN + LEFTMARGIN, 5 + RIGHTMARGIN, 455 + TOPMARGIN, 5 + BOTTOMMARGIN, 105 + END + + IDD_DLGBADCONNECT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 43 + END + + IDD_PLUGINOPT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 312 + VERTGUIDE, 13 + VERTGUIDE, 85 + VERTGUIDE, 160 + VERTGUIDE, 307 + TOPMARGIN, 4 + HORZGUIDE, 5 + HORZGUIDE, 20 + HORZGUIDE, 147 + HORZGUIDE, 157 + HORZGUIDE, 173 + HORZGUIDE, 184 + HORZGUIDE, 207 + HORZGUIDE, 217 + END + + IDD_POP3ACCOUNTOPT, DIALOG + BEGIN + VERTGUIDE, 155 + VERTGUIDE, 236 + END + + IDD_CHOOSESTATUSMODES, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 219 + TOPMARGIN, 7 + BOTTOMMARGIN, 147 + END + + IDD_YAMNOPT, DIALOG + BEGIN + VERTGUIDE, 8 + END + + IDD_POP3ACCOUNTPOPUP, DIALOG + BEGIN + VERTGUIDE, 155 + VERTGUIDE, 236 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DLGVIEWMESSAGES DIALOG 50, 200, 460, 110 +STYLE DS_SETFONT | DS_3DLOOK | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "List4",IDC_LISTMAILS,"SysListView32",LVS_REPORT | LVS_EDITLABELS | WS_BORDER | WS_TABSTOP,5,5,450,70 + DEFPUSHBUTTON "",IDC_BTNOK,395,90,60,15 + PUSHBUTTON "",IDC_BTNAPP,263,90,114,15 + PUSHBUTTON "",IDC_BTNDEL,5,90,114,15 + LTEXT "",IDC_STSTATUS,5,75,450,10 + PUSHBUTTON "",IDC_BTNCHECKALL,150,91,92,14 +END + +IDD_DLGSHOWMESSAGE DIALOGEX 50, 200, 460, 132 +STYLE DS_SETFONT | DS_3DLOOK | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "List5",IDC_LISTHEADERS,"SysListView32",LVS_REPORT | LVS_EDITLABELS | WS_BORDER | WS_TABSTOP,5,5,450,70 + CONTROL "",IDC_SPLITTER,"Static",SS_ENHMETAFILE | WS_TABSTOP,0,80,187,2,WS_EX_STATICEDGE + EDITTEXT IDC_EDITBODY,3,84,454,45,ES_MULTILINE | ES_READONLY | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL +END + +IDD_DLGBADCONNECT DIALOG 0, 0, 186, 76 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +FONT 8, "MS Shell Dlg" +BEGIN + DEFPUSHBUTTON "OK",IDC_BTNOK,69,55,50,14 + LTEXT "",IDC_STATICMSG,7,7,172,37 +END + +IDD_PLUGINOPT DIALOGEX 0, 0, 310, 231 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_BORDER +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Installed plugins",IDC_STATIC,7,5,300,142 + COMBOBOX IDC_COMBOPLUGINS,13,14,287,58,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Version:",IDC_STATIC,13,30,72,11 + EDITTEXT IDC_STVER,85,30,215,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | WS_GROUP + LTEXT "Description:",IDC_STATIC,13,41,72,23 + EDITTEXT IDC_STDESC,85,41,215,23,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | WS_GROUP + LTEXT "Copyright:",IDC_STATIC,13,64,72,10 + EDITTEXT IDC_STCOPY,85,63,215,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | WS_GROUP + LTEXT "Contact:",IDC_STATIC,13,77,72,11 + EDITTEXT IDC_STMAIL,85,76,214,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | WS_GROUP + LTEXT "WWW:",IDC_STATIC,13,101,72,11 + CONTROL "",IDC_STWWW,"Hyperlink",WS_TABSTOP,85,101,215,11 +END + +IDD_POP3ACCOUNTOPT DIALOGEX 0, 0, 310, 230 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + COMBOBOX IDC_COMBOACCOUNT,4,6,106,65,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + CONTROL "Check this account",IDC_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,167,32,118,10,WS_EX_TRANSPARENT + LTEXT "Check interval [min]:",IDC_STINTERVAL,168,56,94,8 + EDITTEXT IDC_EDITINTERVAL,259,53,20,12,ES_AUTOHSCROLL | ES_NUMBER,WS_EX_TRANSPARENT + GROUPBOX "Notifications",IDC_GBNEWMAIL,4,143,304,87 + CONTROL "Sound",IDC_CHECKSND,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,12,162,60,10 + CONTROL "Message",IDC_CHECKMSG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,174,135,10 + CONTROL "Tray Icon",IDC_CHECKICO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,85,163,65,10 + CONTROL "Keyboard Flash",IDC_CHECKKBN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,186,132,9 + CONTROL "Execute Application",IDC_CHECKAPP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,198,135,8 + PUSHBUTTON "...",IDC_BTNAPP,19,209,16,12 + EDITTEXT IDC_EDITAPP,41,209,65,12,ES_AUTOHSCROLL + EDITTEXT IDC_EDITAPPPARAM,111,209,40,12,ES_AUTOHSCROLL + CONTROL "Use contact notification for this account",IDC_CHECKCONTACT, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,166,107,138,10,WS_EX_TRANSPARENT + CONTROL "Replace nick name",IDC_CHECKCONTACTNICK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,187,117,117,10,WS_EX_TRANSPARENT + CONTROL "Disable Events",IDC_CHECKCONTACTNOEVENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,187,128,115,10,WS_EX_TRANSPARENT + LTEXT "",IDC_STSTATUS,218,9,88,8 + LTEXT "Server:",IDC_STSERVER,10,50,44,8 + EDITTEXT IDC_EDITSERVER,56,48,92,12,ES_AUTOHSCROLL | WS_GROUP + LTEXT "User Name:",IDC_STLOGIN,10,82,44,8 + EDITTEXT IDC_EDITLOGIN,57,80,92,12,ES_AUTOHSCROLL | WS_GROUP + LTEXT "Password:",IDC_STPASS,10,96,44,8 + EDITTEXT IDC_EDITPASS,57,94,92,12,ES_PASSWORD | ES_AUTOHSCROLL | WS_GROUP + LTEXT "Codepage:",IDC_STCP,10,111,44,8 + COMBOBOX IDC_COMBOCP,57,108,92,130,CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Port:",IDC_STPORT,10,65,44,8,SS_CENTERIMAGE + EDITTEXT IDC_EDITPORT,57,64,27,12,ES_AUTOHSCROLL | ES_NUMBER | WS_GROUP + CONTROL "SSL",IDC_CHECKSSL,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,87,66,27,10 + CONTROL "Disable STLS",IDC_CHECKNOTLS,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,83,125,69,10 + CONTROL "Startup check",IDC_CHECKSTART,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,167,43,78,10 + CONTROL "Auto retrieve body",IDC_AUTOBODY,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,166,86,137,10 + CONTROL "Check from menu",IDC_CHECKFORCE,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,166,97,137,8 + PUSHBUTTON "Only check when ...",IDC_BTNSTATUS,195,69,81,13 + CONTROL "Sound notification if failed",IDC_CHECKFSND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,166,163,135,10 + CONTROL "Message notification if failed",IDC_CHECKFMSG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,166,174,135,10 + CONTROL "Tray icon notification if failed",IDC_CHECKFICO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,166,186,135,10 + PUSHBUTTON "Reset counter",IDC_BTNRESET,161,200,75,13 + PUSHBUTTON "-",IDC_BTNDEL,140,6,15,13 + PUSHBUTTON "Default",IDC_BTNDEFAULT,9,124,54,13 + LTEXT "",IDC_STTIMELEFT,163,216,141,8 + LTEXT "Status:",IDC_STATIC,175,9,34,9 + PUSHBUTTON "+",IDC_BTNADD,118,6,15,13 + GROUPBOX "Account",IDC_STATIC,4,22,151,120 + CONTROL "APOP",IDC_CHECKAPOP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,119,66,34,10 + LTEXT "Name:",IDC_STATIC,10,34,44,10 + EDITTEXT IDC_EDITNAME,56,32,92,12,ES_AUTOHSCROLL + GROUPBOX "Options",IDC_STATIC,161,22,147,120 + GROUPBOX "New Mail",IDC_STATIC,7,153,149,73 + GROUPBOX "Errors",IDC_STATIC,161,153,143,44 +END + +IDD_CHOOSESTATUSMODES DIALOG 0, 0, 226, 154 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Check while ..." +FONT 8, "MS Shell Dlg" +BEGIN + DEFPUSHBUTTON "OK",IDOK,112,133,50,14 + PUSHBUTTON "Cancel",IDCANCEL,169,133,50,14 + GROUPBOX "Choose modes",IDC_STATUSGROUP,7,7,212,119 + CONTROL "Offline",IDC_CHECKST0,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,15,19,70,9 + CONTROL "Online",IDC_CHECKST1,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,15,39,70,9 + CONTROL "Away",IDC_CHECKST2,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,15,62,70,9 + CONTROL "N/A",IDC_CHECKST3,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,15,83,70,9 + CONTROL "Occupied",IDC_CHECKST4,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,15,104,70,9 + CONTROL "DND",IDC_CHECKST5,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,134,19,70,9 + CONTROL "Free for chat",IDC_CHECKST6,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,134,39,70,9 + CONTROL "Invisible",IDC_CHECKST7,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,134,62,70,9 + CONTROL "On the phone",IDC_CHECKST8,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,134,83,70,9 + CONTROL "Out to lunch",IDC_CHECKST9,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,134,104,70,9 +END + +IDD_YAMNOPT DIALOGEX 0, 0, 310, 216 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_BORDER +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "HotKey1",IDC_HKFORCE,"msctls_hotkey32",WS_BORDER | WS_TABSTOP,169,15,110,12 + LTEXT "Hotkey for mail check:",IDC_STATIC,7,16,153,10 + CONTROL "TopToolBar button ""Check mail""",IDC_CHECKTTB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,28,160,11 + GROUPBOX "YAMN General Options",IDC_STATIC,3,2,303,80 + CONTROL "Enable YAMN Main Menu (Require Restart)",IDC_MAINMENU, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,46,270,9 + GROUPBOX "MailBrowser Options",IDC_STATIC,3,91,151,61 + CONTROL "Enable Close on Delete Button",IDC_CLOSEONDELETE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,103,143,11 + CONTROL "Show long localised date",IDC_LONGDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,170,100,144,10 + CONTROL "Don't show today's date",IDC_SMARTDATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,170,112,144,10 + GROUPBOX "Date/Time Representation",IDC_STATIC,166,91,141,61 + CONTROL "Don't show seconds",IDC_NOSECONDS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,170,124,135,8 + CONTROL "Show YAMN as a Protocol (Require Restart)",IDC_YAMNASPROTO, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,63,270,9 +END + +IDD_POP3ACCOUNTPOPUP DIALOGEX 0, 0, 315, 230 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + COMBOBOX IDC_COMBOACCOUNT,4,4,140,65,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + GROUPBOX "Mail Notifications",IDC_GBNEWMAIL,5,23,300,76 + CONTROL "Popup",IDC_CHECKPOP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,32,108,10 + CONTROL "Single popup",IDC_RADIOPOP1,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,23,43,95,10 + CONTROL "Multi popup",IDC_RADIOPOPN,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,23,55,95,10 + CONTROL "Use custom colour",IDC_CHECKCOL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,23,83,107,10 + CONTROL "",IDC_CPB,"ColourPicker",WS_TABSTOP,145,66,29,12 + CONTROL "",IDC_CPT,"ColourPicker",WS_TABSTOP,145,83,29,12 + EDITTEXT IDC_EDITPOPS,23,65,20,12,ES_AUTOHSCROLL + GROUPBOX "No new mail notifications",IDC_GBNONEWMAIL,5,152,300,62 + CONTROL "Popup if no mail",IDC_CHECKNPOP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,161,94,10 + CONTROL "Persistant message",IDC_CHECKNMSGP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,23,188,110,10 + CONTROL "Use custom colour",IDC_CHECKNCOL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,23,201,107,10 + CONTROL "",IDC_CPNB,"ColourPicker",WS_TABSTOP,145,181,29,12 + CONTROL "",IDC_CPNT,"ColourPicker",WS_TABSTOP,145,198,29,12 + EDITTEXT IDC_EDITNPOPS,23,173,20,12,ES_AUTOHSCROLL + GROUPBOX "Connection failure notifications",IDC_GBBADCONNECT,5,101,300,49 + CONTROL "Popup notification if failed",IDC_CHECKFPOP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,110,118,10 + CONTROL "Use custom colour",IDC_CHECKFCOL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,23,136,95,10 + CONTROL "",IDC_CPFB,"ColourPicker",WS_TABSTOP,145,118,29,12 + CONTROL "",IDC_CPFT,"ColourPicker",WS_TABSTOP,145,134,29,12 + EDITTEXT IDC_EDITFPOPS,23,121,20,12,ES_AUTOHSCROLL + LTEXT "..s Popup duration",IDC_STATIC,45,67,70,8 + LTEXT "..s Popup duration",IDC_STATIC,45,176,70,8 + LTEXT "..s Popup duration",IDC_STATIC,45,122,70,8 + PUSHBUTTON "Preview",IDC_PREVIEW,255,215,49,13 + LTEXT "Background colour",IDC_STATIC,177,184,108,10 + LTEXT "Text colour",IDC_STATIC,177,200,107,10 + LTEXT "Background colour",IDC_STATIC,177,120,108,10 + LTEXT "Text colour",IDC_STATIC,177,136,107,10 + LTEXT "Background colour",IDC_STATIC,177,69,108,10 + LTEXT "Text colour",IDC_STATIC,177,85,107,10 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ONLINE ICON "iconeutral.ico" +IDI_OFFLINE ICON "icooffline.ico" +IDI_NA ICON "icoyamn3.ico" +IDI_OCCUPIED ICON "iconttbdown.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_ICONS BITMAP "yamn.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,1,2,5 + PRODUCTVERSION 0,1,2,5 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "Comments", "Yet Another Mail Notifier" + VALUE "FileDescription", "Yet Another Mail Notifier" + VALUE "FileVersion", "0.1.2.5" + VALUE "InternalName", "YAMN" + VALUE "LegalCopyright", "Copyright © 2007" + VALUE "OriginalFilename", "YAMN.dll" + VALUE "ProductName", "YAMN tweety" + VALUE "ProductVersion", "0.1.2.5" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END + +#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/yamn/resources/iconeutral.ico b/yamn/resources/iconeutral.ico new file mode 100644 index 0000000..9304f43 Binary files /dev/null and b/yamn/resources/iconeutral.ico differ diff --git a/yamn/resources/iconttbdown.ico b/yamn/resources/iconttbdown.ico new file mode 100644 index 0000000..206eba2 Binary files /dev/null and b/yamn/resources/iconttbdown.ico differ diff --git a/yamn/resources/icooffline.ico b/yamn/resources/icooffline.ico new file mode 100644 index 0000000..db5b2e1 Binary files /dev/null and b/yamn/resources/icooffline.ico differ diff --git a/yamn/resources/icoyamn3.ico b/yamn/resources/icoyamn3.ico new file mode 100644 index 0000000..ca11f0f Binary files /dev/null and b/yamn/resources/icoyamn3.ico differ diff --git a/yamn/resources/resource.h b/yamn/resources/resource.h new file mode 100644 index 0000000..bd9b48b --- /dev/null +++ b/yamn/resources/resource.h @@ -0,0 +1,130 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by YAMN.rc +// +#define IDI_ONLINE 104 +#define IDI_OFFLINE 105 +#define IDD_DLGVIEWMESSAGES 107 +#define IDD_DLGSHOWMESSAGE 108 +#define IDI_ICOYAMN2 112 +#define IDI_ICOYAMN1 113 +#define IDD_DLGBADCONNECT 115 +#define IDD_POP3ACCOUNTOPT 121 +#define IDD_YAMNOPT 126 +#define IDB_ICONS 127 +#define IDI_NA 131 +#define IDI_ICOTTBUP 138 +#define IDD_PLUGINOPT 141 +#define IDI_OCCUPIED 159 +#define IDD_CHOOSESTATUSMODES 310 +#define IDD_OPTIONS 311 +#define IDD_POP3ACCOUNTPOPUP 312 +#define IDC_EDITSERVER 1000 +#define IDC_EDITPORT 1001 +#define IDC_EDITLOGIN 1002 +#define IDC_EDITPASS 1003 +#define IDC_COMBOACCOUNT 1005 +#define IDC_BTNDEFAULT 1006 +#define IDC_EDITINTERVAL 1007 +#define IDC_CHECKSND 1008 +#define IDC_CHECKMSG 1009 +#define IDC_CHECKAPP 1010 +#define IDC_BTNAPP 1011 +#define IDC_CHECKICO 1012 +#define IDC_CHECK 1013 +#define IDC_BTNDEL 1014 +#define IDC_STSERVER 1015 +#define IDC_CHECKFSND 1016 +#define IDC_CHECKFMSG 1017 +#define IDC_CHECKFICO 1018 +#define IDC_CHECKST0 1019 +#define IDC_CHECKST1 1020 +#define IDC_CHECKST2 1021 +#define IDC_CHECKST3 1022 +#define IDC_CHECKST4 1023 +#define IDC_CHECKST5 1024 +#define IDC_CHECKST6 1025 +#define IDC_CHECKST7 1026 +#define IDC_EDITAPP 1027 +#define IDC_CHECKST8 1028 +#define IDC_CHECKST9 1029 +#define IDC_CHECKCONTACT 1030 +#define IDC_CHECKCONTACTNICK 1031 +#define IDC_CHECKCONTACTNOEVENT 1032 +#define IDC_STTIMELEFT 1033 +#define IDC_LISTMAILS 1038 +#define IDC_LISTHEADERS 1039 +#define IDC_EDITAPPPARAM 1044 +#define IDC_BTNOK 1047 +#define IDC_COMBOCP 1050 +#define IDC_STCP 1055 +#define IDC_STATICMSG 1055 +#define IDC_STPORT 1056 +#define IDC_STLOGIN 1057 +#define IDC_STPASS 1058 +#define IDC_STINTERVAL 1059 +#define IDC_AUTOBODY 1062 +#define IDC_BTNRESET 1063 +#define IDC_CHECKSTART 1064 +#define IDC_STWCHECK 1065 +#define IDC_CHECKFORCE 1066 +#define IDC_RADIOPOP1 1068 +#define IDC_RADIOPOPN 1069 +#define IDC_CPB 1070 +#define IDC_CPNB 1071 +#define IDC_CHECKCOL 1073 +#define IDC_CPT 1074 +#define IDC_CPFB 1075 +#define IDC_CPFT 1076 +#define IDC_CHECKFCOL 1077 +#define IDC_CHECKNCOL 1078 +#define IDC_CPNT 1079 +#define IDC_HKFORCE 1081 +#define IDC_CHECKPOP 1087 +#define IDC_CHECKNPOP 1088 +#define IDC_CHECKFPOP 1089 +#define IDC_EDITPOPS 1090 +#define IDC_EDITNPOPS 1091 +#define IDC_EDITFPOPS 1092 +#define IDC_GBNEWMAIL 1094 +#define IDC_GBNONEWMAIL 1095 +#define IDC_GBBADCONNECT 1096 +#define IDC_STSTATUS 1102 +#define IDC_COMBOPLUGINS 1104 +#define IDC_STWWW 1111 +#define IDC_STMAIL 1113 +#define IDC_STCOPY 1114 +#define IDC_STDESC 1115 +#define IDC_STVER 1116 +#define IDC_CHECKTTB 1117 +#define IDC_CHECKSSL 1117 +#define IDC_CHECKNMSGP 1118 +#define IDC_CHECKNOTLS 1120 +#define IDC_CHECKKBN 1121 +#define IDC_BTNSTATUS 1123 +#define IDC_OPTIONSTAB 1124 +#define IDC_BTNCHECKALL 1125 +#define IDC_MAINMENU 1126 +#define IDC_CLOSEONDELETE 1127 +#define IDC_LONGDATE 1128 +#define IDC_SMARTDATE 1129 +#define IDC_NOSECONDS 1130 +#define IDC_YAMNASPROTO 1131 +#define IDC_CHECKAPOP 1200 +#define IDC_STATUSGROUP 1338 +#define IDC_SPLITTER 1400 +#define IDC_EDITBODY 1401 +#define IDC_PREVIEW 1402 +#define IDC_BTNADD 1403 +#define IDC_EDITNAME 1404 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 143 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1407 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/yamn/resources/yamn.bmp b/yamn/resources/yamn.bmp new file mode 100644 index 0000000..91a9e34 Binary files /dev/null and b/yamn/resources/yamn.bmp differ diff --git a/yamn/services.cpp b/yamn/services.cpp new file mode 100644 index 0000000..e4b8b79 --- /dev/null +++ b/yamn/services.cpp @@ -0,0 +1,541 @@ + +#include "main.h" +#include "yamn.h" +// External icon var for icolib support + + +//MessageWndCS +//We want to send messages to all windows in the queue +//When we send messages, no other window can register itself to the queue for receiving messages +extern LPCRITICAL_SECTION MessageWndCS; + +//Plugin registration CS +//Used if we add (register) plugin to YAMN plugins and when we browse through registered plugins +extern LPCRITICAL_SECTION PluginRegCS; + +//AccountWriterCS +//We want to store number of writers of Accounts (number of Accounts used for writing) +//If we want to read all accounts (for saving to file) immidiatelly, we have to wait until no account is changing (no thread writing to account) +extern SCOUNTER *AccountWriterSO; + +//NoExitEV +//Event that is signaled when there's a request to exit, so no new pop3 check should be performed +extern HANDLE ExitEV; + +//WriteToFileEV +//If this is signaled, write accounts to file is performed. Set this event if you want to actualize your accounts and messages +extern HANDLE WriteToFileEV; + +//extern HICON hYamnIconsOrg[]; +extern HICON hYamnIcons[]; +extern char *iconDescs[]; +extern char *iconNames[]; +extern HIMAGELIST CSImages; + +extern void __stdcall SSL_DebugLog( const char *fmt, ... ); + +extern char *ProtoName; +extern INT_PTR YAMN_STATUS; + +extern PYAMN_VARIABLES pYAMNVar; +extern HYAMNPROTOPLUGIN POP3Plugin; + +static INT_PTR Service_GetCaps(WPARAM wParam, LPARAM lParam) +{ + if(wParam==PFLAGNUM_4) + return PF4_NOCUSTOMAUTH; + if(wParam==PFLAG_UNIQUEIDTEXT) + return (INT_PTR) Translate("Nick"); + if(wParam==PFLAG_MAXLENOFMESSAGE) + return 400; + if(wParam==PFLAG_UNIQUEIDSETTING) + return (INT_PTR) "Id"; + if(wParam==PFLAGNUM_2) + return PF2_ONLINE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND; + if(wParam==PFLAGNUM_5) + if(DBGetContactSettingByte(NULL, YAMN_DBMODULE, YAMN_SHOWASPROTO, 0)) + return PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND; + else + return PF2_ONLINE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND; + return 0; +} + +static INT_PTR Service_GetStatus(WPARAM wParam, LPARAM lParam) +{ + return YAMN_STATUS; +} + +static INT_PTR Service_SetStatus(WPARAM wParam,LPARAM lParam) +{ + INT_PTR newstatus = (wParam!=ID_STATUS_OFFLINE)?ID_STATUS_ONLINE:ID_STATUS_OFFLINE; + if (newstatus != YAMN_STATUS){ + INT_PTR oldstatus = YAMN_STATUS; + YAMN_STATUS=newstatus; + ProtoBroadcastAck(ProtoName,NULL,ACKTYPE_STATUS,ACKRESULT_SUCCESS,(HANDLE)oldstatus,newstatus); + } + return 0; + +} + +static INT_PTR Service_GetName(WPARAM wParam, LPARAM lParam) +{ + lstrcpyn((char *) lParam, ProtoName, wParam);; + return 0; +} + +static INT_PTR Service_LoadIcon(WPARAM wParam,LPARAM lParam) +{ + if ( LOWORD( wParam ) == PLI_PROTOCOL ) + return (INT_PTR)CopyIcon(hYamnIcons[0]); // noone cares about other than PLI_PROTOCOL + + return (INT_PTR)(HICON)NULL; + +} + +/*static*/ INT_PTR ClistContactDoubleclicked(WPARAM wParam, LPARAM lParam) +{ + ContactDoubleclicked(((CLISTEVENT*)lParam)->lParam, lParam); + return 0; +} + +static int Service_ContactDoubleclicked(WPARAM wParam, LPARAM lParam) +{ + ContactDoubleclicked(wParam, lParam); + return 0; +} + +static INT_PTR ContactApplication(WPARAM wParam, LPARAM lParam) +{ + DBVARIANT dbv; + char *szProto; + HACCOUNT ActualAccount; + + szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); + if(szProto != NULL && strcmp(szProto, ProtoName)==0) + { + if(!DBGetContactSetting((HANDLE) wParam,ProtoName,"Id",&dbv)) + { + ActualAccount=(HACCOUNT) CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)dbv.pszVal); + if(ActualAccount != NULL) + { + PROCESS_INFORMATION pi; + STARTUPINFOW si; + + ZeroMemory(&si,sizeof(si)); + si.cb=sizeof(si); + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ContactApplication:ActualAccountSO-read wait\n"); + #endif + if(WAIT_OBJECT_0==WaitToReadFcn(ActualAccount->AccountAccessSO)) + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ContactApplication:ualAccountSO-read enter\n"); + #endif + if(ActualAccount->NewMailN.App!=NULL) + { + WCHAR *Command; + if(ActualAccount->NewMailN.AppParam!=NULL) + Command=new WCHAR[wcslen(ActualAccount->NewMailN.App)+wcslen(ActualAccount->NewMailN.AppParam)+6]; + else + Command=new WCHAR[wcslen(ActualAccount->NewMailN.App)+6]; + + if(Command!=NULL) + { + lstrcpyW(Command,L"\""); + lstrcatW(Command,ActualAccount->NewMailN.App); + lstrcatW(Command,L"\" "); + if(ActualAccount->NewMailN.AppParam!=NULL) + lstrcatW(Command,ActualAccount->NewMailN.AppParam); + CreateProcessW(NULL,Command,NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi); + delete[] Command; + } + } + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ContactApplication:ActualAccountSO-read done\n"); + #endif + ReadDoneFcn(ActualAccount->AccountAccessSO); + } + #ifdef DEBUG_SYNCHRO + else + DebugLog(SynchroFile,"ContactApplication:ActualAccountSO-read enter failed\n"); + #endif + } + DBFreeVariant(&dbv); + } + } + return 0; +} + +DWORD WINAPI SWMRGWaitToRead(PSWMRG pSWMRG, DWORD dwTimeout); +static INT_PTR AccountMailCheck(WPARAM wParam, LPARAM lParam){ + //This service will check/sincronize the account pointed by wParam + HACCOUNT ActualAccount = (HACCOUNT)wParam; + HANDLE ThreadRunningEV; + DWORD tid; + // copy/paste make mistakes + if(ActualAccount != NULL) + { + //we use event to signal, that running thread has all needed stack parameters copied + if(NULL==(ThreadRunningEV=CreateEvent(NULL,FALSE,FALSE,NULL))) + return 0; + //if we want to close miranda, we get event and do not run pop3 checking anymore + if(WAIT_OBJECT_0==WaitForSingleObject(ExitEV,0)) + return 0; + EnterCriticalSection(PluginRegCS); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"AccountCheck:ActualAccountSO-read wait\n"); + #endif + if(WAIT_OBJECT_0!=SWMRGWaitToRead(ActualAccount->AccountAccessSO,0)) + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ForceCheck:ActualAccountSO-read wait failed\n"); + #endif + } + else + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ForceCheck:ActualAccountSO-read enter\n"); + #endif + if((ActualAccount->Flags & YAMN_ACC_ENA) && ActualAccount->Plugin->Fcn->SynchroFcnPtr) + { + struct CheckParam ParamToPlugin={YAMN_CHECKVERSION,ThreadRunningEV,ActualAccount,lParam?YAMN_FORCECHECK:YAMN_NORMALCHECK,(void *)0,NULL}; + HANDLE NewThread; + + ActualAccount->TimeLeft=ActualAccount->Interval; + if(NewThread=CreateThread(NULL,0,(YAMN_STANDARDFCN)ActualAccount->Plugin->Fcn->SynchroFcnPtr,&ParamToPlugin,0,&tid)) + { + WaitForSingleObject(ThreadRunningEV,INFINITE); + CloseHandle(NewThread); + } + else + { + //ReadDoneFcn(ActualAccount->AccountAccessSO); + } + + } + ReadDoneFcn(ActualAccount->AccountAccessSO); + } + LeaveCriticalSection(PluginRegCS); + CloseHandle(ThreadRunningEV); + } + return 0; +} + +static INT_PTR ContactMailCheck(WPARAM wParam, LPARAM lParam) +{ + + DBVARIANT dbv; + char *szProto; + HACCOUNT ActualAccount; + HANDLE ThreadRunningEV; + DWORD tid; + + szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); + if(szProto != NULL && strcmp(szProto, ProtoName)==0) + { + if(!DBGetContactSetting((HANDLE) wParam,ProtoName,"Id",&dbv)) + { + ActualAccount=(HACCOUNT) CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)dbv.pszVal); + if(ActualAccount != NULL) + { + //we use event to signal, that running thread has all needed stack parameters copied + if(NULL==(ThreadRunningEV=CreateEvent(NULL,FALSE,FALSE,NULL))) + return 0; + //if we want to close miranda, we get event and do not run pop3 checking anymore + if(WAIT_OBJECT_0==WaitForSingleObject(ExitEV,0)) + return 0; + EnterCriticalSection(PluginRegCS); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ForceCheck:ActualAccountSO-read wait\n"); + #endif + if(WAIT_OBJECT_0!=WaitToReadFcn(ActualAccount->AccountAccessSO)) + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ForceCheck:ActualAccountSO-read wait failed\n"); + #endif + } + else + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ForceCheck:ActualAccountSO-read enter\n"); + #endif + if((ActualAccount->Flags & YAMN_ACC_ENA) && (ActualAccount->StatusFlags & YAMN_ACC_FORCE)) //account cannot be forced to check + { + if(ActualAccount->Plugin->Fcn->ForceCheckFcnPtr==NULL) + { + ReadDoneFcn(ActualAccount->AccountAccessSO); + } + struct CheckParam ParamToPlugin={YAMN_CHECKVERSION,ThreadRunningEV,ActualAccount,YAMN_FORCECHECK,(void *)0,NULL}; + + if(NULL==CreateThread(NULL,0,(YAMN_STANDARDFCN)ActualAccount->Plugin->Fcn->ForceCheckFcnPtr,&ParamToPlugin,0,&tid)) + { + ReadDoneFcn(ActualAccount->AccountAccessSO); + } + else + WaitForSingleObject(ThreadRunningEV,INFINITE); + } + ReadDoneFcn(ActualAccount->AccountAccessSO); + } + LeaveCriticalSection(PluginRegCS); + CloseHandle(ThreadRunningEV); + } + DBFreeVariant(&dbv); + } + + } + return 0; +} + + +void MainMenuAccountClicked(WPARAM wParam, LPARAM lParam) +{ + +} + +/*static*/ void ContactDoubleclicked(WPARAM wParam, LPARAM lParam) +{ + DBVARIANT dbv; + char *szProto; + HACCOUNT ActualAccount; + + szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); + if(szProto != NULL && strcmp(szProto, ProtoName)==0) + { + if(!DBGetContactSetting((HANDLE) wParam,ProtoName,"Id",&dbv)) + { + ActualAccount=(HACCOUNT) CallService(MS_YAMN_FINDACCOUNTBYNAME,(WPARAM)POP3Plugin,(LPARAM)dbv.pszVal); + if(ActualAccount != NULL) + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Service_ContactDoubleclicked:ActualAccountSO-read wait\n"); + #endif + if(WAIT_OBJECT_0==WaitToReadFcn(ActualAccount->AccountAccessSO)) + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Service_ContactDoubleclicked:ActualAccountSO-read enter\n"); + #endif + YAMN_MAILBROWSERPARAM Param={(HANDLE)0,ActualAccount,ActualAccount->NewMailN.Flags,ActualAccount->NoNewMailN.Flags,0}; + + Param.nnflags=Param.nnflags | YAMN_ACC_MSG; //show mails in account even no new mail in account + Param.nnflags=Param.nnflags & ~YAMN_ACC_POP; + + Param.nflags=Param.nflags | YAMN_ACC_MSG; //show mails in account even no new mail in account + Param.nflags=Param.nflags & ~YAMN_ACC_POP; + + RunMailBrowserSvc((WPARAM)&Param,(LPARAM)YAMN_MAILBROWSERVERSION); + + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"Service_ContactDoubleclicked:ActualAccountSO-read done\n"); + #endif + ReadDoneFcn(ActualAccount->AccountAccessSO); + } + #ifdef DEBUG_SYNCHRO + else + DebugLog(SynchroFile,"Service_ContactDoubleclicked:ActualAccountSO-read enter failed\n"); + #endif + + } + DBFreeVariant(&dbv); + } + + } +} + +int IcoLibIconsChanged(WPARAM wParam, LPARAM lParam) +{ + HICON temp; + for (int i=0;iFirstAccount;Finder!=NULL;Finder=Finder->Next) + { + if(Finder->hContact != NULL) + { + if((Finder->Flags & YAMN_ACC_ENA) && (Finder->NewMailN.Flags & YAMN_ACC_CONT)) + { + DBDeleteContactSetting(Finder->hContact, "CList", "Hidden"); + } + else + { + DBWriteContactSettingByte(Finder->hContact, "CList", "Hidden", 1); + } + } + else + { + if((Finder->Flags & YAMN_ACC_ENA) && (Finder->NewMailN.Flags & YAMN_ACC_CONT)) + { + Finder->hContact =(HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0); + CallService(MS_PROTO_ADDTOCONTACT,(WPARAM)Finder->hContact,(LPARAM)ProtoName); + DBWriteContactSettingString(Finder->hContact,ProtoName,"Id",Finder->Name); + DBWriteContactSettingString(Finder->hContact,ProtoName,"Nick",Finder->Name); + DBWriteContactSettingString(Finder->hContact,"Protocol","p",ProtoName); + DBWriteContactSettingWord(Finder->hContact, ProtoName, "Status", ID_STATUS_ONLINE); + DBWriteContactSettingString(Finder->hContact, "CList", "StatusMsg", Translate("No new mail message")); + } + + } + } + +} diff --git a/yamn/synchro.cpp b/yamn/synchro.cpp new file mode 100644 index 0000000..e791d5f --- /dev/null +++ b/yamn/synchro.cpp @@ -0,0 +1,378 @@ +/* + * This code implements synchronization objects code between threads. If you want, you can include it to your + * code. This file is not dependent on any other external code (functions) + * + * (c) majvan 2002-2004 + */ +#if !defined(_WIN64) + #include "filter/simple/AggressiveOptimize.h" +#endif +#include +#include "debug.h" +#include "m_yamn.h" +#include "m_synchro.h" +#ifdef DEBUG_SYNCHRO +#include +#include +#endif + +// Initializes a SWMRG structure. This structure must be +// initialized before any writer or reader threads attempt +// to wait on it. +// The structure must be allocated by the application and +// the structure's address is passed as the first parameter. +// The lpszName parameter is the name of the object. Pass +// NULL if you do not want to share the object. +BOOL WINAPI SWMRGInitialize(PSWMRG pSWMRG,TCHAR *Name); + +// Deletes the system resources associated with a SWMRG +// structure. The structure must be deleted only when +// no writer or reader threads in the calling process +// will wait on it. +void WINAPI SWMRGDelete(PSWMRG pSWMRG); + +// A writer thread calls this function to know when +// it can successfully write to the shared data. +// returns WAIT_FINISH when we are in write-access or WAIT_FAILED +// when event about quick finishing is set (or when system returns fail when waiting for synchro object) +DWORD WINAPI SWMRGWaitToWrite(PSWMRG pSWMRG,DWORD dwTimeout); + +// A writer thread calls this function to let other threads +// know that it no longer needs to write to the shared data. +void WINAPI SWMRGDoneWriting(PSWMRG pSWMRG); + +// A reader thread calls this function to know when +// it can successfully read the shared data. +// returns WAIT_FINISH when we are in read-access or WAIT_FAILED +// when event about quick finishing is set (or when system returns fail when waiting for synchro object) +DWORD WINAPI SWMRGWaitToRead(PSWMRG pSWMRG, DWORD dwTimeout); + +// A reader thread calls this function to let other threads +// know when it no longer needs to read the shared data. +void WINAPI SWMRGDoneReading(PSWMRG pSWMRG); + +// WaitToWriteFcn +// is used to wait for write access with SWMRG SO, but it also increments counter if successfull +// returns WAIT_FAILED or WAIT_FINISH +// when WAIT_FAILED, we should not begin to access datas, we are not in write-access mode +DWORD WINAPI WaitToWriteFcn(PSWMRG SObject,PSCOUNTER SCounter=NULL); + +// WriteDoneFcn +// is used to release write access with SWMRG SO, but it also decrements counter if successfull +void WINAPI WriteDoneFcn(PSWMRG SObject,PSCOUNTER SCounter=NULL); + +// WaitToReadFcn +// is used to wait for read access with SWMRG SO, but it also increments counter if successfull +// returns WAIT_FAILED or WAIT_FINISH +// when WAIT_FAILED, we should not begin to access datas, we are not in read-access mode +DWORD WINAPI WaitToReadFcn(PSWMRG SObject); + +// WriteDoneFcn +// is used to release read access with SWMRG SO, but it also decrements counter if successfull +void WINAPI ReadDoneFcn(PSWMRG SObject); + +// This functions is for export purposes +// Plugin can call this function to manage SCOUNTER synchronization object + +// Gets number value stored in SCOUNTER SO +// Note you must not read the number from memory directly, because +// CPU can stop reading thread when it has read HI-Word, then another thread +// can change the value and then OS starts the previous thread, that reads the +// LO-WORD of DWORD. And the return value HI+LO-WORD is corrupted +DWORD WINAPI SCGetNumberFcn(PSCOUNTER SCounter); + +// Increments SCOUNTER and unsets event +// Returns Number after incrementing +DWORD WINAPI SCIncFcn(PSCOUNTER SCounter); + +// Decrements SCOUNTER and sets event if zero +// Returns Number after decrementing +DWORD WINAPI SCDecFcn(PSCOUNTER SCounter); + +struct CExportedFunctions SynchroExportedFcn[]= +{ + {YAMN_WAITTOWRITEID,(void *)WaitToWriteFcn}, + {YAMN_WRITEDONEID,(void *)WriteDoneFcn}, + {YAMN_WAITTOREADID,(void *)WaitToReadFcn}, + {YAMN_READDONEID,(void *)ReadDoneFcn}, + {YAMN_SCGETNUMBERID,(void *)SCGetNumberFcn}, + {YAMN_SCINCID,(void *)SCIncFcn}, + {YAMN_SCDECID,(void *)SCDecFcn}, +}; + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +void WINAPI SWMRGDelete(PSWMRG pSWMRG) +{ +// Destroys any synchronization objects that were +// successfully created. + if (NULL!=pSWMRG->hEventNoWriter) + CloseHandle(pSWMRG->hEventNoWriter); + if (NULL!=pSWMRG->hEventNoReaders) + CloseHandle(pSWMRG->hEventNoReaders); + if (NULL!=pSWMRG->hSemNumReaders) + CloseHandle(pSWMRG->hSemNumReaders); + if (NULL!=pSWMRG->hFinishEV) + CloseHandle(pSWMRG->hFinishEV); +} + +BOOL WINAPI SWMRGInitialize(PSWMRG pSWMRG,TCHAR *Name) +{ + pSWMRG->hEventNoWriter=NULL; + pSWMRG->hEventNoReaders=NULL; + pSWMRG->hSemNumReaders=NULL; + pSWMRG->hFinishEV=NULL; + +// Creates the automatic-reset event that is signalled when +// no writer threads are writing. +// Initially no reader threads are reading. + if(Name!=NULL) + Name[0]=(TCHAR)'W'; + pSWMRG->hEventNoWriter=CreateEvent(NULL,FALSE,TRUE,Name); + +// Creates the manual-reset event that is signalled when +// no reader threads are reading. +// Initially no reader threads are reading. + if(Name!=NULL) + Name[0]=(TCHAR)'R'; + pSWMRG->hEventNoReaders=CreateEvent(NULL,TRUE,TRUE,Name); + +// Initializes the variable that indicates the number of +// reader threads that are reading. +// Initially no reader threads are reading. + if(Name!=NULL) + Name[0]=(TCHAR)'C'; + pSWMRG->hSemNumReaders=CreateSemaphore(NULL,0,0x7FFFFFFF,Name); + + if(Name!=NULL) + Name[0]=(TCHAR)'F'; + pSWMRG->hFinishEV=CreateEvent(NULL,TRUE,FALSE,Name); + +// If a synchronization object could not be created, +// destroys any created objects and return failure. + if((NULL==pSWMRG->hEventNoWriter) || (NULL==pSWMRG->hEventNoReaders) || (NULL==pSWMRG->hSemNumReaders) || (NULL==pSWMRG->hFinishEV)) + { + SWMRGDelete(pSWMRG); + return FALSE; + } + return TRUE; +} + +DWORD WINAPI SWMRGWaitToWrite(PSWMRG pSWMRG,DWORD dwTimeout) +{ + DWORD dw; + HANDLE aHandles[2]; + +// We can write if the following are true: +// 1. No other threads are writing. +// 2. No threads are reading. +// But first we have to know if SWMRG structure is not about to delete + aHandles[0]=pSWMRG->hEventNoWriter; + aHandles[1]=pSWMRG->hEventNoReaders; + if(WAIT_OBJECT_0==(dw=WaitForSingleObject(pSWMRG->hFinishEV,0))) + return WAIT_FINISH; + if(WAIT_FAILED==dw) + return dw; + dw=WaitForMultipleObjects(2,aHandles,TRUE,dwTimeout); +// if a request to delete became later, we should not catch it. Try once more to ask if account is not about to delete + if((dw!=WAIT_FAILED) && (WAIT_OBJECT_0==(WaitForSingleObject(pSWMRG->hFinishEV,0)))) + { + SetEvent(pSWMRG->hEventNoWriter); + return WAIT_FINISH; + } + +// This thread can write to the shared data. +// Automatic event for NoWriter sets hEventNoWriter to nonsignaled after WaitForMultipleObject + +// Because a writer thread is writing, the Event +// should not be reset. This stops other +// writers and readers. + return dw; +} + +void WINAPI SWMRGDoneWriting(PSWMRG pSWMRG) +// Presumably, a writer thread calling this function has +// successfully called WaitToWrite. This means that we +// do not have to wait on any synchronization objects +// here because the writer already owns the Event. +{ +// Allow other writer/reader threads to use +// the SWMRG synchronization object. + SetEvent(pSWMRG->hEventNoWriter); +} + +DWORD WINAPI SWMRGWaitToRead(PSWMRG pSWMRG, DWORD dwTimeout) +{ + DWORD dw; + LONG lPreviousCount; + +// We can read if no threads are writing. +// And there's not request to delete structure + if(WAIT_OBJECT_0==(dw=WaitForSingleObject(pSWMRG->hFinishEV,0))) + return WAIT_FINISH; + if(WAIT_FAILED==dw) + return dw; + dw=WaitForSingleObject(pSWMRG->hEventNoWriter, dwTimeout); +// if a request to delete became later, we should not catch it. Try once more to ask if account is not about to delete + if((dw!=WAIT_FAILED) && (WAIT_OBJECT_0==(WaitForSingleObject(pSWMRG->hFinishEV,0)))) + { + SetEvent(pSWMRG->hEventNoWriter); + return WAIT_FINISH; + } + + if(dw==WAIT_OBJECT_0) + { + // This thread can read from the shared data. + // Increment the number of reader threads. + // But there can't be more than one thread incrementing readers, + // so this is why we use semaphore. + ReleaseSemaphore(pSWMRG->hSemNumReaders,1,&lPreviousCount); + if(lPreviousCount==0) + // If this is the first reader thread, + // set event to reflect this. Other reader threads can read, no writer thread can write. + ResetEvent(pSWMRG->hEventNoReaders); + + // Allow other writer/reader threads to use + // the SWMRG synchronization object. hEventNoWrite is still non-signaled + // (it looks like writer is processing thread, but it is not true) + SetEvent(pSWMRG->hEventNoWriter); + } + + return(dw); +} + +void WINAPI SWMRGDoneReading(PSWMRG pSWMRG) +{ + HANDLE aHandles[2]; + LONG lNumReaders; + +// We can stop reading if the events are available, +// but when we stop reading we must also decrement the +// number of reader threads. + aHandles[0]=pSWMRG->hEventNoWriter; + aHandles[1]=pSWMRG->hSemNumReaders; + WaitForMultipleObjects(2,aHandles,TRUE,INFINITE); + +// Get the remaining number of readers by releasing the +// semaphore and then restoring the count by immediately +// performing a wait. + ReleaseSemaphore(pSWMRG->hSemNumReaders,1,&lNumReaders); + WaitForSingleObject(pSWMRG->hSemNumReaders,INFINITE); + +// If there are no remaining readers, +// set the event to relect this. + if(lNumReaders==0) + // If there are no reader threads, + // set our event to reflect this. + SetEvent(pSWMRG->hEventNoReaders); + +// Allow other writer/reader threads to use +// the SWMRG synchronization object. +// (it looks like writer is processing thread, but it is not true) + SetEvent(pSWMRG->hEventNoWriter); +} + +DWORD WINAPI WaitToWriteFcn(PSWMRG SObject,PSCOUNTER SCounter) +{ + DWORD EnterCode; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tSO WaitToWrite: %x\n",SObject); +#endif + if(WAIT_OBJECT_0==(EnterCode=SWMRGWaitToWrite(SObject,INFINITE))) + if(SCounter!=NULL) + SCIncFcn(SCounter); + return EnterCode; +} + +void WINAPI WriteDoneFcn(PSWMRG SObject,PSCOUNTER SCounter) +{ +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tSO WriteDone: %x\n",SObject); +#endif + SWMRGDoneWriting(SObject); + if(SCounter!=NULL) + SCDecFcn(SCounter); +} + +DWORD WINAPI WaitToReadFcn(PSWMRG SObject) +{ + DWORD EnterCode; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tSO WaitToRead: %x\n",SObject); +#endif + EnterCode=SWMRGWaitToRead(SObject,INFINITE); + return EnterCode; +} + +void WINAPI ReadDoneFcn(PSWMRG SObject) +{ +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tSO ReadDone: %x\n",SObject); +#endif + SWMRGDoneReading(SObject); +} + +DWORD WINAPI SCGetNumberFcn(PSCOUNTER SCounter) +{ + DWORD Temp; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tGetNumber-cs wait\n"); +#endif + EnterCriticalSection(&SCounter->CounterCS); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tGetNumber-cs enter\n"); +#endif + Temp=SCounter->Number; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tValue: %d\n",Temp); + DebugLog(SynchroFile,"\tGetNumber-cs done\n"); +#endif + LeaveCriticalSection(&SCounter->CounterCS); + return Temp; +} + +DWORD WINAPI SCIncFcn(PSCOUNTER SCounter) +{ + DWORD Temp; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tIncrementValue-cs wait\n"); +#endif + EnterCriticalSection(&SCounter->CounterCS); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tIncrementValue-cs enter\n"); +#endif + Temp=++SCounter->Number; + ResetEvent(SCounter->Event); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tValue: %d\n",Temp); + DebugLog(SynchroFile,"\tIncrementValue-cs done\n"); +#endif + LeaveCriticalSection(&SCounter->CounterCS); + return Temp; +} + +DWORD WINAPI SCDecFcn(PSCOUNTER SCounter) +{ + DWORD Temp; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tDecrementValue-cs wait\n"); +#endif + EnterCriticalSection(&SCounter->CounterCS); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tDecrementValue-cs enter\n"); +#endif + if(!(Temp=--SCounter->Number)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tDecrementValue-zero ev set\n"); +#endif + SetEvent(SCounter->Event); + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"\tValue: %d\n",Temp); + DebugLog(SynchroFile,"\tDecrementValue-cs done\n"); +#endif + LeaveCriticalSection(&SCounter->CounterCS); + return Temp; +} diff --git a/yamn/version.h b/yamn/version.h new file mode 100644 index 0000000..e658cfe --- /dev/null +++ b/yamn/version.h @@ -0,0 +1,3 @@ +#define YAMN_VERSION_H 0,1,2,5 +#define YAMN_VERSION PLUGIN_MAKE_VERSION( 0,1,2,5 ) +#define YAMN_VERSION_C "0.1.2.5" diff --git a/yamn/yamn.cpp b/yamn/yamn.cpp new file mode 100644 index 0000000..467f3d6 --- /dev/null +++ b/yamn/yamn.cpp @@ -0,0 +1,478 @@ +/* + * This code implements miscellaneous usefull functions + * + * (c) majvan 2002-2004 + */ +#include "m_yamn.h" +#include "m_protoplugin.h" +#include "m_messages.h" +#include "m_synchro.h" +#include "main.h" +#include "yamn.h" +#ifdef DEBUG_SYNCHRO + #include +#endif + +//- imported --------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +extern PYAMN_PROTOPLUGINQUEUE FirstProtoPlugin; +extern YAMN_VARIABLES YAMNVar; + +extern char *ProtoName; + +extern HANDLE hTTButton; //TopToolBar button + +extern DWORD WriteAccountsToFile(); +extern DWORD WINAPI SWMRGWaitToRead(PSWMRG,DWORD); +extern void WINAPI SWMRGDoneReading(PSWMRG); +extern DWORD WINAPI WaitToReadFcn(PSWMRG); +extern void WINAPI ReadDoneFcn(PSWMRG); + +//From protoplugin.cpp +extern struct CExportedFunctions ProtoPluginExportedFcn[1]; +extern struct CExportedServices ProtoPluginExportedSvc[5]; +//From filterplugin.cpp +extern struct CExportedFunctions FilterPluginExportedFcn[1]; +extern struct CExportedServices FilterPluginExportedSvc[2]; +//From synchro.cpp +extern struct CExportedFunctions SynchroExportedFcn[7]; +//From account.cpp +extern struct CExportedFunctions AccountExportedFcn[2]; +extern struct CExportedServices AccountExportedSvc[9]; +//From mails.cpp (MIME) +extern struct CExportedFunctions MailExportedFcn[8]; +extern struct CExportedServices MailExportedSvc[5]; + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +//MessageWndCS +//We want to send messages to all windows in the queue +//When we send messages, no other window can register itself to the queue for receiving messages +LPCRITICAL_SECTION MessageWndCS; + +//Plugin registration CS +//Used if we add (register) plugin to YAMN plugins and when we browse through registered plugins +LPCRITICAL_SECTION PluginRegCS; + +//AccountWriterCS +//We want to store number of writers of Accounts (number of Accounts used for writing) +//If we want to read all accounts (for saving to file) immidiatelly, we have to wait until no account is changing (no thread writing to account) +SCOUNTER *AccountWriterSO; + +//NoExitEV +//Event that is signaled when there's a request to exit, so no new pop3 check should be performed +HANDLE ExitEV; + +//WriteToFileEV +//If this is signaled, write accounts to file is performed. Set this event if you want to actualize your accounts and messages +HANDLE WriteToFileEV; + +//Returns pointer to YAMN exported function +INT_PTR GetFcnPtrSvc(WPARAM wParam,LPARAM lParam); + +//Returns pointer to YAMN variables +INT_PTR GetVariablesSvc(WPARAM wParam,LPARAM); + +// Thread running only to catch hotkeys +DWORD WINAPI YAMNHotKeyThread(LPVOID Param); + +// Function every seconds decrements account counter of seconds and checks if they are 0 +// If yes, creates a POP3 thread to check account +void CALLBACK TimerProc(HWND,UINT,UINT,DWORD); + +// Function called to check all accounts immidialtelly +// no params +INT_PTR ForceCheckSvc(WPARAM,LPARAM); + +//thread is running all the time +//waits for WriteToFileEV and then writes all accounts to file +//DWORD WINAPI FileWritingThread(PVOID); + +// Function is called when Miranda notifies plugin that it is about to exit +// Ensures succesfull end of POP3 checking, sets event that no next checking should be performed +// If there's no writer to account (POP3 thread), saves the results to the file +//not used now, perhaps in the future + + +//int ExitProc(WPARAM wParam,LPARAM lParam); + +//-------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------- + +INT_PTR GetFcnPtrSvc(WPARAM wParam,LPARAM lParam) +{ + register int i; + + for(i=0;iNext) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"TimerProc:AccountBrowserSO-read wait\n"); +#endif + if(WAIT_OBJECT_0!=SWMRGWaitToRead(ActualPlugin->Plugin->AccountBrowserSO,0)) //we want to access accounts immiadtelly + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"TimerProc:AccountBrowserSO-read enter failed\n"); +#endif + LeaveCriticalSection(PluginRegCS); + return; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"TimerProc:AccountBrowserSO-read enter\n"); +#endif + for(ActualAccount=ActualPlugin->Plugin->FirstAccount;ActualAccount!=NULL;ActualAccount=ActualAccount->Next) + { + if(ActualAccount->Plugin==NULL || ActualAccount->Plugin->Fcn==NULL) //account not inited + continue; +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"TimerProc:ActualAccountSO-read wait\n"); +#endif + if(WAIT_OBJECT_0!=SWMRGWaitToRead(ActualAccount->AccountAccessSO,0)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"TimerProc:ActualAccountSO-read wait failed\n"); +#endif + continue; + } +#ifdef DEBUG_SYNCHRO + + switch(Status) + { + case ID_STATUS_OFFLINE: + DebugLog(SynchroFile,"TimerProc:ActualAccountSO-read enter status offline\n"); + break; + case ID_STATUS_ONLINE: + DebugLog(SynchroFile,"TimerProc:ActualAccountSO-read enter status online\n"); + break; + case ID_STATUS_AWAY: + DebugLog(SynchroFile,"TimerProc:ActualAccountSO-read enter status away\n"); + break; + case ID_STATUS_DND: + DebugLog(SynchroFile,"TimerProc:ActualAccountSO-read enter status dnd\n"); + break; + case ID_STATUS_NA: + DebugLog(SynchroFile,"TimerProc:ActualAccountSO-read enter status na\n"); + break; + case ID_STATUS_OCCUPIED: + DebugLog(SynchroFile,"TimerProc:ActualAccountSO-read enter status occupied\n"); + break; + case ID_STATUS_FREECHAT: + DebugLog(SynchroFile,"TimerProc:ActualAccountSO-read enter status freechat\n"); + break; + case ID_STATUS_INVISIBLE: + DebugLog(SynchroFile,"TimerProc:ActualAccountSO-read enter status invisible\n"); + break; + case ID_STATUS_ONTHEPHONE: + DebugLog(SynchroFile,"TimerProc:ActualAccountSO-read enter status onthephone\n"); + break; + case ID_STATUS_OUTTOLUNCH: + DebugLog(SynchroFile,"TimerProc:ActualAccountSO-read enter status outtolunch\n"); + break; + default: + DebugLog(SynchroFile,"TimerProc:ActualAccountSO-read enter status unknown\n"); + break; + } +#endif + BOOL isAccountCounting = 0; + if( + (ActualAccount->Flags & YAMN_ACC_ENA) && + (((ActualAccount->StatusFlags & YAMN_ACC_ST0) && (Status<=ID_STATUS_OFFLINE)) || + ((ActualAccount->StatusFlags & YAMN_ACC_ST1) && (Status==ID_STATUS_ONLINE)) || + ((ActualAccount->StatusFlags & YAMN_ACC_ST2) && (Status==ID_STATUS_AWAY)) || + ((ActualAccount->StatusFlags & YAMN_ACC_ST3) && (Status==ID_STATUS_DND)) || + ((ActualAccount->StatusFlags & YAMN_ACC_ST4) && (Status==ID_STATUS_NA)) || + ((ActualAccount->StatusFlags & YAMN_ACC_ST5) && (Status==ID_STATUS_OCCUPIED)) || + ((ActualAccount->StatusFlags & YAMN_ACC_ST6) && (Status==ID_STATUS_FREECHAT)) || + ((ActualAccount->StatusFlags & YAMN_ACC_ST7) && (Status==ID_STATUS_INVISIBLE)) || + ((ActualAccount->StatusFlags & YAMN_ACC_ST8) && (Status==ID_STATUS_ONTHEPHONE)) || + ((ActualAccount->StatusFlags & YAMN_ACC_ST9) && (Status==ID_STATUS_OUTTOLUNCH)))) + { + + if((!ActualAccount->Interval && !ActualAccount->TimeLeft) || ActualAccount->Plugin->Fcn->TimeoutFcnPtr==NULL) + { + goto ChangeIsCountingStatusLabel; + } + if(ActualAccount->TimeLeft){ + ActualAccount->TimeLeft--; + isAccountCounting = TRUE; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"TimerProc:time left : %i\n",ActualAccount->TimeLeft); +#endif + WindowList_BroadcastAsync(YAMNVar.MessageWnds,WM_YAMN_CHANGETIME,(WPARAM)ActualAccount,(LPARAM)ActualAccount->TimeLeft); + if(!ActualAccount->TimeLeft) + { + struct CheckParam ParamToPlugin={YAMN_CHECKVERSION,ThreadRunningEV,ActualAccount,YAMN_NORMALCHECK,(void *)0,NULL}; + HANDLE NewThread; + + ActualAccount->TimeLeft=ActualAccount->Interval; + if(NULL==(NewThread=CreateThread(NULL,0,(YAMN_STANDARDFCN)ActualAccount->Plugin->Fcn->TimeoutFcnPtr,&ParamToPlugin,0,&tid))) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"TimerProc:ActualAccountSO-read done\n"); +#endif + ReadDoneFcn(ActualAccount->AccountAccessSO); + continue; + } + else + { + WaitForSingleObject(ThreadRunningEV,INFINITE); + CloseHandle(NewThread); + } + } + + } +ChangeIsCountingStatusLabel: +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"TimerProc:ActualAccountSO-read done\n"); +#endif + if (((ActualAccount->isCounting)!=0)!=isAccountCounting){ + ActualAccount->isCounting=isAccountCounting; + WORD cStatus = DBGetContactSettingWord(ActualAccount->hContact,ProtoName,"Status",0); + switch (cStatus){ + case ID_STATUS_ONLINE: + case ID_STATUS_OFFLINE: + DBWriteContactSettingWord(ActualAccount->hContact, ProtoName, "Status", isAccountCounting?ID_STATUS_ONLINE:ID_STATUS_OFFLINE); + default: break; + } + } + ReadDoneFcn(ActualAccount->AccountAccessSO); + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"TimerProc:AccountBrowserSO-read done\n"); +#endif + SWMRGDoneReading(ActualPlugin->Plugin->AccountBrowserSO); + } + LeaveCriticalSection(PluginRegCS); + CloseHandle(ThreadRunningEV); + return; +} + +INT_PTR ForceCheckSvc(WPARAM,LPARAM) +{ + PYAMN_PROTOPLUGINQUEUE ActualPlugin; + HACCOUNT ActualAccount; + HANDLE ThreadRunningEV; + DWORD tid; + + //we use event to signal, that running thread has all needed stack parameters copied + if(NULL==(ThreadRunningEV=CreateEvent(NULL,FALSE,FALSE,NULL))) + return 0; + //if we want to close miranda, we get event and do not run pop3 checking anymore + if(WAIT_OBJECT_0==WaitForSingleObject(ExitEV,0)) + return 0; + EnterCriticalSection(PluginRegCS); + for(ActualPlugin=FirstProtoPlugin;ActualPlugin!=NULL;ActualPlugin=ActualPlugin->Next) + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ForceCheck:AccountBrowserSO-read wait\n"); + #endif + SWMRGWaitToRead(ActualPlugin->Plugin->AccountBrowserSO,INFINITE); + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ForceCheck:AccountBrowserSO-read enter\n"); + #endif + for(ActualAccount=ActualPlugin->Plugin->FirstAccount;ActualAccount!=NULL;ActualAccount=ActualAccount->Next) + { + if(ActualAccount->Plugin->Fcn==NULL) //account not inited + continue; + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ForceCheck:ActualAccountSO-read wait\n"); + #endif + if(WAIT_OBJECT_0!=WaitToReadFcn(ActualAccount->AccountAccessSO)) + { + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ForceCheck:ActualAccountSO-read wait failed\n"); + #endif + continue; + } + #ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ForceCheck:ActualAccountSO-read enter\n"); + #endif + if((ActualAccount->Flags & YAMN_ACC_ENA) && (ActualAccount->StatusFlags & YAMN_ACC_FORCE)) //account cannot be forced to check + { + if(ActualAccount->Plugin->Fcn->ForceCheckFcnPtr==NULL) + { + ReadDoneFcn(ActualAccount->AccountAccessSO); + continue; + } + struct CheckParam ParamToPlugin={YAMN_CHECKVERSION,ThreadRunningEV,ActualAccount,YAMN_FORCECHECK,(void *)0,NULL}; + + if(NULL==CreateThread(NULL,0,(YAMN_STANDARDFCN)ActualAccount->Plugin->Fcn->ForceCheckFcnPtr,&ParamToPlugin,0,&tid)) + { + ReadDoneFcn(ActualAccount->AccountAccessSO); + continue; + } + else + WaitForSingleObject(ThreadRunningEV,INFINITE); + } + ReadDoneFcn(ActualAccount->AccountAccessSO); + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ForceCheck:AccountBrowserSO-read done\n"); +#endif + SWMRGDoneReading(ActualPlugin->Plugin->AccountBrowserSO); + } + LeaveCriticalSection(PluginRegCS); + CloseHandle(ThreadRunningEV); + CallService(MS_TTB_SETBUTTONSTATE,(WPARAM)hTTButton,(LPARAM)TTBST_RELEASED); + return 1; +} +/* +int ExitProc(WPARAM wParam,LPARAM lParam) +{ + THIS WILL BE IMPLEMENTED LATER +// First, no thread must add or delete accounts. This is achieved by entering browsing through accounts +// If any thread want to delete or add, it waits for write-access to browse accounts (so it waits infinite time) +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ExitProc:AccountBrowserSO-wait to obtain read access\n")); +#endif + if(WAIT_TIMEOUT==SWMRGWaitToRead(AccountBrowserSO,0)) + { +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ExitProc:AccountBrowserSO-read access obtain failed, I'll try later\n")); +#endif + return 1; + } +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ExitProc:AccountBrowserSO-read access obtained\n")); +#endif +#ifdef DEBUG_SYNCHRO + TCHAR Debug[100]; + + _stprintf(Debug,_T("ExitProc:Writers: %d\n"),AccountWriterSO->GetNumber()); + DEBUG_SYNCHRO2F(Debug); + DebugLog(SynchroFile,"ExitProc:NoWriterEV-test\n")); +#endif +// next, threads must not write to any account. This works like hFinishEV event in AccountAccessSO and MessagesAccessSO. +// When hFinishEV is set, any beginning with reading and writing to account (messages) is failed. +// This is similar, but the difference is, that we can finish the whole work (we can decide: if ExitEV is set, should we +// end immidialtelly or should we continue (to end operation successfully)? +// E.g. I decided that once we started checking account, we get all new mails and then we can end. +// The second and more significant difference is, that ExitEV is signal to all accounts and messages, not only to one account. + + SetEvent(ExitEV); + if(WAIT_TIMEOUT==WaitForSingleObject(AccountWriterSO->Event,0)) + { +// There exists a thread writing to account, so we ca try later to write accounts to file, if no thread is writting +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ExitProc:NoWriterEV-writer(s) exists, I'll try later\n")); +#endif + SWMRGDoneReading(AccountBrowserSO); + return 1; + } + +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"ExitProc:NoWriterEV-no writer, going to save!\n")); +#endif +// Save to file + WriteAccountsToFile(); + SWMRGDoneReading(AccountBrowserSO); +// Now, all is saved, we can safe exit from Miranda + return 0; +} +*/ +/* +DWORD WINAPI FileWritingThread(PVOID) +{ + HACCOUNT ActualAccount=FirstAccount; + + while(1) + { + WaitForSingleObject(WriteToFileEV,INFINITE); +#ifdef DEBUG_SYNCHRO + DebugLog(SynchroFile,"FileWriting:WriteToFileEV-signaled\n")); +#endif +// now, write accounts and messages if it is possible. If it is not possible e.g. to read messages from one account, +// function will wait until messages are not used and then writes messages + WriteAccountsToFile(); + } + return 0; +} +*/ diff --git a/yamn/yamn.h b/yamn/yamn.h new file mode 100644 index 0000000..ee2fccb --- /dev/null +++ b/yamn/yamn.h @@ -0,0 +1,178 @@ +#ifndef __YAMN_H +#define __YAMN_H +#ifndef _WIN32_IE + #define _WIN32_IE 0x0400 +#endif +#ifndef _WIN32_WINNT + #define _WIN32_WINNT 0x0501 +#endif + +#if !defined(_WIN64) + #include "filter/simple/AggressiveOptimize.h" +#endif +#include +#include +#include +#include +#include //For _chdir() + +#define MIRANDA_VER 0x0600 + +#include //For hotkeys +#include "newpluginapi.h" //CallService,UnHookEvent +#include "m_utils.h" //window broadcasting +#include "m_system.h" +#include "m_skin.h" +#include "m_langpack.h" +#include "m_clist.h" +#include "m_clui.h" +#include "m_options.h" +#include "m_database.h" //database +#include "m_contacts.h" //contact +#include "m_protocols.h" //protocols +#include "m_protomod.h" //protocols module +#include "m_protosvc.h" +#include "include/m_uninstaller.h" //PluginUninstaller structures +#include "include/m_toptoolbar.h" +#include "m_icolib.h" +#include "include/m_kbdnotify.h" +#include "m_popup.h" +#include "include/m_updater.h" +#include "m_account.h" //Account structure and all needed structures to cooperate with YAMN +#include "m_messages.h" //Messages sent to YAMN windows +#include "mails/m_mails.h" //use YAMN's mails +#include "mails/m_decode.h" //use decoding macros (needed for header extracting) +#include "browser/m_browser.h" //we want to run YAMN mailbrowser, no new mail notification and bad connect window +#include "resources/resource.h" +#include "m_protoplugin.h" +#include "m_filterplugin.h" +#include "m_yamn.h" //Main YAMN's variables +#include "m_protoplugin.h" //Protocol registration and so on +#include "m_synchro.h" //Synchronization +#include "debug.h" +#include + + +//icons definitions +#define ICONSNUMBER 8 +#define ICONSDESCS "Neutral","YAMN","New Mail","Connect Fail","Launch Application","TopToolBar UP","TopToolBar Down","Offline" +#define ICONSNAMES "YAMN_Neutral",iconDescs[1],"YAMN_NewMail","YAMN_ConnectFail","YAMN_ApplExec","YAMN_TopToolBarUp","YAMN_TopToolBarDown","YAMN_Offline" +#define ICONSINDS IDI_ONLINE,IDI_ICOYAMN1,IDI_ICOYAMN2,IDI_NA,IDI_OCCUPIED,IDI_ICOTTBUP,IDI_OCCUPIED,IDI_OFFLINE + +//From services.cpp +void CreateServiceFunctions(void); +void DestroyServiceFunctions(void); +void HookEvents(void); +void UnhookEvents(void); +void RefreshContact(void); +void ContactDoubleclicked(WPARAM wParam,LPARAM lParam); +INT_PTR ClistContactDoubleclicked(WPARAM wParam, LPARAM lParam); + +//From debug.cpp +#undef YAMN_DEBUG +#ifdef YAMN_DEBUG +void InitDebug(); +void UnInitDebug(); +#endif + +//From synchro.cpp +//struct CExportedFunctions SynchroExported[]; + +//From yamn.cpp +INT_PTR GetFcnPtrSvc(WPARAM wParam,LPARAM lParam); +INT_PTR GetVariablesSvc(WPARAM,LPARAM); +//INT_PTR AddWndToYAMNWindowsSvc(WPARAM,LPARAM); +//INT_PTR RemoveWndFromYAMNWindowsSvc(WPARAM,LPARAM); +DWORD WINAPI YAMNHotKeyThread(LPVOID); +void CALLBACK TimerProc(HWND,UINT,UINT,DWORD); +INT_PTR ForceCheckSvc(WPARAM,LPARAM); +// int ExitProc(WPARAM,LPARAM); + +//From account.cpp +//struct CExportedFunctions AccountExported[]; +INT_PTR CreatePluginAccountSvc(WPARAM wParam,LPARAM lParam); +INT_PTR DeletePluginAccountSvc(WPARAM wParam,LPARAM lParam); +INT_PTR WriteAccountsToFileASvc(WPARAM wParam,LPARAM lParam); +INT_PTR WriteAccountsToFileWSvc(WPARAM wParam,LPARAM lParam); +INT_PTR AddAccountsFromFileASvc(WPARAM,LPARAM); +INT_PTR AddAccountsFromFileWSvc(WPARAM,LPARAM); +INT_PTR DeleteAccountSvc(WPARAM,LPARAM); +INT_PTR FindAccountByNameSvc(WPARAM wParam,LPARAM lParam); +INT_PTR GetNextFreeAccountSvc(WPARAM wParam,LPARAM lParam); + +//From protoplugin.cpp +//struct CExportedFunctions ProtoPluginExported[]; +INT_PTR UnregisterProtoPlugins(); +INT_PTR RegisterProtocolPluginSvc(WPARAM,LPARAM); +INT_PTR UnregisterProtocolPluginSvc(WPARAM,LPARAM); +INT_PTR GetFileNameWSvc(WPARAM,LPARAM); +INT_PTR GetFileNameASvc(WPARAM,LPARAM); +INT_PTR DeleteFileNameSvc(WPARAM,LPARAM); + +//From filterplugin.cpp +//struct CExportedFunctions FilterPluginExported[]; +INT_PTR UnregisterFilterPlugins(); +INT_PTR RegisterFilterPluginSvc(WPARAM,LPARAM); +INT_PTR UnregisterFilterPluginSvc(WPARAM,LPARAM); +INT_PTR FilterMailSvc(WPARAM,LPARAM); + +//From mails.cpp (MIME) +//struct CExportedFunctions MailExported[]; +INT_PTR CreateAccountMailSvc(WPARAM wParam,LPARAM lParam); +INT_PTR DeleteAccountMailSvc(WPARAM wParam,LPARAM lParam); +INT_PTR LoadMailDataSvc(WPARAM wParam,LPARAM lParam); +INT_PTR UnloadMailDataSvc(WPARAM wParam,LPARAM); +INT_PTR SaveMailDataSvc(WPARAM wParam,LPARAM lParam); + +//From mime.cpp +//void WINAPI ExtractHeaderFcn(char *,int,WORD,HYAMNMAIL); //already in MailExported +struct _tcptable +{ + char *NameBase,*NameSub; + BOOLEAN isValid; + unsigned short int CP; +}; +extern struct _tcptable CodePageNamesAll[]; // in mime/decode.cpp +extern int CPLENALL; +extern struct _tcptable *CodePageNamesSupp; // in mime/decode.cpp +extern int CPLENSUPP; +//#define CPDEFINDEX 63 //ISO-8859-1 +#define CPDEFINDEX 0 //ACP + +//From pop3comm.cpp +int RegisterPOP3Plugin(WPARAM,LPARAM); +int UninstallPOP3(PLUGINUNINSTALLPARAMS* ppup); //to uninstall POP3 plugin with YAMN + +//From mailbrowser.cpp +INT_PTR RunMailBrowserSvc(WPARAM,LPARAM); + +//From badconnect.cpp +INT_PTR RunBadConnectionSvc(WPARAM,LPARAM); + +//From YAMNopts.cpp +void WordToModAndVk(WORD,UINT *,UINT *); +int YAMNOptInitSvc(WPARAM,LPARAM); + +//From main.cpp +int PostLoad(WPARAM,LPARAM); //Executed after all plugins loaded YAMN reads mails from file and notify every protocol it should set its functions +int Shutdown(WPARAM,LPARAM); //Executed before Miranda is going to shutdown +int AddTopToolbarIcon(WPARAM,LPARAM); //Executed when TopToolBar plugin loaded Adds bitmap to toolbar +void LoadPlugins(); //Loads plugins located in MirandaDir/Plugins/YAMN/*.dll +int UninstallQuestionSvc(WPARAM,LPARAM); //Ask information when user wants to uninstall plugin + +//From synchro.cpp +extern DWORD WINAPI WaitToWriteFcn(PSWMRG SObject,PSCOUNTER SCounter=NULL); +extern void WINAPI WriteDoneFcn(PSWMRG SObject,PSCOUNTER SCounter=NULL); +extern DWORD WINAPI WaitToReadFcn(PSWMRG SObject); +extern void WINAPI ReadDoneFcn(PSWMRG SObject); +extern DWORD WINAPI SCIncFcn(PSCOUNTER SCounter); +extern DWORD WINAPI SCDecFcn(PSCOUNTER SCounter); +//From mails.cpp +extern void WINAPI DeleteMessageFromQueueFcn(HYAMNMAIL *From,HYAMNMAIL Which,int mode); +extern void WINAPI SetRemoveFlagsInQueueFcn(HYAMNMAIL From,DWORD FlagsSet,DWORD FlagsNotSet,DWORD FlagsToSet,int mode); +//From mime.cpp +void ExtractHeader(struct CMimeItem *items,int &CP,struct CHeader *head); +void DeleteHeaderContent(struct CHeader *head); +//From account.cpp +void WINAPI GetStatusFcn(HACCOUNT Which,char *Value); +#endif -- cgit v1.2.3