From cf0d0dace174aa2c0e2f8b5df009d02266e0c96a Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 13 Aug 2014 14:18:43 +0000 Subject: working C++ version restored git-svn-id: http://svn.miranda-ng.org/main/trunk@10178 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/SkypeClassic/SkypeClassic_10.vcxproj | 39 +- .../SkypeClassic/SkypeClassic_10.vcxproj.filters | 97 +- protocols/SkypeClassic/SkypeClassic_12.vcxproj | 32 +- .../SkypeClassic/SkypeClassic_12.vcxproj.filters | 33 +- protocols/SkypeClassic/Skype_protocol.dep | 415 --- protocols/SkypeClassic/Skype_protocol.dsp | 366 -- protocols/SkypeClassic/Skype_protocol.dsw | 29 - protocols/SkypeClassic/Skype_protocol.mak | 253 -- protocols/SkypeClassic/build/deploy.bat | 34 +- protocols/SkypeClassic/build/make.bat | 12 +- protocols/SkypeClassic/build/make_debug_w32.bat | 14 +- protocols/SkypeClassic/build/make_debug_w64.bat | 10 +- protocols/SkypeClassic/build/make_w32.bat | 14 +- protocols/SkypeClassic/build/make_w64.bat | 16 +- protocols/SkypeClassic/src/alogon.c | 129 - protocols/SkypeClassic/src/alogon.cpp | 129 + protocols/SkypeClassic/src/contacts.c | 427 --- protocols/SkypeClassic/src/contacts.cpp | 427 +++ protocols/SkypeClassic/src/debug.c | 75 - protocols/SkypeClassic/src/debug.cpp | 75 + protocols/SkypeClassic/src/gchat.c | 920 ----- protocols/SkypeClassic/src/gchat.cpp | 920 +++++ protocols/SkypeClassic/src/gchat.h | 2 +- protocols/SkypeClassic/src/memlist.c | 248 -- protocols/SkypeClassic/src/memlist.cpp | 248 ++ protocols/SkypeClassic/src/msglist.c | 86 - protocols/SkypeClassic/src/msglist.cpp | 86 + protocols/SkypeClassic/src/msgq.c | 90 - protocols/SkypeClassic/src/msgq.cpp | 90 + protocols/SkypeClassic/src/ng-compat/m_core.h | 52 - protocols/SkypeClassic/src/ng-compat/stdver.h | 9 - protocols/SkypeClassic/src/pthread.c | 70 - protocols/SkypeClassic/src/pthread.cpp | 70 + protocols/SkypeClassic/src/sdk/m_chat.h | 635 ---- protocols/SkypeClassic/src/sdk/m_folders.h | 207 -- protocols/SkypeClassic/src/sdk/m_metacontacts.h | 128 - protocols/SkypeClassic/src/sdk/m_toptoolbar.h | 125 - protocols/SkypeClassic/src/sdk/m_updater.h | 146 - protocols/SkypeClassic/src/sdk/m_voice.h | 158 - protocols/SkypeClassic/src/sdk/m_voiceservice.h | 86 - protocols/SkypeClassic/src/skype.c | 3569 -------------------- protocols/SkypeClassic/src/skype.cpp | 3433 +++++++++++++++++++ protocols/SkypeClassic/src/skype.h | 5 +- protocols/SkypeClassic/src/skypeapi.c | 1707 ---------- protocols/SkypeClassic/src/skypeapi.cpp | 1707 ++++++++++ protocols/SkypeClassic/src/skypeopt.c | 968 ------ protocols/SkypeClassic/src/skypeopt.cpp | 968 ++++++ protocols/SkypeClassic/src/skypeprofile.c | 145 - protocols/SkypeClassic/src/skypeprofile.cpp | 145 + protocols/SkypeClassic/src/skypesvc.c | 187 - protocols/SkypeClassic/src/skypesvc.cpp | 187 + protocols/SkypeClassic/src/utf8.c | 334 -- protocols/SkypeClassic/src/utf8.cpp | 334 ++ protocols/SkypeClassic/src/util.c | 57 - protocols/SkypeClassic/src/util.cpp | 57 + protocols/SkypeClassic/src/voiceservice.c | 169 - protocols/SkypeClassic/src/voiceservice.cpp | 169 + protocols/SkypeClassic/src/voiceservice.h | 36 +- 58 files changed, 9211 insertions(+), 11968 deletions(-) delete mode 100644 protocols/SkypeClassic/Skype_protocol.dep delete mode 100644 protocols/SkypeClassic/Skype_protocol.dsp delete mode 100644 protocols/SkypeClassic/Skype_protocol.dsw delete mode 100644 protocols/SkypeClassic/Skype_protocol.mak delete mode 100644 protocols/SkypeClassic/src/alogon.c create mode 100644 protocols/SkypeClassic/src/alogon.cpp delete mode 100644 protocols/SkypeClassic/src/contacts.c create mode 100644 protocols/SkypeClassic/src/contacts.cpp delete mode 100644 protocols/SkypeClassic/src/debug.c create mode 100644 protocols/SkypeClassic/src/debug.cpp delete mode 100644 protocols/SkypeClassic/src/gchat.c create mode 100644 protocols/SkypeClassic/src/gchat.cpp delete mode 100644 protocols/SkypeClassic/src/memlist.c create mode 100644 protocols/SkypeClassic/src/memlist.cpp delete mode 100644 protocols/SkypeClassic/src/msglist.c create mode 100644 protocols/SkypeClassic/src/msglist.cpp delete mode 100644 protocols/SkypeClassic/src/msgq.c create mode 100644 protocols/SkypeClassic/src/msgq.cpp delete mode 100644 protocols/SkypeClassic/src/ng-compat/m_core.h delete mode 100644 protocols/SkypeClassic/src/ng-compat/stdver.h delete mode 100644 protocols/SkypeClassic/src/pthread.c create mode 100644 protocols/SkypeClassic/src/pthread.cpp delete mode 100644 protocols/SkypeClassic/src/sdk/m_chat.h delete mode 100644 protocols/SkypeClassic/src/sdk/m_folders.h delete mode 100644 protocols/SkypeClassic/src/sdk/m_metacontacts.h delete mode 100644 protocols/SkypeClassic/src/sdk/m_toptoolbar.h delete mode 100644 protocols/SkypeClassic/src/sdk/m_updater.h delete mode 100644 protocols/SkypeClassic/src/sdk/m_voice.h delete mode 100644 protocols/SkypeClassic/src/sdk/m_voiceservice.h delete mode 100644 protocols/SkypeClassic/src/skype.c create mode 100644 protocols/SkypeClassic/src/skype.cpp delete mode 100644 protocols/SkypeClassic/src/skypeapi.c create mode 100644 protocols/SkypeClassic/src/skypeapi.cpp delete mode 100644 protocols/SkypeClassic/src/skypeopt.c create mode 100644 protocols/SkypeClassic/src/skypeopt.cpp delete mode 100644 protocols/SkypeClassic/src/skypeprofile.c create mode 100644 protocols/SkypeClassic/src/skypeprofile.cpp delete mode 100644 protocols/SkypeClassic/src/skypesvc.c create mode 100644 protocols/SkypeClassic/src/skypesvc.cpp delete mode 100644 protocols/SkypeClassic/src/utf8.c create mode 100644 protocols/SkypeClassic/src/utf8.cpp delete mode 100644 protocols/SkypeClassic/src/util.c create mode 100644 protocols/SkypeClassic/src/util.cpp delete mode 100644 protocols/SkypeClassic/src/voiceservice.c create mode 100644 protocols/SkypeClassic/src/voiceservice.cpp diff --git a/protocols/SkypeClassic/SkypeClassic_10.vcxproj b/protocols/SkypeClassic/SkypeClassic_10.vcxproj index 249f023193..ab43a5a327 100644 --- a/protocols/SkypeClassic/SkypeClassic_10.vcxproj +++ b/protocols/SkypeClassic/SkypeClassic_10.vcxproj @@ -45,6 +45,23 @@ + + + + + + + + + + + + + + + + + @@ -65,24 +82,6 @@ - - - - - - - - - - - - - - - - - - {5F9243AE-C6C9-4F42-B670-67A97767A50B} SkypeClassic @@ -149,7 +148,7 @@ Level3 true EditAndContinue - CompileAsCpp + Default ..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories) skype.h true @@ -217,7 +216,7 @@ true Level3 true - CompileAsCpp + Default ..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories) skype.h Fast diff --git a/protocols/SkypeClassic/SkypeClassic_10.vcxproj.filters b/protocols/SkypeClassic/SkypeClassic_10.vcxproj.filters index e53912c3e1..2157533a41 100644 --- a/protocols/SkypeClassic/SkypeClassic_10.vcxproj.filters +++ b/protocols/SkypeClassic/SkypeClassic_10.vcxproj.filters @@ -14,6 +14,53 @@ cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + Header Files @@ -143,54 +190,4 @@ Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - \ No newline at end of file diff --git a/protocols/SkypeClassic/SkypeClassic_12.vcxproj b/protocols/SkypeClassic/SkypeClassic_12.vcxproj index 99e8d4f513..b7868c7487 100644 --- a/protocols/SkypeClassic/SkypeClassic_12.vcxproj +++ b/protocols/SkypeClassic/SkypeClassic_12.vcxproj @@ -46,22 +46,21 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + @@ -147,7 +146,6 @@ MultiThreadedDebugDLL false Level3 - CompileAsCpp ..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories) true Fast diff --git a/protocols/SkypeClassic/SkypeClassic_12.vcxproj.filters b/protocols/SkypeClassic/SkypeClassic_12.vcxproj.filters index b96cbb11fb..2d9d1be44f 100644 --- a/protocols/SkypeClassic/SkypeClassic_12.vcxproj.filters +++ b/protocols/SkypeClassic/SkypeClassic_12.vcxproj.filters @@ -15,52 +15,49 @@ - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - - Source Files - - + Source Files diff --git a/protocols/SkypeClassic/Skype_protocol.dep b/protocols/SkypeClassic/Skype_protocol.dep deleted file mode 100644 index 37869f3145..0000000000 --- a/protocols/SkypeClassic/Skype_protocol.dep +++ /dev/null @@ -1,415 +0,0 @@ -# Microsoft Developer Studio erstellte Abhängigkeitsdatei, einbezogen von Skype_protocol.mak - -.\src\alogon.c : \ - "..\..\include\m_avatars.h"\ - "..\..\include\m_clist.h"\ - "..\..\include\m_contacts.h"\ - "..\..\include\m_database.h"\ - "..\..\include\m_langpack.h"\ - "..\..\include\m_message.h"\ - "..\..\include\m_options.h"\ - "..\..\include\m_plugins.h"\ - "..\..\include\m_popup.h"\ - "..\..\include\m_protocols.h"\ - "..\..\include\m_protomod.h"\ - "..\..\include\m_protosvc.h"\ - "..\..\include\m_skin.h"\ - "..\..\include\m_system.h"\ - "..\..\include\m_userinfo.h"\ - "..\..\include\m_utils.h"\ - "..\..\include\newpluginapi.h"\ - "..\..\include\statusmodes.h"\ - ".\src\debug.h"\ - ".\src\ng-compat\m_core.h"\ - ".\src\sdk\m_folders.h"\ - ".\src\sdk\m_metacontacts.h"\ - ".\src\sdk\m_updater.h"\ - ".\src\skype.h"\ - - -.\src\contacts.c : \ - "..\..\include\m_avatars.h"\ - "..\..\include\m_chat.h"\ - "..\..\include\m_clist.h"\ - "..\..\include\m_contacts.h"\ - "..\..\include\m_database.h"\ - "..\..\include\m_langpack.h"\ - "..\..\include\m_message.h"\ - "..\..\include\m_options.h"\ - "..\..\include\m_plugins.h"\ - "..\..\include\m_popup.h"\ - "..\..\include\m_protocols.h"\ - "..\..\include\m_protomod.h"\ - "..\..\include\m_protosvc.h"\ - "..\..\include\m_skin.h"\ - "..\..\include\m_system.h"\ - "..\..\include\m_userinfo.h"\ - "..\..\include\m_utils.h"\ - "..\..\include\newpluginapi.h"\ - "..\..\include\statusmodes.h"\ - ".\src\debug.h"\ - ".\src\gchat.h"\ - ".\src\ng-compat\m_core.h"\ - ".\src\pthread.h"\ - ".\src\sdk\m_folders.h"\ - ".\src\sdk\m_metacontacts.h"\ - ".\src\sdk\m_updater.h"\ - ".\src\sdk\m_voice.h"\ - ".\src\skype.h"\ - ".\src\skypeapi.h"\ - ".\src\voiceservice.h"\ - - -.\src\debug.c : \ - "..\..\include\m_avatars.h"\ - "..\..\include\m_clist.h"\ - "..\..\include\m_contacts.h"\ - "..\..\include\m_database.h"\ - "..\..\include\m_langpack.h"\ - "..\..\include\m_message.h"\ - "..\..\include\m_options.h"\ - "..\..\include\m_plugins.h"\ - "..\..\include\m_popup.h"\ - "..\..\include\m_protocols.h"\ - "..\..\include\m_protomod.h"\ - "..\..\include\m_protosvc.h"\ - "..\..\include\m_skin.h"\ - "..\..\include\m_system.h"\ - "..\..\include\m_userinfo.h"\ - "..\..\include\m_utils.h"\ - "..\..\include\newpluginapi.h"\ - "..\..\include\statusmodes.h"\ - ".\src\debug.h"\ - ".\src\ng-compat\m_core.h"\ - ".\src\sdk\m_folders.h"\ - ".\src\sdk\m_metacontacts.h"\ - ".\src\sdk\m_updater.h"\ - ".\src\skype.h"\ - - -.\src\gchat.c : \ - "..\..\include\m_avatars.h"\ - "..\..\include\m_chat.h"\ - "..\..\include\m_clist.h"\ - "..\..\include\m_contacts.h"\ - "..\..\include\m_database.h"\ - "..\..\include\m_history.h"\ - "..\..\include\m_langpack.h"\ - "..\..\include\m_message.h"\ - "..\..\include\m_options.h"\ - "..\..\include\m_plugins.h"\ - "..\..\include\m_popup.h"\ - "..\..\include\m_protocols.h"\ - "..\..\include\m_protomod.h"\ - "..\..\include\m_protosvc.h"\ - "..\..\include\m_skin.h"\ - "..\..\include\m_system.h"\ - "..\..\include\m_userinfo.h"\ - "..\..\include\m_utils.h"\ - "..\..\include\newpluginapi.h"\ - "..\..\include\statusmodes.h"\ - ".\src\contacts.h"\ - ".\src\debug.h"\ - ".\src\gchat.h"\ - ".\src\ng-compat\m_core.h"\ - ".\src\pthread.h"\ - ".\src\sdk\m_folders.h"\ - ".\src\sdk\m_metacontacts.h"\ - ".\src\sdk\m_updater.h"\ - ".\src\skype.h"\ - ".\src\skypeapi.h"\ - ".\src\utf8.h"\ - - -.\src\memlist.c : \ - ".\src\memlist.h"\ - - -.\src\msglist.c : \ - ".\src\debug.h"\ - ".\src\memlist.h"\ - ".\src\msglist.h"\ - - -.\src\msgq.c : \ - "..\..\include\m_avatars.h"\ - "..\..\include\m_clist.h"\ - "..\..\include\m_contacts.h"\ - "..\..\include\m_database.h"\ - "..\..\include\m_langpack.h"\ - "..\..\include\m_message.h"\ - "..\..\include\m_options.h"\ - "..\..\include\m_plugins.h"\ - "..\..\include\m_popup.h"\ - "..\..\include\m_protocols.h"\ - "..\..\include\m_protomod.h"\ - "..\..\include\m_protosvc.h"\ - "..\..\include\m_skin.h"\ - "..\..\include\m_system.h"\ - "..\..\include\m_userinfo.h"\ - "..\..\include\m_utils.h"\ - "..\..\include\newpluginapi.h"\ - "..\..\include\statusmodes.h"\ - ".\src\debug.h"\ - ".\src\msgq.h"\ - ".\src\ng-compat\m_core.h"\ - ".\src\sdk\m_folders.h"\ - ".\src\sdk\m_metacontacts.h"\ - ".\src\sdk\m_updater.h"\ - ".\src\skype.h"\ - - -.\src\pthread.c : \ - "..\..\include\m_avatars.h"\ - "..\..\include\m_clist.h"\ - "..\..\include\m_contacts.h"\ - "..\..\include\m_database.h"\ - "..\..\include\m_langpack.h"\ - "..\..\include\m_message.h"\ - "..\..\include\m_options.h"\ - "..\..\include\m_plugins.h"\ - "..\..\include\m_popup.h"\ - "..\..\include\m_protocols.h"\ - "..\..\include\m_protomod.h"\ - "..\..\include\m_protosvc.h"\ - "..\..\include\m_skin.h"\ - "..\..\include\m_system.h"\ - "..\..\include\m_userinfo.h"\ - "..\..\include\m_utils.h"\ - "..\..\include\newpluginapi.h"\ - "..\..\include\statusmodes.h"\ - ".\src\ng-compat\m_core.h"\ - ".\src\sdk\m_folders.h"\ - ".\src\sdk\m_metacontacts.h"\ - ".\src\sdk\m_updater.h"\ - ".\src\skype.h"\ - - -.\src\skype.c : \ - "..\..\include\m_avatars.h"\ - "..\..\include\m_chat.h"\ - "..\..\include\m_clist.h"\ - "..\..\include\m_contacts.h"\ - "..\..\include\m_database.h"\ - "..\..\include\m_langpack.h"\ - "..\..\include\m_message.h"\ - "..\..\include\m_options.h"\ - "..\..\include\m_plugins.h"\ - "..\..\include\m_popup.h"\ - "..\..\include\m_protocols.h"\ - "..\..\include\m_protomod.h"\ - "..\..\include\m_protosvc.h"\ - "..\..\include\m_skin.h"\ - "..\..\include\m_system.h"\ - "..\..\include\m_userinfo.h"\ - "..\..\include\m_utils.h"\ - "..\..\include\newpluginapi.h"\ - "..\..\include\statusmodes.h"\ - ".\src\contacts.h"\ - ".\src\debug.h"\ - ".\src\gchat.h"\ - ".\src\memlist.h"\ - ".\src\msglist.h"\ - ".\src\ng-compat\m_core.h"\ - ".\src\pthread.h"\ - ".\src\sdk\m_folders.h"\ - ".\src\sdk\m_metacontacts.h"\ - ".\src\sdk\m_toptoolbar.h"\ - ".\src\sdk\m_updater.h"\ - ".\src\sdk\m_voice.h"\ - ".\src\skype.h"\ - ".\src\skypeapi.h"\ - ".\src\skypesvc.h"\ - ".\src\utf8.h"\ - ".\src\voiceservice.h"\ - - -.\src\skypeapi.c : \ - "..\..\include\m_avatars.h"\ - "..\..\include\m_chat.h"\ - "..\..\include\m_clist.h"\ - "..\..\include\m_contacts.h"\ - "..\..\include\m_database.h"\ - "..\..\include\m_langpack.h"\ - "..\..\include\m_message.h"\ - "..\..\include\m_options.h"\ - "..\..\include\m_plugins.h"\ - "..\..\include\m_popup.h"\ - "..\..\include\m_protocols.h"\ - "..\..\include\m_protomod.h"\ - "..\..\include\m_protosvc.h"\ - "..\..\include\m_skin.h"\ - "..\..\include\m_system.h"\ - "..\..\include\m_userinfo.h"\ - "..\..\include\m_utils.h"\ - "..\..\include\newpluginapi.h"\ - "..\..\include\statusmodes.h"\ - ".\src\alogon.h"\ - ".\src\contacts.h"\ - ".\src\debug.h"\ - ".\src\gchat.h"\ - ".\src\msgq.h"\ - ".\src\ng-compat\m_core.h"\ - ".\src\pthread.h"\ - ".\src\sdk\m_folders.h"\ - ".\src\sdk\m_metacontacts.h"\ - ".\src\sdk\m_toptoolbar.h"\ - ".\src\sdk\m_updater.h"\ - ".\src\skype.h"\ - ".\src\skypeapi.h"\ - ".\src\skypeproxy.h"\ - ".\src\utf8.h"\ - - -.\src\skypeopt.c : \ - "..\..\include\m_avatars.h"\ - "..\..\include\m_chat.h"\ - "..\..\include\m_clist.h"\ - "..\..\include\m_contacts.h"\ - "..\..\include\m_database.h"\ - "..\..\include\m_langpack.h"\ - "..\..\include\m_message.h"\ - "..\..\include\m_options.h"\ - "..\..\include\m_plugins.h"\ - "..\..\include\m_popup.h"\ - "..\..\include\m_protocols.h"\ - "..\..\include\m_protomod.h"\ - "..\..\include\m_protosvc.h"\ - "..\..\include\m_skin.h"\ - "..\..\include\m_system.h"\ - "..\..\include\m_userinfo.h"\ - "..\..\include\m_utils.h"\ - "..\..\include\newpluginapi.h"\ - "..\..\include\statusmodes.h"\ - ".\src\ezxml\ezxml.c"\ - ".\src\ezxml\ezxml.h"\ - ".\src\gchat.h"\ - ".\src\ng-compat\m_core.h"\ - ".\src\pthread.h"\ - ".\src\sdk\m_folders.h"\ - ".\src\sdk\m_metacontacts.h"\ - ".\src\sdk\m_updater.h"\ - ".\src\skype.h"\ - ".\src\skypeopt.h"\ - ".\src\skypeprofile.h"\ - ".\src\utf8.h" - - -.\src\skypeprofile.c : \ - "..\..\include\m_avatars.h"\ - "..\..\include\m_clist.h"\ - "..\..\include\m_contacts.h"\ - "..\..\include\m_database.h"\ - "..\..\include\m_langpack.h"\ - "..\..\include\m_message.h"\ - "..\..\include\m_options.h"\ - "..\..\include\m_plugins.h"\ - "..\..\include\m_popup.h"\ - "..\..\include\m_protocols.h"\ - "..\..\include\m_protomod.h"\ - "..\..\include\m_protosvc.h"\ - "..\..\include\m_skin.h"\ - "..\..\include\m_system.h"\ - "..\..\include\m_userinfo.h"\ - "..\..\include\m_utils.h"\ - "..\..\include\newpluginapi.h"\ - "..\..\include\statusmodes.h"\ - ".\src\ng-compat\m_core.h"\ - ".\src\sdk\m_folders.h"\ - ".\src\sdk\m_metacontacts.h"\ - ".\src\sdk\m_updater.h"\ - ".\src\skype.h"\ - ".\src\skypeapi.h"\ - ".\src\skypeprofile.h"\ - ".\src\utf8.h"\ - - -.\src\skypesvc.c : \ - "..\..\include\m_avatars.h"\ - "..\..\include\m_clist.h"\ - "..\..\include\m_contacts.h"\ - "..\..\include\m_database.h"\ - "..\..\include\m_langpack.h"\ - "..\..\include\m_message.h"\ - "..\..\include\m_options.h"\ - "..\..\include\m_plugins.h"\ - "..\..\include\m_popup.h"\ - "..\..\include\m_protocols.h"\ - "..\..\include\m_protomod.h"\ - "..\..\include\m_protosvc.h"\ - "..\..\include\m_skin.h"\ - "..\..\include\m_system.h"\ - "..\..\include\m_userinfo.h"\ - "..\..\include\m_utils.h"\ - "..\..\include\newpluginapi.h"\ - "..\..\include\statusmodes.h"\ - ".\src\contacts.h"\ - ".\src\ng-compat\m_core.h"\ - ".\src\sdk\m_folders.h"\ - ".\src\sdk\m_metacontacts.h"\ - ".\src\sdk\m_toptoolbar.h"\ - ".\src\sdk\m_updater.h"\ - ".\src\skype.h"\ - ".\src\skypeapi.h"\ - ".\src\skypeopt.h"\ - ".\src\skypesvc.h"\ - - -.\src\utf8.c : \ - ".\src\utf8.h"\ - - -.\src\voiceservice.c : \ - "..\..\include\m_avatars.h"\ - "..\..\include\m_clist.h"\ - "..\..\include\m_contacts.h"\ - "..\..\include\m_database.h"\ - "..\..\include\m_langpack.h"\ - "..\..\include\m_message.h"\ - "..\..\include\m_options.h"\ - "..\..\include\m_plugins.h"\ - "..\..\include\m_popup.h"\ - "..\..\include\m_protocols.h"\ - "..\..\include\m_protomod.h"\ - "..\..\include\m_protosvc.h"\ - "..\..\include\m_skin.h"\ - "..\..\include\m_system.h"\ - "..\..\include\m_userinfo.h"\ - "..\..\include\m_utils.h"\ - "..\..\include\newpluginapi.h"\ - "..\..\include\statusmodes.h"\ - ".\src\ng-compat\m_core.h"\ - ".\src\sdk\m_folders.h"\ - ".\src\sdk\m_metacontacts.h"\ - ".\src\sdk\m_updater.h"\ - ".\src\sdk\m_voice.h"\ - ".\src\sdk\m_voiceservice.h"\ - ".\src\skype.h"\ - ".\src\skypeapi.h"\ - ".\src\skypesvc.h"\ - ".\src\voiceservice.h"\ - - -.\res\Resource.rc : \ - ".\res\add.ico"\ - ".\res\away.ico"\ - ".\res\call.bmp"\ - ".\res\call.ico"\ - ".\res\chat.ico"\ - ".\res\DND.ico"\ - ".\res\error.ico"\ - ".\res\hang_up.ico"\ - ".\res\hold.ico"\ - ".\res\import.ico"\ - ".\res\invisible.ico"\ - ".\res\Invite.ico"\ - ".\res\message.ico"\ - ".\res\NA.ico"\ - ".\res\occupied.ico"\ - ".\res\offline.ico"\ - ".\res\online.ico"\ - ".\res\phone.ico"\ - ".\res\resume.ico"\ - ".\res\skype.ico"\ - ".\res\skypeout.ico"\ - diff --git a/protocols/SkypeClassic/Skype_protocol.dsp b/protocols/SkypeClassic/Skype_protocol.dsp deleted file mode 100644 index e8d43866a0..0000000000 --- a/protocols/SkypeClassic/Skype_protocol.dsp +++ /dev/null @@ -1,366 +0,0 @@ -# Microsoft Developer Studio Project File - Name="Skype_protocol" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** NICHT BEARBEITEN ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=Skype_protocol - Win32 Debug UNICODE -!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 "Skype_protocol.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 "Skype_protocol.mak" CFG="Skype_protocol - Win32 Debug UNICODE" -!MESSAGE -!MESSAGE Für die Konfiguration stehen zur Auswahl: -!MESSAGE -!MESSAGE "Skype_protocol - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library") -!MESSAGE "Skype_protocol - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library") -!MESSAGE "Skype_protocol - Win32 Debug UNICODE" (basierend auf "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=xicl6.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Skype_protocol - 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 Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /I "src\ng-compat\\" /I "..\..\include" /I "src\sdk\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /YX /FD /c -# SUBTRACT CPP /Fr -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0xc07 /d "NDEBUG" -# ADD RSC /l 0xc07 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=xilink6.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 /nologo /dll /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 wsock32.lib comctl32.lib Rpcrt4.lib /nologo /dll /machine:I386 /out:"../../bin/release/plugins/skype.dll" - -!ELSEIF "$(CFG)" == "Skype_protocol - 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 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "src\ng-compat\\" /I "..\..\include" /I "src\sdk\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /YX /FD /GZ /c -# SUBTRACT CPP /Fr -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0xc07 /d "_DEBUG" -# ADD RSC /l 0xc07 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=xilink6.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 /nologo /dll /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 wsock32.lib comctl32.lib Rpcrt4.lib /nologo /dll /debug /machine:I386 /out:"../../bin/debug/plugins/Skype.dll" /pdbtype:sept -# SUBTRACT LINK32 /map - -!ELSEIF "$(CFG)" == "Skype_protocol - Win32 Debug UNICODE" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Skype_protocol___Win32_Debug_UNICODE" -# PROP BASE Intermediate_Dir "Skype_protocol___Win32_Debug_UNICODE" -# PROP BASE Ignore_Export_Lib 0 -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Skype_protocol___Win32_Debug_UNICODE" -# PROP Intermediate_Dir "Skype_protocol___Win32_Debug_UNICODE" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /YX /FD /GZ /c -# SUBTRACT BASE CPP /Fr -# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "src\ng-compat\\" /I "..\..\include" /I "src\sdk\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /D "UNICODE" /D "_UNICODE" /FR /YX /FD /GZ /c -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0xc07 /d "_DEBUG" -# ADD RSC /l 0xc07 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=xilink6.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 wsock32.lib comctl32.lib Rpcrt4.lib /nologo /dll /debug /machine:I386 /out:"../../bin/debug/plugins/Skype.dll" /pdbtype:sept -# SUBTRACT BASE LINK32 /map -# 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 wsock32.lib comctl32.lib Rpcrt4.lib /nologo /dll /debug /machine:I386 /out:"../../bin/debug Unicode/plugins/Skype.dll" /pdbtype:sept -# SUBTRACT LINK32 /map - -!ENDIF - -# Begin Target - -# Name "Skype_protocol - Win32 Release" -# Name "Skype_protocol - Win32 Debug" -# Name "Skype_protocol - Win32 Debug UNICODE" -# Begin Group "Quellcodedateien" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\src\alogon.c -# End Source File -# Begin Source File - -SOURCE=.\src\contacts.c -# End Source File -# Begin Source File - -SOURCE=.\src\debug.c -# End Source File -# Begin Source File - -SOURCE=.\src\gchat.c -# End Source File -# Begin Source File - -SOURCE=.\src\memlist.c -# End Source File -# Begin Source File - -SOURCE=.\src\msglist.c -# End Source File -# Begin Source File - -SOURCE=.\src\msgq.c -# End Source File -# Begin Source File - -SOURCE=.\src\pthread.c -# End Source File -# Begin Source File - -SOURCE=.\src\skype.c -# End Source File -# Begin Source File - -SOURCE=.\src\skypeapi.c -# End Source File -# Begin Source File - -SOURCE=.\src\skypeopt.c -# End Source File -# Begin Source File - -SOURCE=.\src\skypeprofile.c -# End Source File -# Begin Source File - -SOURCE=.\src\skypesvc.c -# End Source File -# Begin Source File - -SOURCE=.\src\utf8.c -# End Source File -# Begin Source File - -SOURCE=.\src\util.c -# End Source File -# Begin Source File - -SOURCE=.\src\voiceservice.c -# End Source File -# End Group -# Begin Group "Header-Dateien" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\src\alogon.h -# End Source File -# Begin Source File - -SOURCE=.\src\contacts.h -# End Source File -# Begin Source File - -SOURCE=.\src\debug.h -# End Source File -# Begin Source File - -SOURCE=.\src\gchat.h -# End Source File -# Begin Source File - -SOURCE=.\src\m_popup.h -# End Source File -# Begin Source File - -SOURCE=.\src\m_toptoolbar.h -# End Source File -# Begin Source File - -SOURCE=.\src\memlist.h -# End Source File -# Begin Source File - -SOURCE=.\src\msglist.h -# End Source File -# Begin Source File - -SOURCE=.\src\msgq.h -# End Source File -# Begin Source File - -SOURCE=.\src\pthread.h -# End Source File -# Begin Source File - -SOURCE=.\src\skype.h -# End Source File -# Begin Source File - -SOURCE=.\src\skypeapi.h -# End Source File -# Begin Source File - -SOURCE=.\src\skypeopt.h -# End Source File -# Begin Source File - -SOURCE=.\src\skypeprofile.h -# End Source File -# Begin Source File - -SOURCE=.\src\skypesvc.h -# End Source File -# Begin Source File - -SOURCE=.\src\utf8.h -# End Source File -# Begin Source File - -SOURCE=.\src\util.h -# End Source File -# Begin Source File - -SOURCE=.\src\voiceservice.h -# End Source File -# End Group -# Begin Group "Ressourcendateien" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# Begin Source File - -SOURCE=.\res\add.ico -# End Source File -# Begin Source File - -SOURCE=.\res\away.ico -# End Source File -# Begin Source File - -SOURCE=.\res\call.bmp -# End Source File -# Begin Source File - -SOURCE=.\res\call.ico -# End Source File -# Begin Source File - -SOURCE=.\res\chat.ico -# End Source File -# Begin Source File - -SOURCE=.\res\DND.ico -# End Source File -# Begin Source File - -SOURCE=.\res\error.ico -# End Source File -# Begin Source File - -SOURCE=.\res\hang_up.ico -# End Source File -# Begin Source File - -SOURCE=.\res\hold.ico -# End Source File -# Begin Source File - -SOURCE=.\res\import.ico -# End Source File -# Begin Source File - -SOURCE=.\res\invisible.ico -# End Source File -# Begin Source File - -SOURCE=.\res\Invite.ico -# End Source File -# Begin Source File - -SOURCE=.\res\message.ico -# End Source File -# Begin Source File - -SOURCE=.\res\NA.ico -# End Source File -# Begin Source File - -SOURCE=.\res\occupied.ico -# End Source File -# Begin Source File - -SOURCE=.\res\offline.ico -# End Source File -# Begin Source File - -SOURCE=.\res\online.ico -# End Source File -# Begin Source File - -SOURCE=.\res\phone.ico -# End Source File -# Begin Source File - -SOURCE=.\res\Resource.rc -# End Source File -# Begin Source File - -SOURCE=.\res\resume.ico -# End Source File -# Begin Source File - -SOURCE=.\res\skype.ico -# End Source File -# Begin Source File - -SOURCE=.\res\skypeout.ico -# End Source File -# End Group -# Begin Source File - -SOURCE=.\changelog.txt -# End Source File -# End Target -# End Project diff --git a/protocols/SkypeClassic/Skype_protocol.dsw b/protocols/SkypeClassic/Skype_protocol.dsw deleted file mode 100644 index 3965e55d3e..0000000000 --- a/protocols/SkypeClassic/Skype_protocol.dsw +++ /dev/null @@ -1,29 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN! - -############################################################################### - -Project: "Skype_protocol"=.\Skype_protocol.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/protocols/SkypeClassic/Skype_protocol.mak b/protocols/SkypeClassic/Skype_protocol.mak deleted file mode 100644 index 09154ac812..0000000000 --- a/protocols/SkypeClassic/Skype_protocol.mak +++ /dev/null @@ -1,253 +0,0 @@ -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE Keine Konfiguration angegeben. Win32 Debug wird als Standard verwendet. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" && "$(CFG)" != "Win64 Release" && "$(CFG)" != "Win64 Debug" && "$(CFG)" != "Win32 UNICODE Release" && "$(CFG)" != "Win32 UNICODE Debug" && "$(CFG)" != "Win64 UNICODE Release" && "$(CFG)" != "Win64 UNICODE Debug" -!MESSAGE Ungültige Konfiguration "$(CFG)" angegeben. -!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 "Skype_protocol.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Für die Konfiguration stehen zur Auswahl: -!MESSAGE -!MESSAGE "Win32 Release" -!MESSAGE "Win32 Debug" -!MESSAGE "Win64 Release" -!MESSAGE "Win64 Debug" -!MESSAGE "Win32 UNICODE Release" -!MESSAGE "Win32 UNICODE Debug" -!MESSAGE "Win64 UNICODE Release" -!MESSAGE "Win64 UNICODE Debug" - -!MESSAGE -!ERROR Eine ungültige Konfiguration wurde angegeben. -!ENDIF - -!IF "$(OS)" == "Windows_NT" -NULL= -!ELSE -NULL=nul -!ENDIF - -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe -LINK32=link.exe - -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib wsock32.lib comctl32.lib Rpcrt4.lib /nologo /dll /pdb:"$(INTDIR)\skype.pdb" /out:"$(OUTDIR)/skype.dll" /implib:"$(INTDIR)\skype.lib" -CPPFL=/nologo /W3 /GX- /GR- /TC /I "src/ng-compat/" /I "../../include" /I "src/sdk/" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /Fp"$(INTDIR)\Skype_protocol.pch" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c - -!IF "$(CFG)" == "Win64 Release" -OUTDIR=.\Release64 -INTDIR=.\Release64 -CPP_PROJ=$(CPPFL) /MD /O2 /D "NDEBUG" -LINK32_FLAGS=$(LINK32_FLAGS) /incremental:no -MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 -RSC_PROJ=/l 0xc07 /fo"$(INTDIR)\Resource.res" /d "NDEBUG" -!ELSEIF "$(CFG)" == "Win32 Release" -OUTDIR=.\Release -INTDIR=.\Release -CPP_PROJ=$(CPPFL) /MD /O2 /D "NDEBUG" -LINK32_FLAGS=$(LINK32_FLAGS) /incremental:no -MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 -RSC_PROJ=/l 0xc07 /fo"$(INTDIR)\Resource.res" /d "NDEBUG" -!ELSEIF "$(CFG)" == "Win64 Debug" -OUTDIR=Debug64 -INTDIR=$(OUTDIR) -CPP_PROJ=$(CPPFL) /MDd /Gm /Zi /Od /D "_DEBUG" /GZ -LINK32_FLAGS=$(LINK32_FLAGS) /incremental:yes /debug /pdbtype:sept -MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 -RSC_PROJ=/l 0xc07 /fo"$(INTDIR)\Resource.res" /d "_DEBUG" -!ELSEIF "$(CFG)" == "Win32 Debug" -OUTDIR=.\Debug -INTDIR=$(OUTDIR) -CPP_PROJ=$(CPPFL) /MDd /Gm /Zi /Od /D "_DEBUG" /GZ -LINK32_FLAGS=$(LINK32_FLAGS) /incremental:yes /debug /pdbtype:sept -MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 -RSC_PROJ=/l 0xc07 /fo"$(INTDIR)\Resource.res" /d "_DEBUG" -!ELSEIF "$(CFG)" == "Win64 UNICODE Release" -OUTDIR=.\Release64-UNICODE -INTDIR=.\Release64-UNICODE -CPP_PROJ=$(CPPFL) /MD /O2 /D "NDEBUG" /D "UNICODE" /D "_UNICODE" -LINK32_FLAGS=$(LINK32_FLAGS) /incremental:no -MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 -RSC_PROJ=/l 0xc07 /fo"$(INTDIR)\Resource.res" /d "NDEBUG" -!ELSEIF "$(CFG)" == "Win32 UNICODE Release" -OUTDIR=.\Release-UNICODE -INTDIR=.\Release-UNICODE -CPP_PROJ=$(CPPFL) /MD /O2 /D "NDEBUG" /D "UNICODE" /D "_UNICODE" -LINK32_FLAGS=$(LINK32_FLAGS) /incremental:no -MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 -RSC_PROJ=/l 0xc07 /fo"$(INTDIR)\Resource.res" /d "NDEBUG" -!ELSEIF "$(CFG)" == "Win64 UNICODE Debug" -OUTDIR=Debug64-UNICODE -INTDIR=$(OUTDIR) -CPP_PROJ=$(CPPFL) /MDd /Gm /Zi /Od /D "_DEBUG" /D "UNICODE" /D "_UNICODE" -LINK32_FLAGS= $(LINK32_FLAGS) /incremental:yes /debug /pdbtype:sept -MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 -RSC_PROJ=/l 0xc07 /fo"$(INTDIR)\Resource.res" /d "_DEBUG" -!ELSEIF "$(CFG)" == "Win32 UNICODE Debug" -OUTDIR=.\Debug-UNICODE -INTDIR=$(OUTDIR) -CPP_PROJ=$(CPPFL) /MDd /Gm /Zi /Od /D "_DEBUG" /D "UNICODE" /D "_UNICODE" /GZ -LINK32_FLAGS=$(LINK32_FLAGS) /incremental:yes /debug /pdbtype:sept -MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 -RSC_PROJ=/l 0xc07 /fo"$(INTDIR)\Resource.res" /d "_DEBUG" -!ENDIF - -LINK32_OBJS= \ - "$(INTDIR)\contacts.obj" \ - "$(INTDIR)\debug.obj" \ - "$(INTDIR)\gchat.obj" \ - "$(INTDIR)\pthread.obj" \ - "$(INTDIR)\skype.obj" \ - "$(INTDIR)\skypeapi.obj" \ - "$(INTDIR)\skypeopt.obj" \ - "$(INTDIR)\skypeprofile.obj" \ - "$(INTDIR)\skypesvc.obj" \ - "$(INTDIR)\utf8.obj" \ - "$(INTDIR)\voiceservice.obj" \ - "$(INTDIR)\msglist.obj" \ - "$(INTDIR)\memlist.obj" \ - "$(INTDIR)\util.obj" \ - "$(INTDIR)\msgq.obj" \ - "$(INTDIR)\alogon.obj" \ - "$(INTDIR)\Resource.res" - -ALL : "$(OUTDIR)\skype.dll" - - -CLEAN : - -@erase "$(INTDIR)\contacts.obj" - -@erase "$(INTDIR)\debug.obj" - -@erase "$(INTDIR)\gchat.obj" - -@erase "$(INTDIR)\pthread.obj" - -@erase "$(INTDIR)\Resource.res" - -@erase "$(INTDIR)\skype.obj" - -@erase "$(INTDIR)\skypeapi.obj" - -@erase "$(INTDIR)\skypeopt.obj" - -@erase "$(INTDIR)\skypeprofile.obj" - -@erase "$(INTDIR)\skypesvc.obj" - -@erase "$(INTDIR)\msglist.obj" - -@erase "$(INTDIR)\memlist.obj" - -@erase "$(INTDIR)\util.obj" - -@erase "$(INTDIR)\msgq.obj" \ - -@erase "$(INTDIR)\alogon.obj" \ - -@erase "$(INTDIR)\utf8.obj" - -@erase "$(INTDIR)\vc60.idb" - -@erase "$(INTDIR)\voiceservice.obj" - -@erase "$(INTDIR)\skype.exp" - -@erase "$(INTDIR)\skype.pdb" - -@erase "$(INTDIR)\skype.lib" - -@erase "$(OUTDIR)\skype.dll" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -.c{$(INTDIR)}.obj:: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -"$(OUTDIR)\skype.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - - -!IF "$(NO_EXTERNAL_DEPS)" != "1" -!IF EXISTS("Skype_protocol.dep") -!INCLUDE "Skype_protocol.dep" -!ELSE -!MESSAGE Warning: cannot find "Skype_protocol.dep" -!ENDIF -!ENDIF - - -SOURCE=.\src\alogon.c - -"$(INTDIR)\alogon.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=.\src\contacts.c - -"$(INTDIR)\contacts.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=.\src\debug.c - -"$(INTDIR)\debug.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=.\src\gchat.c - -"$(INTDIR)\gchat.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=.\src\msgq.c - -"$(INTDIR)\msgq.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=.\src\msglist.c - -"$(INTDIR)\msglist.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=.\src\memlist.c - -"$(INTDIR)\memlist.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=.\src\pthread.c - -"$(INTDIR)\pthread.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=.\src\skype.c - -"$(INTDIR)\skype.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=.\src\skypeapi.c - -"$(INTDIR)\skypeapi.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=.\src\skypeopt.c - -"$(INTDIR)\skypeopt.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=.\src\skypeprofile.c - -"$(INTDIR)\skypeprofile.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=.\src\skypesvc.c - -"$(INTDIR)\skypesvc.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=.\src\utf8.c - -"$(INTDIR)\utf8.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=.\src\util.c - -"$(INTDIR)\util.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=.\src\voiceservice.c - -"$(INTDIR)\voiceservice.obj" : $(SOURCE) "$(INTDIR)" - $(CPP) $(CPP_PROJ) $(SOURCE) - -SOURCE=.\res\Resource.rc - -"$(INTDIR)\Resource.res" : $(SOURCE) "$(INTDIR)" - $(RSC) $(RSC_PROJ) $(SOURCE) - diff --git a/protocols/SkypeClassic/build/deploy.bat b/protocols/SkypeClassic/build/deploy.bat index 2b3b25687d..6beabe6439 100644 --- a/protocols/SkypeClassic/build/deploy.bat +++ b/protocols/SkypeClassic/build/deploy.bat @@ -1,17 +1,17 @@ -@echo off -set PATH=%PATH%;C:\Programme\WinRAR -echo Deploying.. -pushd .. -winrar a -apPlugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol.zip Release\skype.dll -rem There is no ANSI x64 Build -rem winrar a -apPlugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_x64.zip Release64\skype.dll -winrar a -apPlugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_unicode.zip Release-UNICODE\skype.dll -winrar a -apPlugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_unicode_x64.zip Release64-UNICODE\skype.dll - -winrar a -apDebug -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_debug.zip Debug\skype.pdb -winrar a -apDebug\Plugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_debug.zip Debug\skype.dll -winrar a -apDebug64-UNICODE -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_debug.zip Debug64-UNICODE\skype.pdb -winrar a -apDebug64-UNICODE\Plugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_debug.zip Debug64-UNICODE\skype.dll -winrar a -apDebug-UNICODE -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_debug.zip Debug-UNICODE\skype.pdb -winrar a -apDebug-UNICODE\Plugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_debug.zip Debug-UNICODE\skype.dll -popd +@echo off +set PATH=%PATH%;C:\Programme\WinRAR +echo Deploying.. +pushd .. +winrar a -apPlugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol.zip Release\skype.dll +rem There is no ANSI x64 Build +rem winrar a -apPlugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_x64.zip Release64\skype.dll +winrar a -apPlugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_unicode.zip Release-UNICODE\skype.dll +winrar a -apPlugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_unicode_x64.zip Release64-UNICODE\skype.dll + +winrar a -apDebug -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_debug.zip Debug\skype.pdb +winrar a -apDebug\Plugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_debug.zip Debug\skype.dll +winrar a -apDebug64-UNICODE -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_debug.zip Debug64-UNICODE\skype.pdb +winrar a -apDebug64-UNICODE\Plugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_debug.zip Debug64-UNICODE\skype.dll +winrar a -apDebug-UNICODE -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_debug.zip Debug-UNICODE\skype.pdb +winrar a -apDebug-UNICODE\Plugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_debug.zip Debug-UNICODE\skype.dll +popd diff --git a/protocols/SkypeClassic/build/make.bat b/protocols/SkypeClassic/build/make.bat index 0821b0041f..1e947ad005 100644 --- a/protocols/SkypeClassic/build/make.bat +++ b/protocols/SkypeClassic/build/make.bat @@ -1,6 +1,6 @@ -cmd /c make_w32 -cmd /c make_w64 -cmd /c make_debug_w32 -cmd /c make_debug_w64 -pause -deploy +cmd /c make_w32 +cmd /c make_w64 +cmd /c make_debug_w32 +cmd /c make_debug_w64 +pause +deploy diff --git a/protocols/SkypeClassic/build/make_debug_w32.bat b/protocols/SkypeClassic/build/make_debug_w32.bat index dc8609885b..5e89655e60 100644 --- a/protocols/SkypeClassic/build/make_debug_w32.bat +++ b/protocols/SkypeClassic/build/make_debug_w32.bat @@ -1,7 +1,7 @@ -call "F:\Programme\Microsoft Visual Studio\VC98\Bin\VCVARS32.BAT" -pushd .. -nmake -f Skype_protocol.mak CFG="Win32 UNICODE Debug" clean -nmake -f Skype_protocol.mak CFG="Win32 UNICODE Debug" -nmake -f Skype_protocol.mak CFG="Win32 Debug" clean -nmake -f Skype_protocol.mak CFG="Win32 Debug" -popd +call "F:\Programme\Microsoft Visual Studio\VC98\Bin\VCVARS32.BAT" +pushd .. +nmake -f Skype_protocol.mak CFG="Win32 UNICODE Debug" clean +nmake -f Skype_protocol.mak CFG="Win32 UNICODE Debug" +nmake -f Skype_protocol.mak CFG="Win32 Debug" clean +nmake -f Skype_protocol.mak CFG="Win32 Debug" +popd diff --git a/protocols/SkypeClassic/build/make_debug_w64.bat b/protocols/SkypeClassic/build/make_debug_w64.bat index cb3c8ab315..e52f94b05e 100644 --- a/protocols/SkypeClassic/build/make_debug_w64.bat +++ b/protocols/SkypeClassic/build/make_debug_w64.bat @@ -1,5 +1,5 @@ -call f:\PlatformSDK\SetEnv /X64 /RETAIL -pushd .. -nmake -f Skype_protocol.mak CFG="Win64 UNICODE Debug" clean -nmake -f Skype_protocol.mak CFG="Win64 UNICODE Debug" -popd +call f:\PlatformSDK\SetEnv /X64 /RETAIL +pushd .. +nmake -f Skype_protocol.mak CFG="Win64 UNICODE Debug" clean +nmake -f Skype_protocol.mak CFG="Win64 UNICODE Debug" +popd diff --git a/protocols/SkypeClassic/build/make_w32.bat b/protocols/SkypeClassic/build/make_w32.bat index c888c2e6f3..466966e699 100644 --- a/protocols/SkypeClassic/build/make_w32.bat +++ b/protocols/SkypeClassic/build/make_w32.bat @@ -1,7 +1,7 @@ -call "F:\Programme\Microsoft Visual Studio\VC98\Bin\VCVARS32.BAT" -pushd .. -nmake -f Skype_protocol.mak CFG="Win32 Release" clean -nmake -f Skype_protocol.mak CFG="Win32 Release" -nmake -f Skype_protocol.mak CFG="Win32 UNICODE Release" clean -nmake -f Skype_protocol.mak CFG="Win32 UNICODE Release" -popd +call "F:\Programme\Microsoft Visual Studio\VC98\Bin\VCVARS32.BAT" +pushd .. +nmake -f Skype_protocol.mak CFG="Win32 Release" clean +nmake -f Skype_protocol.mak CFG="Win32 Release" +nmake -f Skype_protocol.mak CFG="Win32 UNICODE Release" clean +nmake -f Skype_protocol.mak CFG="Win32 UNICODE Release" +popd diff --git a/protocols/SkypeClassic/build/make_w64.bat b/protocols/SkypeClassic/build/make_w64.bat index b553650866..fdab907c07 100644 --- a/protocols/SkypeClassic/build/make_w64.bat +++ b/protocols/SkypeClassic/build/make_w64.bat @@ -1,8 +1,8 @@ -call f:\PlatformSDK\SetEnv /X64 /RETAIL -pushd .. -rem There is no ANSI x64 Miranda build -rem nmake -f Skype_protocol.mak CFG="Win64 Release" clean -rem nmake -f Skype_protocol.mak CFG="Win64 Release" -nmake -f Skype_protocol.mak CFG="Win64 UNICODE Release" clean -nmake -f Skype_protocol.mak CFG="Win64 UNICODE Release" -popd +call f:\PlatformSDK\SetEnv /X64 /RETAIL +pushd .. +rem There is no ANSI x64 Miranda build +rem nmake -f Skype_protocol.mak CFG="Win64 Release" clean +rem nmake -f Skype_protocol.mak CFG="Win64 Release" +nmake -f Skype_protocol.mak CFG="Win64 UNICODE Release" clean +nmake -f Skype_protocol.mak CFG="Win64 UNICODE Release" +popd diff --git a/protocols/SkypeClassic/src/alogon.c b/protocols/SkypeClassic/src/alogon.c deleted file mode 100644 index 8002d495fc..0000000000 --- a/protocols/SkypeClassic/src/alogon.c +++ /dev/null @@ -1,129 +0,0 @@ -#include "skype.h" -#include "debug.h" - -extern char g_szProtoName[]; -extern HANDLE SkypeReady; - -/** - * Purpose: Retrieves class name from window - * - * Note: This is some sort of hack to return static local variable, - * but it works :) - */ -static const TCHAR* getClassName(HWND wnd) -{ - static TCHAR className[256]; - - *className=0; - GetClassName(wnd, &className[0], sizeof(className)/sizeof(className[0])); - return className; -} - -/** - * Purpose: Finds a window - * - * Note: This function relies on Skype window placement. - * It should work for Skype 3.x - */ -static HWND findWindow(HWND parent, const TCHAR* childClassName) -{ - // Get child window - // This window is not combo box or edit box - HWND wnd = GetWindow(parent, GW_CHILD); - while(wnd != NULL && _tcscmp(getClassName(wnd), childClassName) != 0) - wnd = GetWindow(wnd, GW_HWNDNEXT); - - return wnd; -} - -static BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) -{ - DWORD dwPID; - const TCHAR *lpszClassName; - - - GetWindowThreadProcessId(hWnd,&dwPID); - if (lParam != 0 && dwPID != (DWORD)lParam) return TRUE; - lpszClassName = getClassName(hWnd); - if(_tcscmp(lpszClassName, _T("tSkMainForm.UnicodeClass")) == 0 || - _tcscmp(lpszClassName, _T("TLoginForm.UnicodeClass")) == 0) - { - HWND loginControl = GetWindow(hWnd, GW_CHILD); - - LOG(("setUserNamePasswordThread: Skype window found!")); - - // Sleep for some time, while Skype is loading - // It loads slowly :( - //Sleep(5000); - LOG (("TLoginControl = %S", getClassName(loginControl))); - - // Check for login control - if(_tcscmp(getClassName(loginControl), _T("TLoginControl")) == 0) - { - // Find user name window - HWND userName = findWindow(loginControl, _T("TNavigableTntComboBox.UnicodeClass")); - HWND password = findWindow(loginControl, _T("TNavigableTntEdit.UnicodeClass")); - - LOG (("userName=%08X; password=%08X", userName, password)); - if (userName && password) - { - // Set user name and password - DBVARIANT dbv; - - if(!db_get_ws(NULL,SKYPE_PROTONAME,"LoginUserName",&dbv)) - { - SendMessageW(userName, WM_SETTEXT, 0, (LPARAM)dbv.pwszVal); - db_free(&dbv); - } - - if(!db_get_ws(NULL,SKYPE_PROTONAME,"LoginPassword",&dbv)) - { - SendMessageW(password, WM_SETTEXT, 0, (LPARAM)dbv.pwszVal); - db_free(&dbv); - SendMessageW(password, WM_CHAR, 13, 0); - } - - - SendMessageW(hWnd, - WM_COMMAND, - 0x4a8, // sign-in button; WARNING: This ID can change during newer Skype versions - (LPARAM)findWindow(loginControl, _T("TTntButton.UnicodeClass"))); - } - return FALSE; - } - - } - return TRUE; -} - -DWORD WINAPI setUserNamePasswordThread(LPVOID lpDummy) -{ - DWORD dwPid = (DWORD)lpDummy; - HANDLE mutex = CreateMutex(NULL, TRUE, _T("setUserNamePasswordMutex")); - - // Check double entrance - if(GetLastError() == ERROR_ALREADY_EXISTS) - return 0; - - WaitForSingleObject(SkypeReady, 5000); - EnumWindows (EnumWindowsProc, dwPid); - - ReleaseMutex(mutex); - CloseHandle(mutex); - return 0; -} - -/** - * Purpose: Finds Skype window and sets user name and password. - * - * Note: This function relies on Skype window placement. - * It should work for Skype 3.x - */ -void setUserNamePassword(int dwPid) -{ - DWORD threadId; - CreateThread(NULL, 0, &setUserNamePasswordThread, (LPVOID)dwPid, 0, &threadId); - - // Give time to thread - Sleep(100); -} diff --git a/protocols/SkypeClassic/src/alogon.cpp b/protocols/SkypeClassic/src/alogon.cpp new file mode 100644 index 0000000000..8002d495fc --- /dev/null +++ b/protocols/SkypeClassic/src/alogon.cpp @@ -0,0 +1,129 @@ +#include "skype.h" +#include "debug.h" + +extern char g_szProtoName[]; +extern HANDLE SkypeReady; + +/** + * Purpose: Retrieves class name from window + * + * Note: This is some sort of hack to return static local variable, + * but it works :) + */ +static const TCHAR* getClassName(HWND wnd) +{ + static TCHAR className[256]; + + *className=0; + GetClassName(wnd, &className[0], sizeof(className)/sizeof(className[0])); + return className; +} + +/** + * Purpose: Finds a window + * + * Note: This function relies on Skype window placement. + * It should work for Skype 3.x + */ +static HWND findWindow(HWND parent, const TCHAR* childClassName) +{ + // Get child window + // This window is not combo box or edit box + HWND wnd = GetWindow(parent, GW_CHILD); + while(wnd != NULL && _tcscmp(getClassName(wnd), childClassName) != 0) + wnd = GetWindow(wnd, GW_HWNDNEXT); + + return wnd; +} + +static BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) +{ + DWORD dwPID; + const TCHAR *lpszClassName; + + + GetWindowThreadProcessId(hWnd,&dwPID); + if (lParam != 0 && dwPID != (DWORD)lParam) return TRUE; + lpszClassName = getClassName(hWnd); + if(_tcscmp(lpszClassName, _T("tSkMainForm.UnicodeClass")) == 0 || + _tcscmp(lpszClassName, _T("TLoginForm.UnicodeClass")) == 0) + { + HWND loginControl = GetWindow(hWnd, GW_CHILD); + + LOG(("setUserNamePasswordThread: Skype window found!")); + + // Sleep for some time, while Skype is loading + // It loads slowly :( + //Sleep(5000); + LOG (("TLoginControl = %S", getClassName(loginControl))); + + // Check for login control + if(_tcscmp(getClassName(loginControl), _T("TLoginControl")) == 0) + { + // Find user name window + HWND userName = findWindow(loginControl, _T("TNavigableTntComboBox.UnicodeClass")); + HWND password = findWindow(loginControl, _T("TNavigableTntEdit.UnicodeClass")); + + LOG (("userName=%08X; password=%08X", userName, password)); + if (userName && password) + { + // Set user name and password + DBVARIANT dbv; + + if(!db_get_ws(NULL,SKYPE_PROTONAME,"LoginUserName",&dbv)) + { + SendMessageW(userName, WM_SETTEXT, 0, (LPARAM)dbv.pwszVal); + db_free(&dbv); + } + + if(!db_get_ws(NULL,SKYPE_PROTONAME,"LoginPassword",&dbv)) + { + SendMessageW(password, WM_SETTEXT, 0, (LPARAM)dbv.pwszVal); + db_free(&dbv); + SendMessageW(password, WM_CHAR, 13, 0); + } + + + SendMessageW(hWnd, + WM_COMMAND, + 0x4a8, // sign-in button; WARNING: This ID can change during newer Skype versions + (LPARAM)findWindow(loginControl, _T("TTntButton.UnicodeClass"))); + } + return FALSE; + } + + } + return TRUE; +} + +DWORD WINAPI setUserNamePasswordThread(LPVOID lpDummy) +{ + DWORD dwPid = (DWORD)lpDummy; + HANDLE mutex = CreateMutex(NULL, TRUE, _T("setUserNamePasswordMutex")); + + // Check double entrance + if(GetLastError() == ERROR_ALREADY_EXISTS) + return 0; + + WaitForSingleObject(SkypeReady, 5000); + EnumWindows (EnumWindowsProc, dwPid); + + ReleaseMutex(mutex); + CloseHandle(mutex); + return 0; +} + +/** + * Purpose: Finds Skype window and sets user name and password. + * + * Note: This function relies on Skype window placement. + * It should work for Skype 3.x + */ +void setUserNamePassword(int dwPid) +{ + DWORD threadId; + CreateThread(NULL, 0, &setUserNamePasswordThread, (LPVOID)dwPid, 0, &threadId); + + // Give time to thread + Sleep(100); +} diff --git a/protocols/SkypeClassic/src/contacts.c b/protocols/SkypeClassic/src/contacts.c deleted file mode 100644 index cb7bfa36e6..0000000000 --- a/protocols/SkypeClassic/src/contacts.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - * Contactlist management functions - */ - -#include "skype.h" -#include "skypeapi.h" -#include "debug.h" -#include "pthread.h" -#include "gchat.h" -#include "voiceservice.h" - -#pragma warning (push) -#pragma warning (disable: 4100) // unreferenced formal parameter -#include -#pragma warning (pop) - -#pragma warning (disable: 4706) // assignment within conditional expression - -// Imported Globals -extern HINSTANCE hInst; -extern BOOL bSkypeOut, bIsImoproxy; -extern char protocol, g_szProtoName[]; - -// Handles -static HANDLE hMenuCallItem, hMenuCallHangup, hMenuSkypeOutCallItem, hMenuHoldCallItem, hMenuFileTransferItem, hMenuChatInitItem; - -// Check if alpha blending icons are supported -// Seems to be not neccessary -/* -BOOL SupportAlphaIcons(void) { -HANDLE hMod; -DLLVERSIONINFO tDVI={0}; -BOOL retval=FALSE; -FARPROC pDllGetVersion; - -if (!(hMod=LoadLibrary("comctl32.dll"))) return FALSE; -if (pDllGetVersion=GetProcAddress(hMod, "DllGetVersion")) { -tDVI.cbSize=sizeof(tDVI); -if (!pDllGetVersion ((DLLVERSIONINFO *)&tDVI)) { -if (GetDeviceCaps(GetDC(NULL), BITSPIXEL)*GetDeviceCaps(GetDC(NULL), PLANES)>=32 && -tDVI.dwMajorVersion>=6) -retval=TRUE; -} -} -FreeLibrary(hMod); -return retval; -} -*/ - -CLISTMENUITEM CallItem(void) { - CLISTMENUITEM mi = { 0 }; - - mi.cbSize = sizeof(mi); - mi.position = -2000005000; - mi.flags = CMIF_NOTOFFLINE | CMIF_TCHAR; - mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_CALL)); - mi.pszContactOwner = SKYPE_PROTONAME; - mi.ptszName = LPGENT("Call (Skype)"); - mi.pszService = SKYPE_CALL; - - return mi; -} - -CLISTMENUITEM SkypeOutCallItem(void) { - CLISTMENUITEM mi = { 0 }; - - mi.cbSize = sizeof(mi); - mi.position = -2000005000; - mi.flags = CMIF_HIDDEN | CMIF_TCHAR; - mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_CALLSKYPEOUT)); - mi.ptszName = LPGENT("Call using SkypeOut"); - mi.pszService = SKYPEOUT_CALL; - - return mi; -} - -CLISTMENUITEM HupItem(void) { - CLISTMENUITEM mi = { 0 }; - - mi.cbSize = sizeof(mi); - mi.position = -2000005000; - mi.flags = CMIF_NOTOFFLINE | CMIF_TCHAR; - mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_HANGUP)); - mi.pszContactOwner = SKYPE_PROTONAME; - mi.ptszName = LPGENT("Hang up call (Skype)"); - mi.pszService = SKYPE_CALLHANGUP; - - return mi; -} - -CLISTMENUITEM SkypeOutHupItem(void) { - CLISTMENUITEM mi = { 0 }; - - mi.cbSize = sizeof(mi); - mi.position = -2000005000; - mi.flags = CMIF_TCHAR; - mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_HANGUP)); - mi.ptszName = LPGENT("Hang up SkypeOut call"); - mi.pszService = SKYPEOUT_CALL; - return mi; -} - -CLISTMENUITEM HoldCallItem(void) { - CLISTMENUITEM mi = { 0 }; - - mi.cbSize = sizeof(mi); - mi.position = -2000005000; - mi.flags = CMIF_HIDDEN | CMIF_NOTOFFLINE | CMIF_TCHAR; - mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_HOLD)); - mi.ptszName = LPGENT("Hold call"); - mi.pszService = SKYPE_HOLDCALL; - return mi; -} - -CLISTMENUITEM ResumeCallItem(void) { - CLISTMENUITEM mi = { 0 }; - - mi.cbSize = sizeof(mi); - mi.position = -2000005000; - mi.flags = CMIF_HIDDEN | CMIF_NOTOFFLINE | CMIF_TCHAR; - mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_RESUME)); - mi.ptszName = LPGENT("Resume call"); - mi.pszService = SKYPE_HOLDCALL; - return mi; -} - -CLISTMENUITEM FileTransferItem(void) { - CLISTMENUITEM mi = { 0 }; - - // Stolen from file.c of Miranda core - mi.cbSize = sizeof(mi); - mi.position = -2000020000; - mi.flags = CMIF_HIDDEN | CMIF_NOTOFFLINE | CMIF_TCHAR; - mi.hIcon = LoadSkinnedIcon(SKINICON_EVENT_FILE); - mi.ptszName = LPGENT("&File"); - mi.pszContactOwner = SKYPE_PROTONAME; - mi.pszService = SKYPE_SENDFILE; - return mi; -} - -CLISTMENUITEM ChatInitItem(void) { - CLISTMENUITEM mi = { 0 }; - - mi.cbSize = sizeof(mi); - mi.position = -2000020000; - mi.flags = CMIF_HIDDEN | CMIF_NOTOFFLINE | CMIF_TCHAR; - mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_INVITE)); - mi.ptszName = LPGENT("&Open group chat"); - mi.pszContactOwner = SKYPE_PROTONAME; - mi.pszService = SKYPE_CHATNEW; - return mi; -} - -HANDLE add_contextmenu(MCONTACT hContact) { - CLISTMENUITEM mi; - - UNREFERENCED_PARAMETER(hContact); - - if (!HasVoiceService()) { - mi = CallItem(); - hMenuCallItem = Menu_AddContactMenuItem(&mi); - mi = HupItem(); - hMenuCallHangup = Menu_AddContactMenuItem(&mi); - } - - mi = SkypeOutCallItem(); - hMenuSkypeOutCallItem = Menu_AddContactMenuItem(&mi); - - if (!HasVoiceService()) { - mi = HoldCallItem(); - hMenuHoldCallItem = Menu_AddContactMenuItem(&mi); - } - - // We cannot use flag PF1_FILESEND for sending files, as Skype opens its own - // sendfile-Dialog. - mi = FileTransferItem(); - hMenuFileTransferItem = Menu_AddContactMenuItem(&mi); - - mi = ChatInitItem(); - hMenuChatInitItem = Menu_AddContactMenuItem(&mi); - - - ZeroMemory(&mi, sizeof(mi)); - mi.cbSize = sizeof(mi); - mi.position = -2000005000; - mi.flags = CMIF_TCHAR; - mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_IMPORT)); - mi.pszContactOwner = SKYPE_PROTONAME; - mi.ptszName = LPGENT("Import Skype history"); - mi.pszService = SKYPE_IMPORTHISTORY; - return Menu_AddContactMenuItem(&mi); -} - -HANDLE add_mainmenu(void) { - CLISTMENUITEM mi = { 0 }; - - mi.cbSize = sizeof(mi); - mi.position = -2000005000; - mi.flags = CMIF_TCHAR; - mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ADD)); - mi.pszContactOwner = SKYPE_PROTONAME; - mi.ptszName = LPGENT("Add Skype contact"); - mi.pszService = SKYPE_ADDUSER; - return Menu_AddMainMenuItem(&mi); - -} - -int __cdecl PrebuildContactMenu(WPARAM wParam, LPARAM lParam) { - DBVARIANT dbv; - CLISTMENUITEM mi; - char *szProto; - BOOL callAvailable = FALSE; - BOOL hangupAvailable = FALSE; - - UNREFERENCED_PARAMETER(lParam); - - if (!(szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0))) return 0; - - if (!HasVoiceService()) - { - // Clear hold-Item in case it exists - mi = HoldCallItem(); - mi.flags |= CMIM_ALL; - CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuHoldCallItem, (LPARAM)&mi); - } - - if (!strcmp(szProto, SKYPE_PROTONAME)) { - if (!HasVoiceService()) { - if (!db_get((MCONTACT)wParam, SKYPE_PROTONAME, "CallId", &dbv)) { - if (db_get_b((MCONTACT)wParam, SKYPE_PROTONAME, "OnHold", 0)) - mi = ResumeCallItem(); else mi = HoldCallItem(); - mi.flags = CMIM_ALL; - CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuHoldCallItem, (LPARAM)&mi); - - callAvailable = FALSE; - hangupAvailable = TRUE; - - db_free(&dbv); - } - else { callAvailable = TRUE; hangupAvailable = FALSE; } - - if (db_get_b((MCONTACT)wParam, SKYPE_PROTONAME, "ChatRoom", 0) != 0) { - callAvailable = FALSE; - hangupAvailable = FALSE; - } - - mi = CallItem(); - mi.flags |= CMIM_ALL | (!callAvailable ? CMIF_HIDDEN : 0); - CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuCallItem, (LPARAM)&mi); - - mi = HupItem(); - mi.flags |= CMIM_ALL | (!hangupAvailable ? CMIF_HIDDEN : 0); - CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuCallHangup, (LPARAM)&mi); - } - - // Clear SkypeOut menu in case it exists - mi = SkypeOutCallItem(); - mi.flags |= CMIM_ALL; - CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuSkypeOutCallItem, (LPARAM)&mi); - - // File sending and groupchat-creation works starting with protocol version 5 - if (protocol >= 5) { - mi = FileTransferItem(); - if (db_get_b((MCONTACT)wParam, SKYPE_PROTONAME, "ChatRoom", 0) == 0) - mi.flags ^= CMIF_HIDDEN; - mi.flags |= CMIM_FLAGS; - CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuFileTransferItem, (LPARAM)&mi); - } - - if (protocol >= 5 || bIsImoproxy) { - mi = ChatInitItem(); - if (db_get_b(NULL, SKYPE_PROTONAME, "UseGroupchat", 0) && - db_get_b((MCONTACT)wParam, SKYPE_PROTONAME, "ChatRoom", 0) == 0) - mi.flags ^= CMIF_HIDDEN; - mi.flags |= CMIM_FLAGS; - CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuChatInitItem, (LPARAM)&mi); - } - - } - else if (bSkypeOut) { - if (!db_get((MCONTACT)wParam, SKYPE_PROTONAME, "CallId", &dbv)) { - mi = SkypeOutHupItem(); - db_free(&dbv); - } - else { - mi = SkypeOutCallItem(); - if (!db_get((MCONTACT)wParam, "UserInfo", "MyPhone0", &dbv)) { - db_free(&dbv); - mi.flags = 0; - } - } - mi.flags |= CMIM_ALL; - CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuSkypeOutCallItem, (LPARAM)&mi); - } - - return 0; -} - -/* -int ClistDblClick(WPARAM wParam, LPARAM lParam) { -char *szProto; - -szProto = (char*)CallService( MS_PROTO_GETCONTACTBASEPROTO, wParam, 0 ); -if (szProto!=NULL && !strcmp(szProto, SKYPE_PROTONAME) && -db_get_w((HANDLE)wParam, SKYPE_PROTONAME, "Status", ID_STATUS_OFFLINE)==ID_STATUS_ONTHEPHONE) { -SkypeCall(wParam, 0); -} - -return 0; -} -*/ - -MCONTACT find_contact(char *name) -{ - int tCompareResult; - MCONTACT hContact; - DBVARIANT dbv; - - // already on list? - for (hContact = db_find_first(SKYPE_PROTONAME); hContact != NULL; hContact = db_find_next(hContact)) - { - char *szProto = (char*)GetContactProto(hContact); - if (szProto != NULL && !strcmp(szProto, SKYPE_PROTONAME) && db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0) == 0) - { - if (db_get_s(hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) continue; - tCompareResult = strcmp(dbv.pszVal, name); - db_free(&dbv); - if (tCompareResult) continue; - return hContact; // already there, return handle - } - } - return NULL; -} - -MCONTACT find_contactT(TCHAR *name) -{ - int tCompareResult; - MCONTACT hContact; - DBVARIANT dbv; - - // already on list? - for (hContact = db_find_first(SKYPE_PROTONAME); hContact != NULL; hContact = db_find_next(hContact)) - { - char *szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); - if (szProto != NULL && !strcmp(szProto, SKYPE_PROTONAME) && db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0) == 0) - { - if (db_get_ts(hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) continue; - tCompareResult = _tcscmp(dbv.ptszVal, name); - db_free(&dbv); - if (tCompareResult) continue; - return hContact; // already there, return handle - } - } - return NULL; -} - - -MCONTACT add_contact(char *name, DWORD flags) -{ - MCONTACT hContact; - - // already on list? - if (hContact = find_contact(name)) { - if (!(flags & PALF_TEMPORARY) && db_get_b(hContact, "CList", "NotOnList", 1)) { - db_unset(hContact, "CList", "NotOnList"); - db_unset(hContact, "CList", "Hidden"); - } - LOG(("add_contact: Found %s", name)); - return hContact; // already there, return handle - } - // no, so add - - LOG(("add_contact: Adding %s", name)); - hContact = (MCONTACT)CallServiceSync(MS_DB_CONTACT_ADD, 0, 0); - if (hContact) { - if (CallServiceSync(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)SKYPE_PROTONAME) != 0) { - LOG(("add_contact: Ouch! MS_PROTO_ADDTOCONTACT failed for some reason")); - CallServiceSync(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0); - return NULL; - } - if (name[0]) db_set_s(hContact, SKYPE_PROTONAME, SKYPE_NAME, name); - - if (flags & PALF_TEMPORARY) { - db_set_b(hContact, "CList", "NotOnList", 1); - db_set_b(hContact, "CList", "Hidden", 1); - } - if (name[0]) { - SkypeSend("GET USER %s DISPLAYNAME", name); - } - else { LOG(("add_contact: Info: The contact added has no name.")); } - } - else { LOG(("add_contact: Ouch! MS_DB_CONTACT_ADD failed for some reason")); } - LOG(("add_contact succeeded")); - return hContact; -} - -void logoff_contacts(BOOL bCleanup) { - MCONTACT hContact; - char *szProto; - DBVARIANT dbv = { 0 }; - - LOG(("logoff_contacts: Logging off contacts.")); - for (hContact = db_find_first(SKYPE_PROTONAME); hContact != NULL; hContact = db_find_next(hContact)) { - szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); - if (szProto != NULL && !strcmp(szProto, SKYPE_PROTONAME)) - { - if (db_get_w(hContact, SKYPE_PROTONAME, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE) - db_set_w(hContact, SKYPE_PROTONAME, "Status", ID_STATUS_OFFLINE); - - db_unset(hContact, SKYPE_PROTONAME, "CallId"); - if (db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0) == 1) - { - if (db_get_ts(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv)) continue; - RemChat(dbv.ptszVal); - db_free(&dbv); - } - if (db_get_s(hContact, SKYPE_PROTONAME, "Typing_Stream", &dbv) == 0) - { - if (bCleanup) SkypeSend("ALTER APPLICATION libpurple_typing DISCONNECT %s", dbv.pszVal); - db_free(&dbv); - db_unset(hContact, SKYPE_PROTONAME, "Typing_Stream"); - } - - } - } - if (bCleanup && (protocol >= 5 || bIsImoproxy)) SkypeSend("DELETE APPLICATION libpurple_typing"); -} diff --git a/protocols/SkypeClassic/src/contacts.cpp b/protocols/SkypeClassic/src/contacts.cpp new file mode 100644 index 0000000000..2bb2bb0898 --- /dev/null +++ b/protocols/SkypeClassic/src/contacts.cpp @@ -0,0 +1,427 @@ +/* + * Contactlist management functions + */ + +#include "skype.h" +#include "skypeapi.h" +#include "debug.h" +#include "pthread.h" +#include "gchat.h" +#include "voiceservice.h" + +#pragma warning (push) +#pragma warning (disable: 4100) // unreferenced formal parameter +#include +#pragma warning (pop) + +#pragma warning (disable: 4706) // assignment within conditional expression + +// Imported Globals +extern HINSTANCE hInst; +extern BOOL bSkypeOut, bIsImoproxy; +extern char protocol, g_szProtoName[]; + +// Handles +static HANDLE hMenuCallItem, hMenuCallHangup, hMenuSkypeOutCallItem, hMenuHoldCallItem, hMenuFileTransferItem, hMenuChatInitItem; + +// Check if alpha blending icons are supported +// Seems to be not neccessary +/* +BOOL SupportAlphaIcons(void) { +HANDLE hMod; +DLLVERSIONINFO tDVI={0}; +BOOL retval=FALSE; +FARPROC pDllGetVersion; + +if (!(hMod=LoadLibrary("comctl32.dll"))) return FALSE; +if (pDllGetVersion=GetProcAddress(hMod, "DllGetVersion")) { +tDVI.cbSize=sizeof(tDVI); +if (!pDllGetVersion ((DLLVERSIONINFO *)&tDVI)) { +if (GetDeviceCaps(GetDC(NULL), BITSPIXEL)*GetDeviceCaps(GetDC(NULL), PLANES)>=32 && +tDVI.dwMajorVersion>=6) +retval=TRUE; +} +} +FreeLibrary(hMod); +return retval; +} +*/ + +CLISTMENUITEM CallItem(void) { + CLISTMENUITEM mi = { 0 }; + + mi.cbSize = sizeof(mi); + mi.position = -2000005000; + mi.flags = CMIF_NOTOFFLINE | CMIF_TCHAR; + mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_CALL)); + mi.pszContactOwner = SKYPE_PROTONAME; + mi.ptszName = LPGENT("Call (Skype)"); + mi.pszService = SKYPE_CALL; + + return mi; +} + +CLISTMENUITEM SkypeOutCallItem(void) { + CLISTMENUITEM mi = { 0 }; + + mi.cbSize = sizeof(mi); + mi.position = -2000005000; + mi.flags = CMIF_HIDDEN | CMIF_TCHAR; + mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_CALLSKYPEOUT)); + mi.ptszName = LPGENT("Call using SkypeOut"); + mi.pszService = SKYPEOUT_CALL; + + return mi; +} + +CLISTMENUITEM HupItem(void) { + CLISTMENUITEM mi = { 0 }; + + mi.cbSize = sizeof(mi); + mi.position = -2000005000; + mi.flags = CMIF_NOTOFFLINE | CMIF_TCHAR; + mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_HANGUP)); + mi.pszContactOwner = SKYPE_PROTONAME; + mi.ptszName = LPGENT("Hang up call (Skype)"); + mi.pszService = SKYPE_CALLHANGUP; + + return mi; +} + +CLISTMENUITEM SkypeOutHupItem(void) { + CLISTMENUITEM mi = { 0 }; + + mi.cbSize = sizeof(mi); + mi.position = -2000005000; + mi.flags = CMIF_TCHAR; + mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_HANGUP)); + mi.ptszName = LPGENT("Hang up SkypeOut call"); + mi.pszService = SKYPEOUT_CALL; + return mi; +} + +CLISTMENUITEM HoldCallItem(void) { + CLISTMENUITEM mi = { 0 }; + + mi.cbSize = sizeof(mi); + mi.position = -2000005000; + mi.flags = CMIF_HIDDEN | CMIF_NOTOFFLINE | CMIF_TCHAR; + mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_HOLD)); + mi.ptszName = LPGENT("Hold call"); + mi.pszService = SKYPE_HOLDCALL; + return mi; +} + +CLISTMENUITEM ResumeCallItem(void) { + CLISTMENUITEM mi = { 0 }; + + mi.cbSize = sizeof(mi); + mi.position = -2000005000; + mi.flags = CMIF_HIDDEN | CMIF_NOTOFFLINE | CMIF_TCHAR; + mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_RESUME)); + mi.ptszName = LPGENT("Resume call"); + mi.pszService = SKYPE_HOLDCALL; + return mi; +} + +CLISTMENUITEM FileTransferItem(void) { + CLISTMENUITEM mi = { 0 }; + + // Stolen from file.c of Miranda core + mi.cbSize = sizeof(mi); + mi.position = -2000020000; + mi.flags = CMIF_HIDDEN | CMIF_NOTOFFLINE | CMIF_TCHAR; + mi.hIcon = LoadSkinnedIcon(SKINICON_EVENT_FILE); + mi.ptszName = LPGENT("&File"); + mi.pszContactOwner = SKYPE_PROTONAME; + mi.pszService = SKYPE_SENDFILE; + return mi; +} + +CLISTMENUITEM ChatInitItem(void) { + CLISTMENUITEM mi = { 0 }; + + mi.cbSize = sizeof(mi); + mi.position = -2000020000; + mi.flags = CMIF_HIDDEN | CMIF_NOTOFFLINE | CMIF_TCHAR; + mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_INVITE)); + mi.ptszName = LPGENT("&Open group chat"); + mi.pszContactOwner = SKYPE_PROTONAME; + mi.pszService = SKYPE_CHATNEW; + return mi; +} + +HANDLE add_contextmenu(MCONTACT hContact) { + CLISTMENUITEM mi; + + UNREFERENCED_PARAMETER(hContact); + + if (!HasVoiceService()) { + mi = CallItem(); + hMenuCallItem = Menu_AddContactMenuItem(&mi); + mi = HupItem(); + hMenuCallHangup = Menu_AddContactMenuItem(&mi); + } + + mi = SkypeOutCallItem(); + hMenuSkypeOutCallItem = Menu_AddContactMenuItem(&mi); + + if (!HasVoiceService()) { + mi = HoldCallItem(); + hMenuHoldCallItem = Menu_AddContactMenuItem(&mi); + } + + // We cannot use flag PF1_FILESEND for sending files, as Skype opens its own + // sendfile-Dialog. + mi = FileTransferItem(); + hMenuFileTransferItem = Menu_AddContactMenuItem(&mi); + + mi = ChatInitItem(); + hMenuChatInitItem = Menu_AddContactMenuItem(&mi); + + + ZeroMemory(&mi, sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.position = -2000005000; + mi.flags = CMIF_TCHAR; + mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_IMPORT)); + mi.pszContactOwner = SKYPE_PROTONAME; + mi.ptszName = LPGENT("Import Skype history"); + mi.pszService = SKYPE_IMPORTHISTORY; + return Menu_AddContactMenuItem(&mi); +} + +HANDLE add_mainmenu(void) { + CLISTMENUITEM mi = { 0 }; + + mi.cbSize = sizeof(mi); + mi.position = -2000005000; + mi.flags = CMIF_TCHAR; + mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ADD)); + mi.pszContactOwner = SKYPE_PROTONAME; + mi.ptszName = LPGENT("Add Skype contact"); + mi.pszService = SKYPE_ADDUSER; + return Menu_AddMainMenuItem(&mi); + +} + +int __cdecl PrebuildContactMenu(WPARAM wParam, LPARAM lParam) { + DBVARIANT dbv; + CLISTMENUITEM mi; + char *szProto; + BOOL callAvailable = FALSE; + BOOL hangupAvailable = FALSE; + + UNREFERENCED_PARAMETER(lParam); + + if (!(szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0))) return 0; + + if (!HasVoiceService()) + { + // Clear hold-Item in case it exists + mi = HoldCallItem(); + mi.flags |= CMIM_ALL; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuHoldCallItem, (LPARAM)&mi); + } + + if (!strcmp(szProto, SKYPE_PROTONAME)) { + if (!HasVoiceService()) { + if (!db_get((MCONTACT)wParam, SKYPE_PROTONAME, "CallId", &dbv)) { + if (db_get_b((MCONTACT)wParam, SKYPE_PROTONAME, "OnHold", 0)) + mi = ResumeCallItem(); else mi = HoldCallItem(); + mi.flags = CMIM_ALL; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuHoldCallItem, (LPARAM)&mi); + + callAvailable = FALSE; + hangupAvailable = TRUE; + + db_free(&dbv); + } + else { callAvailable = TRUE; hangupAvailable = FALSE; } + + if (db_get_b((MCONTACT)wParam, SKYPE_PROTONAME, "ChatRoom", 0) != 0) { + callAvailable = FALSE; + hangupAvailable = FALSE; + } + + mi = CallItem(); + mi.flags |= CMIM_ALL | (!callAvailable ? CMIF_HIDDEN : 0); + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuCallItem, (LPARAM)&mi); + + mi = HupItem(); + mi.flags |= CMIM_ALL | (!hangupAvailable ? CMIF_HIDDEN : 0); + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuCallHangup, (LPARAM)&mi); + } + + // Clear SkypeOut menu in case it exists + mi = SkypeOutCallItem(); + mi.flags |= CMIM_ALL; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuSkypeOutCallItem, (LPARAM)&mi); + + // File sending and groupchat-creation works starting with protocol version 5 + if (protocol >= 5) { + mi = FileTransferItem(); + if (db_get_b((MCONTACT)wParam, SKYPE_PROTONAME, "ChatRoom", 0) == 0) + mi.flags ^= CMIF_HIDDEN; + mi.flags |= CMIM_FLAGS; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuFileTransferItem, (LPARAM)&mi); + } + + if (protocol >= 5 || bIsImoproxy) { + mi = ChatInitItem(); + if (db_get_b(NULL, SKYPE_PROTONAME, "UseGroupchat", 0) && + db_get_b((MCONTACT)wParam, SKYPE_PROTONAME, "ChatRoom", 0) == 0) + mi.flags ^= CMIF_HIDDEN; + mi.flags |= CMIM_FLAGS; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuChatInitItem, (LPARAM)&mi); + } + + } + else if (bSkypeOut) { + if (!db_get((MCONTACT)wParam, SKYPE_PROTONAME, "CallId", &dbv)) { + mi = SkypeOutHupItem(); + db_free(&dbv); + } + else { + mi = SkypeOutCallItem(); + if (!db_get((MCONTACT)wParam, "UserInfo", "MyPhone0", &dbv)) { + db_free(&dbv); + mi.flags = 0; + } + } + mi.flags |= CMIM_ALL; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuSkypeOutCallItem, (LPARAM)&mi); + } + + return 0; +} + +/* +int ClistDblClick(WPARAM wParam, LPARAM lParam) { +char *szProto; + +szProto = (char*)CallService( MS_PROTO_GETCONTACTBASEPROTO, wParam, 0 ); +if (szProto!=NULL && !strcmp(szProto, SKYPE_PROTONAME) && +db_get_w((HANDLE)wParam, SKYPE_PROTONAME, "Status", ID_STATUS_OFFLINE)==ID_STATUS_ONTHEPHONE) { +SkypeCall(wParam, 0); +} + +return 0; +} +*/ + +MCONTACT find_contact(char *name) +{ + int tCompareResult; + MCONTACT hContact; + DBVARIANT dbv; + + // already on list? + for (hContact = db_find_first(); hContact != NULL; hContact = db_find_next(hContact)) + { + char *szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (szProto != NULL && !strcmp(szProto, SKYPE_PROTONAME) && db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0) == 0) + { + if (db_get_s(hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) continue; + tCompareResult = strcmp(dbv.pszVal, name); + db_free(&dbv); + if (tCompareResult) continue; + return hContact; // already there, return handle + } + } + return NULL; +} + +MCONTACT find_contactT(TCHAR *name) +{ + int tCompareResult; + MCONTACT hContact; + DBVARIANT dbv; + + // already on list? + for (hContact = db_find_first(); hContact != NULL; hContact = db_find_next(hContact)) + { + char *szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (szProto != NULL && !strcmp(szProto, SKYPE_PROTONAME) && db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0) == 0) + { + if (db_get_ts(hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) continue; + tCompareResult = _tcscmp(dbv.ptszVal, name); + db_free(&dbv); + if (tCompareResult) continue; + return hContact; // already there, return handle + } + } + return NULL; +} + + +MCONTACT add_contact(char *name, DWORD flags) +{ + MCONTACT hContact; + + // already on list? + if (hContact = find_contact(name)) { + if (!(flags & PALF_TEMPORARY) && db_get_b(hContact, "CList", "NotOnList", 1)) { + db_unset(hContact, "CList", "NotOnList"); + db_unset(hContact, "CList", "Hidden"); + } + LOG(("add_contact: Found %s", name)); + return hContact; // already there, return handle + } + // no, so add + + LOG(("add_contact: Adding %s", name)); + hContact = (MCONTACT)CallServiceSync(MS_DB_CONTACT_ADD, 0, 0); + if (hContact) { + if (CallServiceSync(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)SKYPE_PROTONAME) != 0) { + LOG(("add_contact: Ouch! MS_PROTO_ADDTOCONTACT failed for some reason")); + CallServiceSync(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0); + return NULL; + } + if (name[0]) db_set_s(hContact, SKYPE_PROTONAME, SKYPE_NAME, name); + + if (flags & PALF_TEMPORARY) { + db_set_b(hContact, "CList", "NotOnList", 1); + db_set_b(hContact, "CList", "Hidden", 1); + } + if (name[0]) { + SkypeSend("GET USER %s DISPLAYNAME", name); + } + else { LOG(("add_contact: Info: The contact added has no name.")); } + } + else { LOG(("add_contact: Ouch! MS_DB_CONTACT_ADD failed for some reason")); } + LOG(("add_contact succeeded")); + return hContact; +} + +void logoff_contacts(BOOL bCleanup) { + MCONTACT hContact; + char *szProto; + DBVARIANT dbv = { 0 }; + + LOG(("logoff_contacts: Logging off contacts.")); + for (hContact = db_find_first(); hContact != NULL; hContact = db_find_next(hContact)) { + szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (szProto != NULL && !strcmp(szProto, SKYPE_PROTONAME)) + { + if (db_get_w(hContact, SKYPE_PROTONAME, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE) + db_set_w(hContact, SKYPE_PROTONAME, "Status", ID_STATUS_OFFLINE); + + db_unset(hContact, SKYPE_PROTONAME, "CallId"); + if (db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0) == 1) + { + if (db_get_ts(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv)) continue; + RemChat(dbv.ptszVal); + db_free(&dbv); + } + if (db_get_s(hContact, SKYPE_PROTONAME, "Typing_Stream", &dbv) == 0) + { + if (bCleanup) SkypeSend("ALTER APPLICATION libpurple_typing DISCONNECT %s", dbv.pszVal); + db_free(&dbv); + db_unset(hContact, SKYPE_PROTONAME, "Typing_Stream"); + } + + } + } + if (bCleanup && (protocol >= 5 || bIsImoproxy)) SkypeSend("DELETE APPLICATION libpurple_typing"); +} diff --git a/protocols/SkypeClassic/src/debug.c b/protocols/SkypeClassic/src/debug.c deleted file mode 100644 index beb19c6db6..0000000000 --- a/protocols/SkypeClassic/src/debug.c +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef _DEBUG -#pragma warning (disable: 4206) // nonstandard extension used : translation unit is empty -#else -#include "debug.h" - -#define WIN32_LEAN_AND_MEAN -//#include -#include -//#include -#include "skype.h" -#include -#include - -#define INITBUF 1024 /* Initial size of buffer */ - -#pragma warning (disable: 4706) // assignment within conditional expression - -extern char g_szProtoName[]; - -static CRITICAL_SECTION m_WriteFileMutex; -static FILE *m_fpLogFile = NULL; -static char *m_szLogBuf = NULL; -static DWORD m_iBufSize = 0; - -void init_debug(void) { - char *p; - char logfile[MAX_PATH]; - - ZeroMemory(logfile, sizeof(logfile)); - p=logfile+GetModuleFileNameA(NULL, logfile, sizeof(logfile)); - if (!(p=strrchr (logfile, '\\'))) p=logfile; else p++; - sprintf (p, "%s_log.txt", SKYPE_PROTONAME); - m_szLogBuf = (char*)calloc (1, (m_iBufSize = INITBUF)); - m_fpLogFile = fopen(logfile, "a"); - InitializeCriticalSection(&m_WriteFileMutex); -} - -void end_debug (void) { - if (m_szLogBuf) free (m_szLogBuf); - if (m_fpLogFile) fclose (m_fpLogFile); - DeleteCriticalSection(&m_WriteFileMutex); -} - -void do_log(const char *pszFormat, ...) { - char *ct, *pNewBuf; - va_list ap; - time_t lt; - int iLen; - - if (!m_szLogBuf || !m_fpLogFile) return; - EnterCriticalSection(&m_WriteFileMutex); - time(<); - ct=ctime(<); - ct[strlen(ct)-1]=0; - do - { - va_start(ap, pszFormat); - iLen = _vsnprintf(m_szLogBuf, m_iBufSize, pszFormat, ap); - va_end(ap); - if (iLen == -1) - { - if (!(pNewBuf = (char*)realloc (m_szLogBuf, m_iBufSize*2))) - { - iLen = strlen (m_szLogBuf); - break; - } - m_szLogBuf = pNewBuf; - m_iBufSize*=2; - } - } while (iLen == -1); - fprintf (m_fpLogFile, sizeof(time_t) == sizeof(int) ? "%s (%ld) [%08X] %s\n" : "%s (%lld) [%08X] %s\n", ct, lt, GetCurrentThreadId(), m_szLogBuf); - fflush (m_fpLogFile); - LeaveCriticalSection(&m_WriteFileMutex); -} -#endif \ No newline at end of file diff --git a/protocols/SkypeClassic/src/debug.cpp b/protocols/SkypeClassic/src/debug.cpp new file mode 100644 index 0000000000..beb19c6db6 --- /dev/null +++ b/protocols/SkypeClassic/src/debug.cpp @@ -0,0 +1,75 @@ +#ifndef _DEBUG +#pragma warning (disable: 4206) // nonstandard extension used : translation unit is empty +#else +#include "debug.h" + +#define WIN32_LEAN_AND_MEAN +//#include +#include +//#include +#include "skype.h" +#include +#include + +#define INITBUF 1024 /* Initial size of buffer */ + +#pragma warning (disable: 4706) // assignment within conditional expression + +extern char g_szProtoName[]; + +static CRITICAL_SECTION m_WriteFileMutex; +static FILE *m_fpLogFile = NULL; +static char *m_szLogBuf = NULL; +static DWORD m_iBufSize = 0; + +void init_debug(void) { + char *p; + char logfile[MAX_PATH]; + + ZeroMemory(logfile, sizeof(logfile)); + p=logfile+GetModuleFileNameA(NULL, logfile, sizeof(logfile)); + if (!(p=strrchr (logfile, '\\'))) p=logfile; else p++; + sprintf (p, "%s_log.txt", SKYPE_PROTONAME); + m_szLogBuf = (char*)calloc (1, (m_iBufSize = INITBUF)); + m_fpLogFile = fopen(logfile, "a"); + InitializeCriticalSection(&m_WriteFileMutex); +} + +void end_debug (void) { + if (m_szLogBuf) free (m_szLogBuf); + if (m_fpLogFile) fclose (m_fpLogFile); + DeleteCriticalSection(&m_WriteFileMutex); +} + +void do_log(const char *pszFormat, ...) { + char *ct, *pNewBuf; + va_list ap; + time_t lt; + int iLen; + + if (!m_szLogBuf || !m_fpLogFile) return; + EnterCriticalSection(&m_WriteFileMutex); + time(<); + ct=ctime(<); + ct[strlen(ct)-1]=0; + do + { + va_start(ap, pszFormat); + iLen = _vsnprintf(m_szLogBuf, m_iBufSize, pszFormat, ap); + va_end(ap); + if (iLen == -1) + { + if (!(pNewBuf = (char*)realloc (m_szLogBuf, m_iBufSize*2))) + { + iLen = strlen (m_szLogBuf); + break; + } + m_szLogBuf = pNewBuf; + m_iBufSize*=2; + } + } while (iLen == -1); + fprintf (m_fpLogFile, sizeof(time_t) == sizeof(int) ? "%s (%ld) [%08X] %s\n" : "%s (%lld) [%08X] %s\n", ct, lt, GetCurrentThreadId(), m_szLogBuf); + fflush (m_fpLogFile); + LeaveCriticalSection(&m_WriteFileMutex); +} +#endif \ No newline at end of file diff --git a/protocols/SkypeClassic/src/gchat.c b/protocols/SkypeClassic/src/gchat.c deleted file mode 100644 index 933e75755a..0000000000 --- a/protocols/SkypeClassic/src/gchat.c +++ /dev/null @@ -1,920 +0,0 @@ -#include "skype.h" -#include "skypeapi.h" -#include "gchat.h" -#include "contacts.h" -#include "debug.h" -#include "utf8.h" -#include "pthread.h" - -#pragma warning (push) -#pragma warning (disable: 4100) // unreferenced formal parameter -#include -#include -#include -#include -#pragma warning (pop) - -#ifndef DWLP_USER -#define DWLP_USER DWL_USER -#endif - -#ifdef _UNICODE -#define STR "%S" -#else -#define STR "%s" -#endif - -/* VC6 PSDK compatibility */ -#if !defined(_WIN64) && !defined(SetWindowLongPtr) -#define SetWindowLongPtr SetWindowLong -#define GetWindowLongPtr GetWindowLong -#endif - -#pragma warning (disable: 4706) // assignment within conditional expression - -extern HANDLE hInitChat; -extern HINSTANCE hInst; -extern char protocol, g_szProtoName[]; -extern DWORD mirandaVersion; - -static gchat_contacts *chats=NULL; -static int chatcount=0; -static CRITICAL_SECTION m_GCMutex; - -// TODO: Disable groupchat for Protocol verisons <5 - -/****************************************************************************/ -/* Chat management helper functions */ -/****************************************************************************/ - -/* Get the gchat_contacts entry for the chat with the id szChatId - If the chat doesn't already exist in the list, it is added. - - Parameters: szChatId - String with the chat ID of the chat to be found - Returns: Pointer to the gchat_contacts entry for the given id. - NULL on failure (not enough memory) -*/ -gchat_contacts *GetChat(const TCHAR *szChatId) { - int i; - - for (i=0;i=0 = Number of found item - */ -static int ExistsChatContact(gchat_contacts *gc, const TCHAR *who) { - int i; - - for (i=0;imJoinedCount;i++) - if (_tcscmp(gc->mJoinedContacts[i].who, who)==0) return i; - return -1; -} - -gchat_contact *GetChatContact(gchat_contacts *gc, const TCHAR *who) { - int i = ExistsChatContact (gc, who); - - if (i==-1) return NULL; - return &gc->mJoinedContacts[i]; -} - -/* Adds contact with the name who to the groupchat given in gc - - Parameters: gc - - Returns: -1 = Contact not found - -2 = On failure - >=0 = Number of added item - */ -static int AddChatContact(gchat_contacts *gc, char *who, TCHAR *pszRole) -{ - int i = -2; - MCONTACT hContact; - GCDEST gcd = {0}; - GCEVENT gce = {0}; - CONTACTINFO ci = {0}; - TCHAR *twho; - - LOG (("AddChatContact %s", who)); - if (!(twho = make_nonutf_tchar_string((const unsigned char*)who))) - return -2; - if ((i=ExistsChatContact(gc, twho))>=0) return i; - hContact=find_contact(who); - - gcd.pszModule = SKYPE_PROTONAME; - gcd.ptszID = gc->szChatName; - gcd.iType = GC_EVENT_JOIN; - - gce.cbSize = sizeof(GCEVENT); - gce.pDest = &gcd; - gce.ptszStatus = pszRole?pszRole:_T("USER"); - gce.time = (DWORD)time(NULL); - gce.dwFlags = GCEF_ADDTOLOG | GC_TCHAR; - - ci.cbSize = sizeof(ci); - ci.szProto = SKYPE_PROTONAME; - ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; - ci.hContact = hContact; - - if (hContact && !CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci)) gce.ptszNick=ci.pszVal; - else gce.ptszNick=twho; - - gce.ptszUID=twho; - if (!CallService(MS_GC_EVENT, 0, (LPARAM)&gce)) { - if ((gc->mJoinedContacts=(gchat_contact*)realloc(gc->mJoinedContacts, (gc->mJoinedCount+1)*sizeof(gchat_contact)))) - { - gc->mJoinedContacts[i=gc->mJoinedCount].hContact=hContact; - _tcscpy (gc->mJoinedContacts[i].szRole, gce.ptszStatus); - _tcscpy (gc->mJoinedContacts[i].who, twho); - gc->mJoinedCount++; - } - } - if (ci.pszVal) mir_free (ci.pszVal); - free_nonutf_tchar_string (twho); - return i; -} - -void RemChatContact(gchat_contacts *gc, const TCHAR *who) { - int i; - - if (!gc) return; - for (i=0;imJoinedCount;i++) - if (_tcscmp(gc->mJoinedContacts[i].who, who)==0) { - if (i<--gc->mJoinedCount) - memmove(&gc->mJoinedContacts[i], &gc->mJoinedContacts[i+1], (gc->mJoinedCount-i)*sizeof(gchat_contact)); - if (gc->mJoinedCount) gc->mJoinedContacts = (gchat_contact*)realloc(gc->mJoinedContacts, sizeof(gchat_contact)*gc->mJoinedCount); - else {free (gc->mJoinedContacts); gc->mJoinedContacts = NULL; } - return; - } -} - -MCONTACT find_chat(LPCTSTR chatname) { - char *szProto; - int tCompareResult; - MCONTACT hContact; - DBVARIANT dbv; - - for (hContact=db_find_first();hContact != NULL;hContact=db_find_next(hContact)) { - szProto = (char*)CallService( MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0 ); - if (szProto!=NULL && !strcmp(szProto, SKYPE_PROTONAME) && - db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0)==1) - { - if (db_get_ts(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv)) continue; - tCompareResult = _tcscmp(dbv.ptszVal, chatname); - db_free(&dbv); - if (tCompareResult) continue; - return hContact; // already there, return handle - } - } - return NULL; -} - -#ifdef _UNICODE -MCONTACT find_chatA(char *chatname) { - char *szProto; - int tCompareResult; - MCONTACT hContact; - DBVARIANT dbv; - - for (hContact=db_find_first();hContact != NULL;hContact=db_find_next(hContact)) { - szProto = (char*)CallService( MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0 ); - if (szProto!=NULL && !strcmp(szProto, SKYPE_PROTONAME) && - db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0)==1) - { - if (db_get_s(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv)) continue; - tCompareResult = strcmp(dbv.pszVal, chatname); - db_free(&dbv); - if (tCompareResult) continue; - return hContact; // already there, return handle - } - } - return NULL; -} -#endif - - - -int __cdecl AddMembers(char *szSkypeMsg) { - BYTE *contactmask=NULL; - DBVARIANT dbv2; - CONTACTINFO ci={0}; - char *ptr, *who, *nextoken; - TCHAR *szChatId; - int i, iRet = 0; - gchat_contacts *gc; - - LOG(("AddMembers STARTED")); - if (!(ptr=strstr(szSkypeMsg, " MEMBERS"))) return -1; - EnterCriticalSection(&m_GCMutex); - ptr[0]=0; - szChatId = make_nonutf_tchar_string((const unsigned char*)szSkypeMsg+5); - ptr+=9; - if (find_chat(szChatId) && (gc=GetChat(szChatId)) && - !db_get_s(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv2)) - { - char *pszMemObjs, *token; - - if (protocol>=7 && (pszMemObjs = SkypeGet ("CHAT", szSkypeMsg+5, "MEMBEROBJECTS"))) { - // Add new contacts (protocol 7+ with memberobjects, supports roles) - for (token=strtok_r(pszMemObjs, ", ", &nextoken); token; token=strtok_r(NULL, ", ", &nextoken)) { - if (!(who = SkypeGet ("CHATMEMBER", token, "IDENTITY"))) continue; - if (strcmp(who, dbv2.pszVal)) { - char *pszRole; - TCHAR *ptszRole = NULL; - - if (pszRole = SkypeGet ("CHATMEMBER", token, "ROLE")) - ptszRole = make_nonutf_tchar_string((const unsigned char*)pszRole); - - i=AddChatContact(gc, who, ptszRole); - free_nonutf_tchar_string (ptszRole); - if (pszRole) free (pszRole); - if (i>=0 && !contactmask && !(contactmask = (unsigned char*)calloc(gc->mJoinedCount, 1))) i=-2; - if (!(contactmask= (unsigned char *) realloc(contactmask, gc->mJoinedCount))) { - iRet = -1; - free (who); - break; - } - contactmask[i]=TRUE; - } - free (who); - } - free (pszMemObjs); - } - else - { - // Add new contacts (normal) - for (who=strtok_r(ptr, " ", &nextoken); who; who=strtok_r(NULL, " ", &nextoken)) { - if (strcmp(who, dbv2.pszVal)) { - i=AddChatContact(gc, who, NULL); - if (i>=0 && !contactmask && !(contactmask = (unsigned char*)calloc(gc->mJoinedCount, 1))) i=-2; - if (i<0 || !(contactmask= (unsigned char *) realloc(contactmask, gc->mJoinedCount))) { - iRet = -1; - break; - } - contactmask[i]=TRUE; - } - } - } - // Quit contacts which are no longer there - if (iRet == 0 && contactmask) { - GCDEST gcd = {0}; - GCEVENT gce = {0}; - - gcd.pszModule = SKYPE_PROTONAME; - gcd.ptszID = szChatId; - gcd.iType = GC_EVENT_QUIT; - - gce.cbSize = sizeof(GCEVENT); - gce.pDest = &gcd; - gce.time = (DWORD)time(NULL); - gce.dwFlags = GCEF_ADDTOLOG | GC_TCHAR; - - ci.cbSize = sizeof(ci); - ci.szProto = SKYPE_PROTONAME; - ci.dwFlag = CNF_DISPLAY; - - for (i=0;imJoinedCount;i++) - if (!contactmask[i]) - { - ci.hContact = gc->mJoinedContacts[i].hContact; - ci.dwFlag = CNF_TCHAR; - if (ci.hContact && !CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci)) gce.ptszNick=ci.pszVal; - else gce.ptszNick=gc->mJoinedContacts[i].who; - RemChatContact(gc, gc->mJoinedContacts[i].who); - gce.ptszUID = gc->mJoinedContacts[i].who; - CallService(MS_GC_EVENT, 0, (LPARAM)&gce); - if (ci.pszVal) { - mir_free (ci.pszVal); - ci.pszVal=NULL; - } - } - // We don't do this, because the dialog group-chat may have been started intentionally - /* - if (gc->mJoinedCount == 1) { - // switch back to normal session - KillChatSession(&gcd); - } - */ - } - if (contactmask) free(contactmask); - db_free(&dbv2); - } else iRet = -1; - free_nonutf_tchar_string (szChatId); - LeaveCriticalSection(&m_GCMutex); - LOG(("AddMembers DONE")); - return iRet; -} - -void AddMembersThread(char *szSkypeMsg) -{ - AddMembers (szSkypeMsg); - free (szSkypeMsg); -} - -/****************************************************************************/ -/* Window procedures */ -/****************************************************************************/ -INT_PTR CALLBACK InputBoxDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_INITDIALOG: - { - TranslateDialogDefault(hwndDlg); - SetWindowLongPtr(hwndDlg, DWLP_USER, lParam); - SetDlgItemText(hwndDlg, IDC_TEXT, (TCHAR*)lParam); - return TRUE; - } - - case WM_COMMAND: - switch ( LOWORD( wParam )) { - case IDOK: - { - GetDlgItemText(hwndDlg, IDC_TEXT, (TCHAR*)GetWindowLongPtr(hwndDlg, DWLP_USER), (MAX_BUF-1)*sizeof(TCHAR)); - EndDialog(hwndDlg, 1); - break; - } - case IDCANCEL: - EndDialog(hwndDlg, 0); - break; - } } - return FALSE; -} - -/****************************************************************************/ -/* Core Chat management functions */ -/****************************************************************************/ - -/* We have a new Groupchat - - This hook is called when a new chat is initialised. - Parameters: wParam = (char *)Name of new chat session [Has to be ASCIIZ/UTF8] - lParam = 1 - Create groupchat, but don't open it - 0 - Default - open groupchat after init -*/ -int __cdecl ChatInit(WPARAM wParam, LPARAM lParam) { - GCSESSION gcw = {0}; - GCEVENT gce = {0}; - GCDEST gcd = {0}; - DBVARIANT dbv, dbv2; - char *szChatName; - int iRet = -1; - - UNREFERENCED_PARAMETER(lParam); - - if (!wParam) return -1; - - gcw.cbSize = sizeof(GCSESSION); - gcw.iType = GCW_CHATROOM; - gcw.pszModule = SKYPE_PROTONAME; - gcw.dwFlags = GC_TCHAR; - - if (!(szChatName = SkypeGet ("CHAT", (char *)wParam, "FRIENDLYNAME")) || !*szChatName) - gcw.ptszName=TranslateT("Unknown"); else { -#ifdef _UNICODE - gcw.ptszName=make_unicode_string((const unsigned char*)szChatName); - free (szChatName); - szChatName = (char*)gcw.ptszName; -#else - gcw.ptszName=szChatName; -#endif - } - gcw.ptszID = make_nonutf_tchar_string((const unsigned char*)wParam); - gcw.ptszStatusbarText = NULL; - EnterCriticalSection(&m_GCMutex); - if (!CallService(MS_GC_NEWSESSION, 0, (LPARAM)&gcw)) { - char *szChatRole; - - gce.cbSize = sizeof(GCEVENT); - gcd.pszModule = SKYPE_PROTONAME; - gcd.ptszID = (TCHAR*)gcw.ptszID; - gcd.iType = GC_EVENT_ADDGROUP; - gce.pDest = &gcd; - gce.ptszStatus = _T("CREATOR"); - gce.dwFlags = GC_TCHAR; - // BUG: Groupchat returns nonzero on success here in earlier versions, so we don't check - // it here - CallService(MS_GC_EVENT, 0, (LPARAM)&gce); - gce.ptszStatus = _T("MASTER"); - CallService(MS_GC_EVENT, 0, (LPARAM)&gce); - gce.ptszStatus = _T("HELPER"); - CallService(MS_GC_EVENT, 0, (LPARAM)&gce); - gce.ptszStatus = _T("USER"); - CallService(MS_GC_EVENT, 0, (LPARAM)&gce); - gce.ptszStatus = _T("LISTENER"); - CallService(MS_GC_EVENT, 0, (LPARAM)&gce); - gce.ptszStatus = _T("APPLICANT"); - CallService(MS_GC_EVENT, 0, (LPARAM)&gce); - - gcd.iType = GC_EVENT_JOIN; - gce.ptszStatus = NULL; - if (protocol >=7 && (szChatRole = SkypeGet ("CHAT", (char *)wParam, "MYROLE"))) { - if (strncmp(szChatRole, "ERROR", 5)) - { -#ifdef _UNICODE - gce.ptszStatus = make_unicode_string((const unsigned char*)szChatRole); - free (szChatRole); -#else - gce.ptszStatus = szChatRole; -#endif - } - } - if (!gce.ptszStatus) gce.ptszStatus=_tcsdup(_T("CREATOR")); - - if (!db_get_ts(NULL, SKYPE_PROTONAME, "Nick", &dbv)) { - if (!db_get_ts(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv2)) { - gce.ptszNick = dbv.ptszVal; - gce.ptszUID = dbv2.ptszVal; - gce.time = 0; - gce.bIsMe = TRUE; - gce.dwFlags |= GCEF_ADDTOLOG; - if (!CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce)) { - gce.cbSize = sizeof(GCEVENT); - gcd.iType = GC_EVENT_CONTROL; - gce.pDest = &gcd; - if (!lParam) CallService(MS_GC_EVENT, SESSION_INITDONE, (LPARAM)&gce); - CallService(MS_GC_EVENT, SESSION_ONLINE, (LPARAM)&gce); - CallService(MS_GC_EVENT, lParam ? WINDOW_HIDDEN : WINDOW_VISIBLE, (LPARAM)&gce); - SkypeSend ("GET CHAT %s MEMBERS", (char *)wParam); - iRet = 0; - } - else {LOG (("ChatInit: Joining 'me' failed."));} - } - db_free(&dbv2); - } - free ((void*)gce.ptszStatus); - db_free(&dbv); - } - free (szChatName); - free_nonutf_tchar_string ((void*)gcw.ptszID); - LeaveCriticalSection(&m_GCMutex); - return iRet; -} - -/* Open new Groupchat - - Parameters: szChatId = (char *)Name of new chat session -*/ -int __cdecl ChatStart(char *szChatId, BOOL bJustCreate) { - LOG(("ChatStart: New groupchat started")); - if (!szChatId || NotifyEventHooks(hInitChat, (WPARAM)szChatId, bJustCreate)) return -1; - return 0; -} - - -void KillChatSession(GCDEST *gcd) { - GCEVENT gce = {0}; - - EnterCriticalSection(&m_GCMutex); - LOG(("KillChatSession: Groupchatsession terminated.")); - gce.cbSize = sizeof(GCEVENT); - gce.dwFlags = GC_TCHAR; - gce.pDest = gcd; - gcd->iType = GC_EVENT_CONTROL; - if (SkypeSend ("ALTER CHAT "STR" LEAVE", gcd->ptszID) == 0) - { - CallService(MS_GC_EVENT, SESSION_OFFLINE, (LPARAM)&gce); - CallService(MS_GC_EVENT, SESSION_TERMINATE, (LPARAM)&gce); - } - LeaveCriticalSection(&m_GCMutex); -} - -void InviteUser(const TCHAR *szChatId) -{ - HMENU tMenu = CreatePopupMenu(); - MCONTACT hContact = db_find_first(), hInvitedUser; - DBVARIANT dbv; - HWND tWindow; - POINT pt; - gchat_contacts *gc; - int j; - - if (!szChatId || !(gc=GetChat(szChatId))) return; - - // add the heading - AppendMenu(tMenu, MF_STRING|MF_GRAYED|MF_DISABLED, (UINT_PTR)0, TranslateT("&Invite user...")); - AppendMenu(tMenu, MF_SEPARATOR, (UINT_PTR)1, NULL); - - // generate a list of contact - while (hContact) { - char *szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact,0 ); - if (szProto && !strcmp(SKYPE_PROTONAME, szProto) && - !db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0) && - db_get_w(hContact, SKYPE_PROTONAME, "Status", ID_STATUS_OFFLINE)!=ID_STATUS_OFFLINE) - { - BOOL alreadyInSession = FALSE; - for (j=0; jmJoinedCount; j++) { - if (gc->mJoinedContacts[j].hContact==hContact) { - alreadyInSession = TRUE; - break; - } - } - if (!alreadyInSession) - AppendMenu(tMenu, MF_STRING, (UINT_PTR)hContact, - (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)); - } - hContact = db_find_next(hContact); - } - - tWindow = CreateWindow(_T("EDIT"),_T(""),0,1,1,1,1,NULL,NULL,hInst,NULL); - - GetCursorPos (&pt); - hInvitedUser = (MCONTACT)TrackPopupMenu(tMenu, TPM_NONOTIFY | TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD, pt.x, pt.y, 0, tWindow, NULL); - DestroyMenu(tMenu); - DestroyWindow(tWindow); - - if (!hInvitedUser || db_get_s(hInvitedUser, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) - return; - SkypeSend ("ALTER CHAT "STR" ADDMEMBERS %s", szChatId, dbv.pszVal); - db_free(&dbv); - -} - -static void KickUser (MCONTACT hContact, GCHOOK *gch) -{ - char *ptr; - - EnterCriticalSection(&m_GCMutex); - if (SkypeSend ("ALTER CHAT "STR" KICK "STR, gch->pDest->ptszID, gch->ptszUID)!=-1) { - if (ptr=SkypeRcv("ALTER CHAT KICK", 2000)) { - if (strncmp(ptr, "ERROR", 5)) { - GCDEST gcd = {0}; - GCEVENT gce = {0}; - CONTACTINFO ci = {0}; - DBVARIANT dbv; - - gcd.pszModule = SKYPE_PROTONAME; - gcd.ptszID = (TCHAR*)gch->pDest->ptszID; - gcd.iType = GC_EVENT_KICK; - - gce.cbSize = sizeof(GCEVENT); - gce.pDest = &gcd; - gce.time = (DWORD)time(NULL); - gce.dwFlags = GCEF_ADDTOLOG | GC_TCHAR; - gce.ptszUID= gch->ptszUID; - - ci.cbSize = sizeof(ci); - ci.szProto = SKYPE_PROTONAME; - ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; - ci.hContact = hContact; - if (hContact && !CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci)) gce.ptszNick=ci.pszVal; - else gce.ptszNick=gce.ptszUID; - - if (!db_get_ts(NULL, SKYPE_PROTONAME, "Nick", &dbv)) { - gce.ptszStatus = dbv.ptszVal; - CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce); - RemChatContact (GetChat(gcd.ptszID), gch->ptszUID); - db_free(&dbv); - } - if (ci.pszVal) mir_free (ci.pszVal); - } - free (ptr); - } - } - LeaveCriticalSection(&m_GCMutex); -} - -void SetChatTopic(TCHAR *szChatId, TCHAR *szTopic, BOOL bSet) -{ - GCDEST gcd = {0}; - GCEVENT gce = {0}; - MCONTACT hContact = find_chat (szChatId); - char *szUTFTopic; - - gce.cbSize = sizeof(GCEVENT); - gcd.pszModule = SKYPE_PROTONAME; - gcd.ptszID = szChatId; - gcd.iType = GC_EVENT_TOPIC; - gce.pDest = &gcd; - gce.ptszText = szTopic; - gce.dwFlags = GCEF_ADDTOLOG | GC_TCHAR; - gce.time = (DWORD)time (NULL); - gce.dwFlags = GC_TCHAR; - CallService(MS_GC_EVENT, 0, (LPARAM)&gce); - - gcd.iType = GC_EVENT_SETSBTEXT; - CallService(MS_GC_EVENT, 0, (LPARAM)&gce); - - if (bSet) { -#ifdef _UNICODE - szUTFTopic=(char*)make_utf8_string(szTopic); -#else - if (utf8_encode(szTopic, &szUTFTopic)==-1) szUTFTopic = NULL; -#endif - if (szUTFTopic) { - SkypeSend ("ALTER CHAT "STR" SETTOPIC %s", szChatId, szUTFTopic); - free (szUTFTopic); - } - testfor ("ALTER CHAT SETTOPIC", INFINITE); - } - - if (hContact) - db_set_ts(hContact, SKYPE_PROTONAME, "Nick", szTopic); -} - - -int GCEventHook(WPARAM wParam,LPARAM lParam) { - GCHOOK *gch = (GCHOOK*) lParam; - gchat_contacts *gc = GetChat(gch->pDest->ptszID); - - UNREFERENCED_PARAMETER(wParam); - - if(gch) { - if (!_stricmp(gch->pDest->pszModule, SKYPE_PROTONAME)) { - - switch (gch->pDest->iType) { - case GC_SESSION_TERMINATE: { - MCONTACT hContact; - - if (gc->mJoinedCount == 1) { - // switch back to normal session - // I don't know if this behaviour isn't a bit annoying, therefore, we - // don't do this now, until a user requests this feature :) - - // open up srmm dialog when quit while 1 person left -// CallService(MS_MSG_SENDMESSAGE, (WPARAM)gc->mJoinedContacts[0].hContact, 0); - - RemChatContact(gc, gc->mJoinedContacts[0].who); - } - // Delete Chatroom from Contact list, as we don't need it anymore...? - if (hContact = find_chat(gc->szChatName)) - CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0); - RemChat(gc->szChatName); - - break; - } - case GC_USER_MESSAGE: - if(gch && gch->ptszText && _tcslen(gch->ptszText) > 0) { - DBVARIANT dbv, dbv2; - CCSDATA ccs = {0}; - GCDEST gcd = { 0 }; - GCEVENT gce = { sizeof(gce), &gcd }; - TCHAR *pEnd; - - // remove the ending linebreak - for (pEnd = &gch->ptszText[_tcslen(gch->ptszText) - 1]; - *pEnd==_T('\r') || *pEnd==_T('\n'); pEnd--) *pEnd=0; - // Send message to the chat-contact - if (ccs.hContact = find_chat(gch->pDest->ptszID)) { -#ifdef _UNICODE - // If PREF_UTF is supported, just convert it to UTF8 and pass the buffer to PSS_MESSAGE - if (mirandaVersion >= 0x070000) { - ccs.lParam = (LPARAM)make_utf8_string(gch->ptszText); - ccs.wParam = PREF_UTF; - CallProtoService (SKYPE_PROTONAME, PSS_MESSAGE, 0, (LPARAM)&ccs); - free ((void*)ccs.lParam); - } else { - // Otherwise create this strange dual miranda-format - ccs.lParam = (LPARAM)calloc(3, _tcslen(gch->ptszText)+1); - wcstombs ((char*)ccs.lParam, gch->ptszText, _tcslen(gch->ptszText)+1); - _tcscpy ((TCHAR*)((char*)ccs.lParam+strlen((char*)ccs.lParam)+1), gch->ptszText); - ccs.wParam = PREF_UNICODE; - CallProtoService (SKYPE_PROTONAME, PSS_MESSAGE, 0, (LPARAM)&ccs); - free ((void*)ccs.lParam); - } -#else - ccs.lParam = (LPARAM)gch->ptszText; - ccs.wParam = PREF_TCHAR; - CallProtoService (SKYPE_PROTONAME, PSS_MESSAGE, 0, (LPARAM)&ccs); -#endif - } - - // Add our line to the chatlog - gcd.pszModule = gch->pDest->pszModule; - gcd.ptszID = gch->pDest->ptszID; - if ( _tcsncmp(gch->ptszText, _T("/me "), 4)==0 && _tcslen(gch->ptszText)>4) { - gce.ptszText = gch->ptszText+4; - gcd.iType = GC_EVENT_ACTION; - } - else { - gce.ptszText = gch->ptszText; - gcd.iType = GC_EVENT_MESSAGE; - } - - if (db_get_ts(NULL, SKYPE_PROTONAME, "Nick", &dbv)) - gce.ptszNick = TranslateT("Me"); - else - gce.ptszNick = dbv.ptszVal; - db_get_ts(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv2); - gce.ptszUID = dbv2.ptszVal; - gce.time = (DWORD)time(NULL); - gce.dwFlags = GCEF_ADDTOLOG; - gce.bIsMe = TRUE; - CallService(MS_GC_EVENT, 0, (LPARAM)&gce); - if (dbv.pszVal) db_free(&dbv); - if (dbv2.pszVal) db_free(&dbv2); - } - break; - case GC_USER_CHANMGR: - InviteUser(gch->pDest->ptszID); - break; - case GC_USER_PRIVMESS: { - MCONTACT hContact = find_contactT(gch->ptszUID); - if (hContact) CallService(MS_MSG_SENDMESSAGE, (WPARAM)hContact, 0); - break; - - } - case GC_USER_LOGMENU: - switch(gch->dwData) { - case 10: InviteUser(gch->pDest->ptszID); break; - case 20: KillChatSession(gch->pDest); break; - case 30: - { - TCHAR *ptr, buf[MAX_BUF]; - - ptr = SkypeGetT ("CHAT", (TCHAR*)gch->pDest->ptszID, "TOPIC"); - _tcscpy(buf, ptr); - free(ptr); - if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_INPUTBOX), NULL, InputBoxDlgProc, (LPARAM)&buf)) - SetChatTopic((TCHAR*)gch->pDest->ptszID, buf, TRUE); - break; - } - } - break; - case GC_USER_NICKLISTMENU: { - MCONTACT hContact = find_contactT(gch->ptszUID); - - switch(gch->dwData) { - case 10:CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)hContact, 0); break; - case 20:CallService(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM)hContact, 0); break; - case 30: KickUser(hContact, gch); break; - case 110: KillChatSession(gch->pDest); break; - } - break; - } - default: - break; - } - } - - } - return 0; -} - -int __cdecl GCMenuHook(WPARAM wParam,LPARAM lParam) { - GCMENUITEMS *gcmi= (GCMENUITEMS*) lParam; - DBVARIANT dbv; - TCHAR* szInvite = TranslateT("&Invite user..."); - TCHAR* szLeave = TranslateT("&Leave chat session"); - TCHAR* szTopic = TranslateT("Set &Topic..."); - TCHAR* szDetails = TranslateT("User &details"); - TCHAR* szHistory = TranslateT("User &history"); - TCHAR* szKick = TranslateT("&Kick user"); - - static struct gc_item Item_log[] = { - {NULL, 10, MENU_ITEM, FALSE}, - {NULL, 30, MENU_ITEM, FALSE}, - {NULL, 20, MENU_ITEM, FALSE} - }; - static struct gc_item Item_nicklist_me[] = { - {NULL, 20, MENU_ITEM, FALSE}, - {_T(""), 100, MENU_SEPARATOR, FALSE}, - {NULL, 110, MENU_ITEM, FALSE} - }; - static struct gc_item Item_nicklist[] = { - {NULL, 10, MENU_ITEM, FALSE}, - {NULL, 20, MENU_ITEM, FALSE}, - {NULL, 30, MENU_ITEM, FALSE} - }; - - UNREFERENCED_PARAMETER(wParam); - - Item_log[0].pszDesc = szInvite; - Item_log[1].pszDesc = szTopic; - Item_log[2].pszDesc = szLeave; - Item_nicklist_me[0].pszDesc = szHistory; - Item_nicklist_me[2].pszDesc = szLeave; - Item_nicklist[0].pszDesc = szDetails; - Item_nicklist[1].pszDesc = szHistory; - Item_nicklist[2].pszDesc = szKick; - - LOG (("GCMenuHook started.")); - if(gcmi) { - if (!_stricmp(gcmi->pszModule, SKYPE_PROTONAME)) { - switch (gcmi->Type) - { - case MENU_ON_LOG: - gcmi->nItems = sizeof(Item_log)/sizeof(Item_log[0]); - gcmi->Item = &Item_log[0]; - LOG (("GCMenuHook: Items in log window: %d", gcmi->nItems)); - break; - case MENU_ON_NICKLIST: - if (db_get_ts(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) return -1; - if (!lstrcmp(dbv.ptszVal, gcmi->pszUID)) { - gcmi->nItems = sizeof(Item_nicklist_me)/sizeof(Item_nicklist_me[0]); - gcmi->Item = &Item_nicklist_me[0]; - } else { - gchat_contacts *gcs = GetChat(gcmi->pszID); - gchat_contact *gc = gcs?GetChatContact(gcs, gcmi->pszUID):NULL; - gcmi->nItems = sizeof(Item_nicklist)/sizeof(Item_nicklist[0]); - - Item_nicklist[2].bDisabled = FALSE; - if (gc && !gc->hContact) - { - gcmi->nItems -= 2; - gcmi->Item = &Item_nicklist[2]; - } - else - gcmi->Item = &Item_nicklist[0]; - /* - if (protocol<7) Item_nicklist[2].bDisabled = TRUE; - else { - TCHAR *szChatRole; - if (szChatRole = SkypeGetT ("CHAT", gcmi->pszID, "MYROLE")) { - if (_tcscmp(szChatRole, _T("MASTER")) && _tcscmp(szChatRole, _T("CREATOR"))) - Item_nicklist[2].bDisabled = TRUE; - free (szChatRole); - } - }*/ - - } - db_free(&dbv); - break; - } - } else {LOG (("GCMenuHook: ERROR: Not our protocol."));} - } else {LOG (("GCMenuHook: ERROR: No gcmi"));} - LOG (("GCMenuHook: terminated.")); - return 0; -} - -INT_PTR GCOnLeaveChat(WPARAM wParam,LPARAM lParam) -{ - MCONTACT hContact = (MCONTACT)wParam; - DBVARIANT dbv; - - UNREFERENCED_PARAMETER(lParam); - - if (db_get_ts(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv) == 0) - { - GCDEST gcd = {0}; - - gcd.pszModule = SKYPE_PROTONAME; - gcd.iType = GC_EVENT_CONTROL; - gcd.ptszID = dbv.ptszVal; - KillChatSession(&gcd); - db_free(&dbv); - } - return 0; -} - -INT_PTR GCOnJoinChat(WPARAM wParam,LPARAM lParam) -{ - MCONTACT hContact = (MCONTACT)wParam; - DBVARIANT dbv; - - UNREFERENCED_PARAMETER(lParam); - - if (db_get_s(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv) == 0) - { - ChatStart (dbv.pszVal, FALSE); - db_free(&dbv); - } - return 0; -} - -void GCInit(void) -{ - InitializeCriticalSection (&m_GCMutex); -} - -void GCExit(void) -{ - int i; - - DeleteCriticalSection (&m_GCMutex); - for (i=0;i +#include +#include +#include +#pragma warning (pop) + +#ifndef DWLP_USER +#define DWLP_USER DWL_USER +#endif + +#ifdef _UNICODE +#define STR "%S" +#else +#define STR "%s" +#endif + +/* VC6 PSDK compatibility */ +#if !defined(_WIN64) && !defined(SetWindowLongPtr) +#define SetWindowLongPtr SetWindowLong +#define GetWindowLongPtr GetWindowLong +#endif + +#pragma warning (disable: 4706) // assignment within conditional expression + +extern HANDLE hInitChat; +extern HINSTANCE hInst; +extern char protocol, g_szProtoName[]; +extern DWORD mirandaVersion; + +static gchat_contacts *chats=NULL; +static int chatcount=0; +static CRITICAL_SECTION m_GCMutex; + +// TODO: Disable groupchat for Protocol verisons <5 + +/****************************************************************************/ +/* Chat management helper functions */ +/****************************************************************************/ + +/* Get the gchat_contacts entry for the chat with the id szChatId + If the chat doesn't already exist in the list, it is added. + + Parameters: szChatId - String with the chat ID of the chat to be found + Returns: Pointer to the gchat_contacts entry for the given id. + NULL on failure (not enough memory) +*/ +gchat_contacts *GetChat(const TCHAR *szChatId) { + int i; + + for (i=0;i=0 = Number of found item + */ +static int ExistsChatContact(gchat_contacts *gc, const TCHAR *who) { + int i; + + for (i=0;imJoinedCount;i++) + if (_tcscmp(gc->mJoinedContacts[i].who, who)==0) return i; + return -1; +} + +gchat_contact *GetChatContact(gchat_contacts *gc, const TCHAR *who) { + int i = ExistsChatContact (gc, who); + + if (i==-1) return NULL; + return &gc->mJoinedContacts[i]; +} + +/* Adds contact with the name who to the groupchat given in gc + + Parameters: gc - + Returns: -1 = Contact not found + -2 = On failure + >=0 = Number of added item + */ +static int AddChatContact(gchat_contacts *gc, char *who, TCHAR *pszRole) +{ + int i = -2; + MCONTACT hContact; + GCDEST gcd = {0}; + GCEVENT gce = {0}; + CONTACTINFO ci = {0}; + TCHAR *twho; + + LOG (("AddChatContact %s", who)); + if (!(twho = make_nonutf_tchar_string((const unsigned char*)who))) + return -2; + if ((i=ExistsChatContact(gc, twho))>=0) return i; + hContact=find_contact(who); + + gcd.pszModule = SKYPE_PROTONAME; + gcd.ptszID = gc->szChatName; + gcd.iType = GC_EVENT_JOIN; + + gce.cbSize = sizeof(GCEVENT); + gce.pDest = &gcd; + gce.ptszStatus = pszRole?pszRole:_T("USER"); + gce.time = (DWORD)time(NULL); + gce.dwFlags = GCEF_ADDTOLOG | GC_TCHAR; + + ci.cbSize = sizeof(ci); + ci.szProto = SKYPE_PROTONAME; + ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; + ci.hContact = hContact; + + if (hContact && !CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci)) gce.ptszNick=ci.pszVal; + else gce.ptszNick=twho; + + gce.ptszUID=twho; + if (!CallService(MS_GC_EVENT, 0, (LPARAM)&gce)) { + if ((gc->mJoinedContacts=(gchat_contact*)realloc(gc->mJoinedContacts, (gc->mJoinedCount+1)*sizeof(gchat_contact)))) + { + gc->mJoinedContacts[i=gc->mJoinedCount].hContact=hContact; + _tcscpy (gc->mJoinedContacts[i].szRole, gce.ptszStatus); + _tcscpy (gc->mJoinedContacts[i].who, twho); + gc->mJoinedCount++; + } + } + if (ci.pszVal) mir_free (ci.pszVal); + free_nonutf_tchar_string (twho); + return i; +} + +void RemChatContact(gchat_contacts *gc, const TCHAR *who) { + int i; + + if (!gc) return; + for (i=0;imJoinedCount;i++) + if (_tcscmp(gc->mJoinedContacts[i].who, who)==0) { + if (i<--gc->mJoinedCount) + memmove(&gc->mJoinedContacts[i], &gc->mJoinedContacts[i+1], (gc->mJoinedCount-i)*sizeof(gchat_contact)); + if (gc->mJoinedCount) gc->mJoinedContacts = (gchat_contact*)realloc(gc->mJoinedContacts, sizeof(gchat_contact)*gc->mJoinedCount); + else {free (gc->mJoinedContacts); gc->mJoinedContacts = NULL; } + return; + } +} + +MCONTACT find_chat(LPCTSTR chatname) { + char *szProto; + int tCompareResult; + MCONTACT hContact; + DBVARIANT dbv; + + for (hContact=db_find_first();hContact != NULL;hContact=db_find_next(hContact)) { + szProto = (char*)CallService( MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0 ); + if (szProto!=NULL && !strcmp(szProto, SKYPE_PROTONAME) && + db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0)==1) + { + if (db_get_ts(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv)) continue; + tCompareResult = _tcscmp(dbv.ptszVal, chatname); + db_free(&dbv); + if (tCompareResult) continue; + return hContact; // already there, return handle + } + } + return NULL; +} + +#ifdef _UNICODE +MCONTACT find_chatA(char *chatname) { + char *szProto; + int tCompareResult; + MCONTACT hContact; + DBVARIANT dbv; + + for (hContact=db_find_first();hContact != NULL;hContact=db_find_next(hContact)) { + szProto = (char*)CallService( MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0 ); + if (szProto!=NULL && !strcmp(szProto, SKYPE_PROTONAME) && + db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0)==1) + { + if (db_get_s(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv)) continue; + tCompareResult = strcmp(dbv.pszVal, chatname); + db_free(&dbv); + if (tCompareResult) continue; + return hContact; // already there, return handle + } + } + return NULL; +} +#endif + + + +int __cdecl AddMembers(char *szSkypeMsg) { + BYTE *contactmask=NULL; + DBVARIANT dbv2; + CONTACTINFO ci={0}; + char *ptr, *who, *nextoken; + TCHAR *szChatId; + int i, iRet = 0; + gchat_contacts *gc; + + LOG(("AddMembers STARTED")); + if (!(ptr=strstr(szSkypeMsg, " MEMBERS"))) return -1; + EnterCriticalSection(&m_GCMutex); + ptr[0]=0; + szChatId = make_nonutf_tchar_string((const unsigned char*)szSkypeMsg+5); + ptr+=9; + if (find_chat(szChatId) && (gc=GetChat(szChatId)) && + !db_get_s(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv2)) + { + char *pszMemObjs, *token; + + if (protocol>=7 && (pszMemObjs = SkypeGet ("CHAT", szSkypeMsg+5, "MEMBEROBJECTS"))) { + // Add new contacts (protocol 7+ with memberobjects, supports roles) + for (token=strtok_r(pszMemObjs, ", ", &nextoken); token; token=strtok_r(NULL, ", ", &nextoken)) { + if (!(who = SkypeGet ("CHATMEMBER", token, "IDENTITY"))) continue; + if (strcmp(who, dbv2.pszVal)) { + char *pszRole; + TCHAR *ptszRole = NULL; + + if (pszRole = SkypeGet ("CHATMEMBER", token, "ROLE")) + ptszRole = make_nonutf_tchar_string((const unsigned char*)pszRole); + + i=AddChatContact(gc, who, ptszRole); + free_nonutf_tchar_string (ptszRole); + if (pszRole) free (pszRole); + if (i>=0 && !contactmask && !(contactmask = (unsigned char*)calloc(gc->mJoinedCount, 1))) i=-2; + if (!(contactmask= (unsigned char *) realloc(contactmask, gc->mJoinedCount))) { + iRet = -1; + free (who); + break; + } + contactmask[i]=TRUE; + } + free (who); + } + free (pszMemObjs); + } + else + { + // Add new contacts (normal) + for (who=strtok_r(ptr, " ", &nextoken); who; who=strtok_r(NULL, " ", &nextoken)) { + if (strcmp(who, dbv2.pszVal)) { + i=AddChatContact(gc, who, NULL); + if (i>=0 && !contactmask && !(contactmask = (unsigned char*)calloc(gc->mJoinedCount, 1))) i=-2; + if (i<0 || !(contactmask= (unsigned char *) realloc(contactmask, gc->mJoinedCount))) { + iRet = -1; + break; + } + contactmask[i]=TRUE; + } + } + } + // Quit contacts which are no longer there + if (iRet == 0 && contactmask) { + GCDEST gcd = {0}; + GCEVENT gce = {0}; + + gcd.pszModule = SKYPE_PROTONAME; + gcd.ptszID = szChatId; + gcd.iType = GC_EVENT_QUIT; + + gce.cbSize = sizeof(GCEVENT); + gce.pDest = &gcd; + gce.time = (DWORD)time(NULL); + gce.dwFlags = GCEF_ADDTOLOG | GC_TCHAR; + + ci.cbSize = sizeof(ci); + ci.szProto = SKYPE_PROTONAME; + ci.dwFlag = CNF_DISPLAY; + + for (i=0;imJoinedCount;i++) + if (!contactmask[i]) + { + ci.hContact = gc->mJoinedContacts[i].hContact; + ci.dwFlag = CNF_TCHAR; + if (ci.hContact && !CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci)) gce.ptszNick=ci.pszVal; + else gce.ptszNick=gc->mJoinedContacts[i].who; + RemChatContact(gc, gc->mJoinedContacts[i].who); + gce.ptszUID = gc->mJoinedContacts[i].who; + CallService(MS_GC_EVENT, 0, (LPARAM)&gce); + if (ci.pszVal) { + mir_free (ci.pszVal); + ci.pszVal=NULL; + } + } + // We don't do this, because the dialog group-chat may have been started intentionally + /* + if (gc->mJoinedCount == 1) { + // switch back to normal session + KillChatSession(&gcd); + } + */ + } + if (contactmask) free(contactmask); + db_free(&dbv2); + } else iRet = -1; + free_nonutf_tchar_string (szChatId); + LeaveCriticalSection(&m_GCMutex); + LOG(("AddMembers DONE")); + return iRet; +} + +void AddMembersThread(char *szSkypeMsg) +{ + AddMembers (szSkypeMsg); + free (szSkypeMsg); +} + +/****************************************************************************/ +/* Window procedures */ +/****************************************************************************/ +INT_PTR CALLBACK InputBoxDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + { + TranslateDialogDefault(hwndDlg); + SetWindowLongPtr(hwndDlg, DWLP_USER, lParam); + SetDlgItemText(hwndDlg, IDC_TEXT, (TCHAR*)lParam); + return TRUE; + } + + case WM_COMMAND: + switch ( LOWORD( wParam )) { + case IDOK: + { + GetDlgItemText(hwndDlg, IDC_TEXT, (TCHAR*)GetWindowLongPtr(hwndDlg, DWLP_USER), (MAX_BUF-1)*sizeof(TCHAR)); + EndDialog(hwndDlg, 1); + break; + } + case IDCANCEL: + EndDialog(hwndDlg, 0); + break; + } } + return FALSE; +} + +/****************************************************************************/ +/* Core Chat management functions */ +/****************************************************************************/ + +/* We have a new Groupchat + + This hook is called when a new chat is initialised. + Parameters: wParam = (char *)Name of new chat session [Has to be ASCIIZ/UTF8] + lParam = 1 - Create groupchat, but don't open it + 0 - Default - open groupchat after init +*/ +int __cdecl ChatInit(WPARAM wParam, LPARAM lParam) { + GCSESSION gcw = {0}; + GCEVENT gce = {0}; + GCDEST gcd = {0}; + DBVARIANT dbv, dbv2; + char *szChatName; + int iRet = -1; + + UNREFERENCED_PARAMETER(lParam); + + if (!wParam) return -1; + + gcw.cbSize = sizeof(GCSESSION); + gcw.iType = GCW_CHATROOM; + gcw.pszModule = SKYPE_PROTONAME; + gcw.dwFlags = GC_TCHAR; + + if (!(szChatName = SkypeGet ("CHAT", (char *)wParam, "FRIENDLYNAME")) || !*szChatName) + gcw.ptszName=TranslateT("Unknown"); else { +#ifdef _UNICODE + gcw.ptszName=make_unicode_string((const unsigned char*)szChatName); + free (szChatName); + szChatName = (char*)gcw.ptszName; +#else + gcw.ptszName=szChatName; +#endif + } + gcw.ptszID = make_nonutf_tchar_string((const unsigned char*)wParam); + gcw.ptszStatusbarText = NULL; + EnterCriticalSection(&m_GCMutex); + if (!CallService(MS_GC_NEWSESSION, 0, (LPARAM)&gcw)) { + char *szChatRole; + + gce.cbSize = sizeof(GCEVENT); + gcd.pszModule = SKYPE_PROTONAME; + gcd.ptszID = (TCHAR*)gcw.ptszID; + gcd.iType = GC_EVENT_ADDGROUP; + gce.pDest = &gcd; + gce.ptszStatus = _T("CREATOR"); + gce.dwFlags = GC_TCHAR; + // BUG: Groupchat returns nonzero on success here in earlier versions, so we don't check + // it here + CallService(MS_GC_EVENT, 0, (LPARAM)&gce); + gce.ptszStatus = _T("MASTER"); + CallService(MS_GC_EVENT, 0, (LPARAM)&gce); + gce.ptszStatus = _T("HELPER"); + CallService(MS_GC_EVENT, 0, (LPARAM)&gce); + gce.ptszStatus = _T("USER"); + CallService(MS_GC_EVENT, 0, (LPARAM)&gce); + gce.ptszStatus = _T("LISTENER"); + CallService(MS_GC_EVENT, 0, (LPARAM)&gce); + gce.ptszStatus = _T("APPLICANT"); + CallService(MS_GC_EVENT, 0, (LPARAM)&gce); + + gcd.iType = GC_EVENT_JOIN; + gce.ptszStatus = NULL; + if (protocol >=7 && (szChatRole = SkypeGet ("CHAT", (char *)wParam, "MYROLE"))) { + if (strncmp(szChatRole, "ERROR", 5)) + { +#ifdef _UNICODE + gce.ptszStatus = make_unicode_string((const unsigned char*)szChatRole); + free (szChatRole); +#else + gce.ptszStatus = szChatRole; +#endif + } + } + if (!gce.ptszStatus) gce.ptszStatus=_tcsdup(_T("CREATOR")); + + if (!db_get_ts(NULL, SKYPE_PROTONAME, "Nick", &dbv)) { + if (!db_get_ts(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv2)) { + gce.ptszNick = dbv.ptszVal; + gce.ptszUID = dbv2.ptszVal; + gce.time = 0; + gce.bIsMe = TRUE; + gce.dwFlags |= GCEF_ADDTOLOG; + if (!CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce)) { + gce.cbSize = sizeof(GCEVENT); + gcd.iType = GC_EVENT_CONTROL; + gce.pDest = &gcd; + if (!lParam) CallService(MS_GC_EVENT, SESSION_INITDONE, (LPARAM)&gce); + CallService(MS_GC_EVENT, SESSION_ONLINE, (LPARAM)&gce); + CallService(MS_GC_EVENT, lParam ? WINDOW_HIDDEN : WINDOW_VISIBLE, (LPARAM)&gce); + SkypeSend ("GET CHAT %s MEMBERS", (char *)wParam); + iRet = 0; + } + else {LOG (("ChatInit: Joining 'me' failed."));} + } + db_free(&dbv2); + } + free ((void*)gce.ptszStatus); + db_free(&dbv); + } + free (szChatName); + free_nonutf_tchar_string ((void*)gcw.ptszID); + LeaveCriticalSection(&m_GCMutex); + return iRet; +} + +/* Open new Groupchat + + Parameters: szChatId = (char *)Name of new chat session +*/ +int __cdecl ChatStart(char *szChatId, BOOL bJustCreate) { + LOG(("ChatStart: New groupchat started")); + if (!szChatId || NotifyEventHooks(hInitChat, (WPARAM)szChatId, bJustCreate)) return -1; + return 0; +} + + +void KillChatSession(GCDEST *gcd) { + GCEVENT gce = {0}; + + EnterCriticalSection(&m_GCMutex); + LOG(("KillChatSession: Groupchatsession terminated.")); + gce.cbSize = sizeof(GCEVENT); + gce.dwFlags = GC_TCHAR; + gce.pDest = gcd; + gcd->iType = GC_EVENT_CONTROL; + if (SkypeSend ("ALTER CHAT "STR" LEAVE", gcd->ptszID) == 0) + { + CallService(MS_GC_EVENT, SESSION_OFFLINE, (LPARAM)&gce); + CallService(MS_GC_EVENT, SESSION_TERMINATE, (LPARAM)&gce); + } + LeaveCriticalSection(&m_GCMutex); +} + +void InviteUser(const TCHAR *szChatId) +{ + HMENU tMenu = CreatePopupMenu(); + MCONTACT hContact = db_find_first(), hInvitedUser; + DBVARIANT dbv; + HWND tWindow; + POINT pt; + gchat_contacts *gc; + int j; + + if (!szChatId || !(gc=GetChat(szChatId))) return; + + // add the heading + AppendMenu(tMenu, MF_STRING|MF_GRAYED|MF_DISABLED, (UINT_PTR)0, TranslateT("&Invite user...")); + AppendMenu(tMenu, MF_SEPARATOR, (UINT_PTR)1, NULL); + + // generate a list of contact + while (hContact) { + char *szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact,0 ); + if (szProto && !strcmp(SKYPE_PROTONAME, szProto) && + !db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0) && + db_get_w(hContact, SKYPE_PROTONAME, "Status", ID_STATUS_OFFLINE)!=ID_STATUS_OFFLINE) + { + BOOL alreadyInSession = FALSE; + for (j=0; jmJoinedCount; j++) { + if (gc->mJoinedContacts[j].hContact==hContact) { + alreadyInSession = TRUE; + break; + } + } + if (!alreadyInSession) + AppendMenu(tMenu, MF_STRING, (UINT_PTR)hContact, + (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR)); + } + hContact = db_find_next(hContact); + } + + tWindow = CreateWindow(_T("EDIT"),_T(""),0,1,1,1,1,NULL,NULL,hInst,NULL); + + GetCursorPos (&pt); + hInvitedUser = (MCONTACT)TrackPopupMenu(tMenu, TPM_NONOTIFY | TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD, pt.x, pt.y, 0, tWindow, NULL); + DestroyMenu(tMenu); + DestroyWindow(tWindow); + + if (!hInvitedUser || db_get_s(hInvitedUser, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) + return; + SkypeSend ("ALTER CHAT "STR" ADDMEMBERS %s", szChatId, dbv.pszVal); + db_free(&dbv); + +} + +static void KickUser (MCONTACT hContact, GCHOOK *gch) +{ + char *ptr; + + EnterCriticalSection(&m_GCMutex); + if (SkypeSend ("ALTER CHAT "STR" KICK "STR, gch->pDest->ptszID, gch->ptszUID)!=-1) { + if (ptr=SkypeRcv("ALTER CHAT KICK", 2000)) { + if (strncmp(ptr, "ERROR", 5)) { + GCDEST gcd = {0}; + GCEVENT gce = {0}; + CONTACTINFO ci = {0}; + DBVARIANT dbv; + + gcd.pszModule = SKYPE_PROTONAME; + gcd.ptszID = (TCHAR*)gch->pDest->ptszID; + gcd.iType = GC_EVENT_KICK; + + gce.cbSize = sizeof(GCEVENT); + gce.pDest = &gcd; + gce.time = (DWORD)time(NULL); + gce.dwFlags = GCEF_ADDTOLOG | GC_TCHAR; + gce.ptszUID= gch->ptszUID; + + ci.cbSize = sizeof(ci); + ci.szProto = SKYPE_PROTONAME; + ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; + ci.hContact = hContact; + if (hContact && !CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci)) gce.ptszNick=ci.pszVal; + else gce.ptszNick=gce.ptszUID; + + if (!db_get_ts(NULL, SKYPE_PROTONAME, "Nick", &dbv)) { + gce.ptszStatus = dbv.ptszVal; + CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce); + RemChatContact (GetChat(gcd.ptszID), gch->ptszUID); + db_free(&dbv); + } + if (ci.pszVal) mir_free (ci.pszVal); + } + free (ptr); + } + } + LeaveCriticalSection(&m_GCMutex); +} + +void SetChatTopic(const TCHAR *szChatId, TCHAR *szTopic, BOOL bSet) +{ + GCDEST gcd = {0}; + GCEVENT gce = {0}; + MCONTACT hContact = find_chat (szChatId); + char *szUTFTopic; + + gce.cbSize = sizeof(GCEVENT); + gcd.pszModule = SKYPE_PROTONAME; + gcd.ptszID = szChatId; + gcd.iType = GC_EVENT_TOPIC; + gce.pDest = &gcd; + gce.ptszText = szTopic; + gce.dwFlags = GCEF_ADDTOLOG | GC_TCHAR; + gce.time = (DWORD)time (NULL); + gce.dwFlags = GC_TCHAR; + CallService(MS_GC_EVENT, 0, (LPARAM)&gce); + + gcd.iType = GC_EVENT_SETSBTEXT; + CallService(MS_GC_EVENT, 0, (LPARAM)&gce); + + if (bSet) { +#ifdef _UNICODE + szUTFTopic=(char*)make_utf8_string(szTopic); +#else + if (utf8_encode(szTopic, &szUTFTopic)==-1) szUTFTopic = NULL; +#endif + if (szUTFTopic) { + SkypeSend ("ALTER CHAT "STR" SETTOPIC %s", szChatId, szUTFTopic); + free (szUTFTopic); + } + testfor ("ALTER CHAT SETTOPIC", INFINITE); + } + + if (hContact) + db_set_ts(hContact, SKYPE_PROTONAME, "Nick", szTopic); +} + + +int GCEventHook(WPARAM wParam,LPARAM lParam) { + GCHOOK *gch = (GCHOOK*) lParam; + gchat_contacts *gc = GetChat(gch->pDest->ptszID); + + UNREFERENCED_PARAMETER(wParam); + + if(gch) { + if (!_stricmp(gch->pDest->pszModule, SKYPE_PROTONAME)) { + + switch (gch->pDest->iType) { + case GC_SESSION_TERMINATE: { + MCONTACT hContact; + + if (gc->mJoinedCount == 1) { + // switch back to normal session + // I don't know if this behaviour isn't a bit annoying, therefore, we + // don't do this now, until a user requests this feature :) + + // open up srmm dialog when quit while 1 person left +// CallService(MS_MSG_SENDMESSAGE, (WPARAM)gc->mJoinedContacts[0].hContact, 0); + + RemChatContact(gc, gc->mJoinedContacts[0].who); + } + // Delete Chatroom from Contact list, as we don't need it anymore...? + if (hContact = find_chat(gc->szChatName)) + CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0); + RemChat(gc->szChatName); + + break; + } + case GC_USER_MESSAGE: + if(gch && gch->ptszText && _tcslen(gch->ptszText) > 0) { + DBVARIANT dbv, dbv2; + CCSDATA ccs = {0}; + GCDEST gcd = { 0 }; + GCEVENT gce = { sizeof(gce), &gcd }; + TCHAR *pEnd; + + // remove the ending linebreak + for (pEnd = &gch->ptszText[_tcslen(gch->ptszText) - 1]; + *pEnd==_T('\r') || *pEnd==_T('\n'); pEnd--) *pEnd=0; + // Send message to the chat-contact + if (ccs.hContact = find_chat(gch->pDest->ptszID)) { +#ifdef _UNICODE + // If PREF_UTF is supported, just convert it to UTF8 and pass the buffer to PSS_MESSAGE + if (mirandaVersion >= 0x070000) { + ccs.lParam = (LPARAM)make_utf8_string(gch->ptszText); + ccs.wParam = PREF_UTF; + CallProtoService (SKYPE_PROTONAME, PSS_MESSAGE, 0, (LPARAM)&ccs); + free ((void*)ccs.lParam); + } else { + // Otherwise create this strange dual miranda-format + ccs.lParam = (LPARAM)calloc(3, _tcslen(gch->ptszText)+1); + wcstombs ((char*)ccs.lParam, gch->ptszText, _tcslen(gch->ptszText)+1); + _tcscpy ((TCHAR*)((char*)ccs.lParam+strlen((char*)ccs.lParam)+1), gch->ptszText); + ccs.wParam = PREF_UNICODE; + CallProtoService (SKYPE_PROTONAME, PSS_MESSAGE, 0, (LPARAM)&ccs); + free ((void*)ccs.lParam); + } +#else + ccs.lParam = (LPARAM)gch->ptszText; + ccs.wParam = PREF_TCHAR; + CallProtoService (SKYPE_PROTONAME, PSS_MESSAGE, 0, (LPARAM)&ccs); +#endif + } + + // Add our line to the chatlog + gcd.pszModule = gch->pDest->pszModule; + gcd.ptszID = gch->pDest->ptszID; + if ( _tcsncmp(gch->ptszText, _T("/me "), 4)==0 && _tcslen(gch->ptszText)>4) { + gce.ptszText = gch->ptszText+4; + gcd.iType = GC_EVENT_ACTION; + } + else { + gce.ptszText = gch->ptszText; + gcd.iType = GC_EVENT_MESSAGE; + } + + if (db_get_ts(NULL, SKYPE_PROTONAME, "Nick", &dbv)) + gce.ptszNick = TranslateT("Me"); + else + gce.ptszNick = dbv.ptszVal; + db_get_ts(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv2); + gce.ptszUID = dbv2.ptszVal; + gce.time = (DWORD)time(NULL); + gce.dwFlags = GCEF_ADDTOLOG; + gce.bIsMe = TRUE; + CallService(MS_GC_EVENT, 0, (LPARAM)&gce); + if (dbv.pszVal) db_free(&dbv); + if (dbv2.pszVal) db_free(&dbv2); + } + break; + case GC_USER_CHANMGR: + InviteUser(gch->pDest->ptszID); + break; + case GC_USER_PRIVMESS: { + MCONTACT hContact = find_contactT(gch->ptszUID); + if (hContact) CallService(MS_MSG_SENDMESSAGE, (WPARAM)hContact, 0); + break; + + } + case GC_USER_LOGMENU: + switch(gch->dwData) { + case 10: InviteUser(gch->pDest->ptszID); break; + case 20: KillChatSession(gch->pDest); break; + case 30: + { + TCHAR *ptr, buf[MAX_BUF]; + + ptr = SkypeGetT ("CHAT", (TCHAR*)gch->pDest->ptszID, "TOPIC"); + _tcscpy(buf, ptr); + free(ptr); + if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_INPUTBOX), NULL, InputBoxDlgProc, (LPARAM)&buf)) + SetChatTopic(gch->pDest->ptszID, buf, TRUE); + break; + } + } + break; + case GC_USER_NICKLISTMENU: { + MCONTACT hContact = find_contactT(gch->ptszUID); + + switch(gch->dwData) { + case 10:CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)hContact, 0); break; + case 20:CallService(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM)hContact, 0); break; + case 30: KickUser(hContact, gch); break; + case 110: KillChatSession(gch->pDest); break; + } + break; + } + default: + break; + } + } + + } + return 0; +} + +int __cdecl GCMenuHook(WPARAM wParam,LPARAM lParam) { + GCMENUITEMS *gcmi= (GCMENUITEMS*) lParam; + DBVARIANT dbv; + TCHAR* szInvite = TranslateT("&Invite user..."); + TCHAR* szLeave = TranslateT("&Leave chat session"); + TCHAR* szTopic = TranslateT("Set &Topic..."); + TCHAR* szDetails = TranslateT("User &details"); + TCHAR* szHistory = TranslateT("User &history"); + TCHAR* szKick = TranslateT("&Kick user"); + + static struct gc_item Item_log[] = { + {NULL, 10, MENU_ITEM, FALSE}, + {NULL, 30, MENU_ITEM, FALSE}, + {NULL, 20, MENU_ITEM, FALSE} + }; + static struct gc_item Item_nicklist_me[] = { + {NULL, 20, MENU_ITEM, FALSE}, + {_T(""), 100, MENU_SEPARATOR, FALSE}, + {NULL, 110, MENU_ITEM, FALSE} + }; + static struct gc_item Item_nicklist[] = { + {NULL, 10, MENU_ITEM, FALSE}, + {NULL, 20, MENU_ITEM, FALSE}, + {NULL, 30, MENU_ITEM, FALSE} + }; + + UNREFERENCED_PARAMETER(wParam); + + Item_log[0].pszDesc = szInvite; + Item_log[1].pszDesc = szTopic; + Item_log[2].pszDesc = szLeave; + Item_nicklist_me[0].pszDesc = szHistory; + Item_nicklist_me[2].pszDesc = szLeave; + Item_nicklist[0].pszDesc = szDetails; + Item_nicklist[1].pszDesc = szHistory; + Item_nicklist[2].pszDesc = szKick; + + LOG (("GCMenuHook started.")); + if(gcmi) { + if (!_stricmp(gcmi->pszModule, SKYPE_PROTONAME)) { + switch (gcmi->Type) + { + case MENU_ON_LOG: + gcmi->nItems = sizeof(Item_log)/sizeof(Item_log[0]); + gcmi->Item = &Item_log[0]; + LOG (("GCMenuHook: Items in log window: %d", gcmi->nItems)); + break; + case MENU_ON_NICKLIST: + if (db_get_ts(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) return -1; + if (!lstrcmp(dbv.ptszVal, gcmi->pszUID)) { + gcmi->nItems = sizeof(Item_nicklist_me)/sizeof(Item_nicklist_me[0]); + gcmi->Item = &Item_nicklist_me[0]; + } else { + gchat_contacts *gcs = GetChat(gcmi->pszID); + gchat_contact *gc = gcs?GetChatContact(gcs, gcmi->pszUID):NULL; + gcmi->nItems = sizeof(Item_nicklist)/sizeof(Item_nicklist[0]); + + Item_nicklist[2].bDisabled = FALSE; + if (gc && !gc->hContact) + { + gcmi->nItems -= 2; + gcmi->Item = &Item_nicklist[2]; + } + else + gcmi->Item = &Item_nicklist[0]; + /* + if (protocol<7) Item_nicklist[2].bDisabled = TRUE; + else { + TCHAR *szChatRole; + if (szChatRole = SkypeGetT ("CHAT", gcmi->pszID, "MYROLE")) { + if (_tcscmp(szChatRole, _T("MASTER")) && _tcscmp(szChatRole, _T("CREATOR"))) + Item_nicklist[2].bDisabled = TRUE; + free (szChatRole); + } + }*/ + + } + db_free(&dbv); + break; + } + } else {LOG (("GCMenuHook: ERROR: Not our protocol."));} + } else {LOG (("GCMenuHook: ERROR: No gcmi"));} + LOG (("GCMenuHook: terminated.")); + return 0; +} + +INT_PTR GCOnLeaveChat(WPARAM wParam,LPARAM lParam) +{ + MCONTACT hContact = (MCONTACT)wParam; + DBVARIANT dbv; + + UNREFERENCED_PARAMETER(lParam); + + if (db_get_ts(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv) == 0) + { + GCDEST gcd = {0}; + + gcd.pszModule = SKYPE_PROTONAME; + gcd.iType = GC_EVENT_CONTROL; + gcd.ptszID = dbv.ptszVal; + KillChatSession(&gcd); + db_free(&dbv); + } + return 0; +} + +INT_PTR GCOnJoinChat(WPARAM wParam,LPARAM lParam) +{ + MCONTACT hContact = (MCONTACT)wParam; + DBVARIANT dbv; + + UNREFERENCED_PARAMETER(lParam); + + if (db_get_s(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv) == 0) + { + ChatStart (dbv.pszVal, FALSE); + db_free(&dbv); + } + return 0; +} + +void GCInit(void) +{ + InitializeCriticalSection (&m_GCMutex); +} + +void GCExit(void) +{ + int i; + + DeleteCriticalSection (&m_GCMutex); + for (i=0;i -#include "memlist.h" - -#pragma warning (disable: 4706) // assignment within conditional expression - -struct _tagLIST -{ - unsigned int uiCount; - unsigned int uiCapacity; - void **apStorage; - HANDLE hHeap; - CRITICAL_SECTION cs; -}; - - -TYP_LIST *List_Init(unsigned int uiCapacity) -{ - HANDLE hHeap = GetProcessHeap(); - TYP_LIST *pstHandle; - - pstHandle = (TYP_LIST *)HeapAlloc(hHeap, 0, sizeof(TYP_LIST)); - if (!pstHandle) return NULL; - pstHandle->uiCount = 0; - pstHandle->uiCapacity = uiCapacity; - if (uiCapacity == 0) - pstHandle->apStorage = NULL; - else - { - pstHandle->apStorage = (void **)HeapAlloc(hHeap, 0, sizeof(void *)*uiCapacity); - if (!pstHandle->apStorage) - { - HeapFree (hHeap, 0, pstHandle); - return NULL; - } - } - pstHandle->hHeap = hHeap; - InitializeCriticalSection (&pstHandle->cs); - return pstHandle; -} - -void List_Exit(TYP_LIST *pstHandle) -{ - if (pstHandle->apStorage) - HeapFree (pstHandle->hHeap, 0, pstHandle->apStorage); - DeleteCriticalSection (&pstHandle->cs); - HeapFree (pstHandle->hHeap, 0, pstHandle); -} - -BOOL List_Push(TYP_LIST *pstHandle, void *pItem) -{ - return List_InsertElementAt(pstHandle, pItem,pstHandle->uiCount); -} - -void *List_Pop (TYP_LIST *pstHandle) -{ - if (pstHandle->uiCount) - return List_RemoveElementAt(pstHandle ,pstHandle->uiCount-1); - else return NULL; -} - -BOOL List_InsertElementAt(TYP_LIST *pstHandle, void *pItem, unsigned int uiPos) -{ - unsigned int uiStep; - void **apNewStorage; - - EnterCriticalSection (&pstHandle->cs); - if (uiPos > pstHandle->uiCount) - uiPos = pstHandle->uiCount; - - if (pstHandle->uiCount >= pstHandle->uiCapacity) - { - uiStep = pstHandle->uiCount*2; - if (uiStep < 8) uiStep = 8; - - if (!pstHandle->apStorage) - apNewStorage = (void **)HeapAlloc(pstHandle->hHeap, 0, sizeof(void *)*uiStep); - else - apNewStorage = (void **)HeapReAlloc (pstHandle->hHeap, 0, pstHandle->apStorage, sizeof(void *)*uiStep); - if (!apNewStorage) - { - LeaveCriticalSection (&pstHandle->cs); - return FALSE; - } - pstHandle->apStorage = apNewStorage; - pstHandle->uiCapacity = uiStep; - } - - if (uiPosuiCount) - MoveMemory (&pstHandle->apStorage[uiPos+1], &pstHandle->apStorage[uiPos], (pstHandle->uiCount-uiPos)*sizeof(void*)); - pstHandle->apStorage[uiPos] = pItem; - pstHandle->uiCount++; - LeaveCriticalSection (&pstHandle->cs); - return TRUE; -} - -void *List_RemoveElementAt(TYP_LIST *pstHandle, unsigned int uiPos) -{ - void *pRet; - - EnterCriticalSection (&pstHandle->cs); - pRet = pstHandle->apStorage[uiPos]; - if (uiPosuiCount) - MoveMemory (&pstHandle->apStorage[uiPos], &pstHandle->apStorage[uiPos+1], (pstHandle->uiCount-uiPos)*sizeof(void*)); - pstHandle->uiCount--; - LeaveCriticalSection (&pstHandle->cs); - return pRet; -} - -unsigned int List_Count(TYP_LIST *pstHandle) -{ - return pstHandle->uiCount; -} - -void *List_ElementAt(TYP_LIST *pstHandle,unsigned int uiPos) -{ - void *pRet = NULL; - - EnterCriticalSection (&pstHandle->cs); - if (uiPos < pstHandle->uiCount) - pRet = pstHandle->apStorage[uiPos]; - LeaveCriticalSection (&pstHandle->cs); - return pRet; -} - -void *List_Top(TYP_LIST *pstHandle) -{ - if (pstHandle->uiCount) - return List_ElementAt (pstHandle, pstHandle->uiCount-1); - else return NULL; -} - -#ifdef _INC_STDLIB -void List_Sort(TYP_LIST *pstHandle, int (*pFunc)(const void*,const void*)) -{ - EnterCriticalSection (&pstHandle->cs); - qsort(pstHandle->apStorage,pstHandle->uiCount,sizeof(void *),pFunc); - LeaveCriticalSection (&pstHandle->cs); -} -#endif - - -void List_FreeElements(TYP_LIST *pstHandle) -{ - void *pEntry; - HANDLE hHeap = GetProcessHeap(); - - while (pEntry = List_Pop(pstHandle)) - HeapFree (hHeap, 0, pEntry); -} - -BOOL List_BinarySearch(TYP_LIST *hPList, - int (*pPFunc)(const void *pstPElement,const void *pstPToFind), - const void *pstPToFind,int *piPToInsert) -{ - unsigned int - iStart, - iEnd, - iInd; - int iRetCompare; - - if (hPList == NULL) - { - *piPToInsert = 0; - return FALSE; - } - - iStart = 0; - if (hPList->uiCount == 0) - { - *piPToInsert = 0; - return FALSE; - } - EnterCriticalSection (&hPList->cs); - iEnd = hPList->uiCount-1; - - iRetCompare = (*pPFunc)(hPList->apStorage[0],pstPToFind); - if (iRetCompare >= 0) - { - *piPToInsert = 0; - LeaveCriticalSection (&hPList->cs); - return iRetCompare == 0; - } - - iRetCompare = (*pPFunc)(hPList->apStorage[iEnd],pstPToFind); - if (iRetCompare < 0) - { - *piPToInsert = hPList->uiCount; - LeaveCriticalSection (&hPList->cs); - return FALSE; - } - else if (iRetCompare == 0) - { - *piPToInsert = hPList->uiCount-1; - LeaveCriticalSection (&hPList->cs); - return TRUE; - } - - // Otherwise C4702: unreachable code below - #pragma warning (suppress: 4127) // conditional expression is constant - while(1) - { - switch (iEnd-iStart) - { - case 0: - *piPToInsert = iStart; - LeaveCriticalSection (&hPList->cs); - return FALSE; - case 1: - *piPToInsert = iStart+1; - LeaveCriticalSection (&hPList->cs); - return FALSE; - default: - iInd = iStart + (iEnd-iStart)/2; - iRetCompare = (*pPFunc)(hPList->apStorage[iInd],pstPToFind); - if (iRetCompare == 0) - { - *piPToInsert = iInd; - LeaveCriticalSection (&hPList->cs); - return TRUE; - } - if (iRetCompare < 0) - iStart = iInd; - else - iEnd = iInd; - break; - } - } - - LeaveCriticalSection (&hPList->cs); - return FALSE; -} - -BOOL List_InsertSort(TYP_LIST *hPList, - int (*pPFunc)(const void *pstPElement,const void *pstPToFind), - void *pItem) -{ - int iListInd; - - if (!List_BinarySearch(hPList,pPFunc,(void *)pItem,&iListInd)) - { - return List_InsertElementAt (hPList, pItem, iListInd); - } - return FALSE; -} - - diff --git a/protocols/SkypeClassic/src/memlist.cpp b/protocols/SkypeClassic/src/memlist.cpp new file mode 100644 index 0000000000..b14133ef57 --- /dev/null +++ b/protocols/SkypeClassic/src/memlist.cpp @@ -0,0 +1,248 @@ +// The omnipresent memory list, WIN32 implementation, thread safe +#define WIN32_LEAN_AND_MEAN +#include +#include "memlist.h" + +#pragma warning (disable: 4706) // assignment within conditional expression + +struct _tagLIST +{ + unsigned int uiCount; + unsigned int uiCapacity; + void **apStorage; + HANDLE hHeap; + CRITICAL_SECTION cs; +}; + + +TYP_LIST *List_Init(unsigned int uiCapacity) +{ + HANDLE hHeap = GetProcessHeap(); + TYP_LIST *pstHandle; + + pstHandle = (TYP_LIST *)HeapAlloc(hHeap, 0, sizeof(TYP_LIST)); + if (!pstHandle) return NULL; + pstHandle->uiCount = 0; + pstHandle->uiCapacity = uiCapacity; + if (uiCapacity == 0) + pstHandle->apStorage = NULL; + else + { + pstHandle->apStorage = (void **)HeapAlloc(hHeap, 0, sizeof(void *)*uiCapacity); + if (!pstHandle->apStorage) + { + HeapFree (hHeap, 0, pstHandle); + return NULL; + } + } + pstHandle->hHeap = hHeap; + InitializeCriticalSection (&pstHandle->cs); + return pstHandle; +} + +void List_Exit(TYP_LIST *pstHandle) +{ + if (pstHandle->apStorage) + HeapFree (pstHandle->hHeap, 0, pstHandle->apStorage); + DeleteCriticalSection (&pstHandle->cs); + HeapFree (pstHandle->hHeap, 0, pstHandle); +} + +BOOL List_Push(TYP_LIST *pstHandle, void *pItem) +{ + return List_InsertElementAt(pstHandle, pItem,pstHandle->uiCount); +} + +void *List_Pop (TYP_LIST *pstHandle) +{ + if (pstHandle->uiCount) + return List_RemoveElementAt(pstHandle ,pstHandle->uiCount-1); + else return NULL; +} + +BOOL List_InsertElementAt(TYP_LIST *pstHandle, void *pItem, unsigned int uiPos) +{ + unsigned int uiStep; + void **apNewStorage; + + EnterCriticalSection (&pstHandle->cs); + if (uiPos > pstHandle->uiCount) + uiPos = pstHandle->uiCount; + + if (pstHandle->uiCount >= pstHandle->uiCapacity) + { + uiStep = pstHandle->uiCount*2; + if (uiStep < 8) uiStep = 8; + + if (!pstHandle->apStorage) + apNewStorage = (void **)HeapAlloc(pstHandle->hHeap, 0, sizeof(void *)*uiStep); + else + apNewStorage = (void **)HeapReAlloc (pstHandle->hHeap, 0, pstHandle->apStorage, sizeof(void *)*uiStep); + if (!apNewStorage) + { + LeaveCriticalSection (&pstHandle->cs); + return FALSE; + } + pstHandle->apStorage = apNewStorage; + pstHandle->uiCapacity = uiStep; + } + + if (uiPosuiCount) + MoveMemory (&pstHandle->apStorage[uiPos+1], &pstHandle->apStorage[uiPos], (pstHandle->uiCount-uiPos)*sizeof(void*)); + pstHandle->apStorage[uiPos] = pItem; + pstHandle->uiCount++; + LeaveCriticalSection (&pstHandle->cs); + return TRUE; +} + +void *List_RemoveElementAt(TYP_LIST *pstHandle, unsigned int uiPos) +{ + void *pRet; + + EnterCriticalSection (&pstHandle->cs); + pRet = pstHandle->apStorage[uiPos]; + if (uiPosuiCount) + MoveMemory (&pstHandle->apStorage[uiPos], &pstHandle->apStorage[uiPos+1], (pstHandle->uiCount-uiPos)*sizeof(void*)); + pstHandle->uiCount--; + LeaveCriticalSection (&pstHandle->cs); + return pRet; +} + +unsigned int List_Count(TYP_LIST *pstHandle) +{ + return pstHandle->uiCount; +} + +void *List_ElementAt(TYP_LIST *pstHandle,unsigned int uiPos) +{ + void *pRet = NULL; + + EnterCriticalSection (&pstHandle->cs); + if (uiPos < pstHandle->uiCount) + pRet = pstHandle->apStorage[uiPos]; + LeaveCriticalSection (&pstHandle->cs); + return pRet; +} + +void *List_Top(TYP_LIST *pstHandle) +{ + if (pstHandle->uiCount) + return List_ElementAt (pstHandle, pstHandle->uiCount-1); + else return NULL; +} + +#ifdef _INC_STDLIB +void List_Sort(TYP_LIST *pstHandle, int (*pFunc)(const void*,const void*)) +{ + EnterCriticalSection (&pstHandle->cs); + qsort(pstHandle->apStorage,pstHandle->uiCount,sizeof(void *),pFunc); + LeaveCriticalSection (&pstHandle->cs); +} +#endif + + +void List_FreeElements(TYP_LIST *pstHandle) +{ + void *pEntry; + HANDLE hHeap = GetProcessHeap(); + + while (pEntry = List_Pop(pstHandle)) + HeapFree (hHeap, 0, pEntry); +} + +BOOL List_BinarySearch(TYP_LIST *hPList, + int (*pPFunc)(const void *pstPElement,const void *pstPToFind), + const void *pstPToFind,int *piPToInsert) +{ + unsigned int + iStart, + iEnd, + iInd; + int iRetCompare; + + if (hPList == NULL) + { + *piPToInsert = 0; + return FALSE; + } + + iStart = 0; + if (hPList->uiCount == 0) + { + *piPToInsert = 0; + return FALSE; + } + EnterCriticalSection (&hPList->cs); + iEnd = hPList->uiCount-1; + + iRetCompare = (*pPFunc)(hPList->apStorage[0],pstPToFind); + if (iRetCompare >= 0) + { + *piPToInsert = 0; + LeaveCriticalSection (&hPList->cs); + return iRetCompare == 0; + } + + iRetCompare = (*pPFunc)(hPList->apStorage[iEnd],pstPToFind); + if (iRetCompare < 0) + { + *piPToInsert = hPList->uiCount; + LeaveCriticalSection (&hPList->cs); + return FALSE; + } + else if (iRetCompare == 0) + { + *piPToInsert = hPList->uiCount-1; + LeaveCriticalSection (&hPList->cs); + return TRUE; + } + + // Otherwise C4702: unreachable code below + #pragma warning (suppress: 4127) // conditional expression is constant + while(1) + { + switch (iEnd-iStart) + { + case 0: + *piPToInsert = iStart; + LeaveCriticalSection (&hPList->cs); + return FALSE; + case 1: + *piPToInsert = iStart+1; + LeaveCriticalSection (&hPList->cs); + return FALSE; + default: + iInd = iStart + (iEnd-iStart)/2; + iRetCompare = (*pPFunc)(hPList->apStorage[iInd],pstPToFind); + if (iRetCompare == 0) + { + *piPToInsert = iInd; + LeaveCriticalSection (&hPList->cs); + return TRUE; + } + if (iRetCompare < 0) + iStart = iInd; + else + iEnd = iInd; + break; + } + } + + LeaveCriticalSection (&hPList->cs); + return FALSE; +} + +BOOL List_InsertSort(TYP_LIST *hPList, + int (*pPFunc)(const void *pstPElement,const void *pstPToFind), + void *pItem) +{ + int iListInd; + + if (!List_BinarySearch(hPList,pPFunc,(void *)pItem,&iListInd)) + { + return List_InsertElementAt (hPList, pItem, iListInd); + } + return FALSE; +} + + diff --git a/protocols/SkypeClassic/src/msglist.c b/protocols/SkypeClassic/src/msglist.c deleted file mode 100644 index aedb4d1257..0000000000 --- a/protocols/SkypeClassic/src/msglist.c +++ /dev/null @@ -1,86 +0,0 @@ -#define WIN32_LEAN_AND_MEAN -#include -#include "memlist.h" -#include "debug.h" -#include "msglist.h" - -#define MSGLIST_TIMEOUT 1800 // Chatmessage references will be kept for 30 minutes - -static TYP_LIST *m_hMsgList = NULL; - -static int CmpProc(const void *pstPElement,const void *pstPToFind) -{ - return (DWORD)pstPToFind - ((TYP_MSGLENTRY*)pstPElement)->uMsgNum; -} - -void MsgList_Init(void) -{ - m_hMsgList = List_Init(128); -} - -void MsgList_Exit(void) -{ - if (!m_hMsgList) return; - List_FreeElements (m_hMsgList); - List_Exit(m_hMsgList); - m_hMsgList = NULL; -} - -TYP_MSGLENTRY *MsgList_Add(DWORD uMsgNum, HANDLE hEvent) -{ - TYP_MSGLENTRY *pEntry; - int iListInd; - BOOL bFound; - - LOG (("MsgList_Add (%d, %08X)", uMsgNum, hEvent)); - if (!m_hMsgList || !hEvent) return FALSE; - bFound = List_BinarySearch(m_hMsgList,CmpProc,(void *)uMsgNum,&iListInd); - if (!bFound) pEntry = (TYP_MSGLENTRY*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TYP_MSGLENTRY)); - else pEntry = (TYP_MSGLENTRY*)List_ElementAt (m_hMsgList, iListInd); - if (!pEntry) return NULL; - pEntry->uMsgNum = uMsgNum; - pEntry->hEvent = hEvent; - pEntry->tEdited = 0; - time(&pEntry->t); - if (!bFound) return List_InsertElementAt (m_hMsgList, pEntry, iListInd)?pEntry:NULL; - return pEntry; -} - - -TYP_MSGLENTRY *MsgList_FindMessage(DWORD uMsgNum) -{ - TYP_MSGLENTRY *pEntry; - int iPos; - - LOG (("MsgList_FindEvent (%d)", uMsgNum)); - if (m_hMsgList && List_BinarySearch(m_hMsgList, CmpProc, (void*)uMsgNum, &iPos)) - { - pEntry = (TYP_MSGLENTRY*)List_ElementAt (m_hMsgList, iPos); - time(&pEntry->t); // Touch it, so that it doesn't get thrown away too soon - LOG (("MsgList_FindEvent(%d): %08X", uMsgNum, pEntry->hEvent)); - return pEntry; - } - return NULL; -} - -void MsgList_CollectGarbage(void) -{ - unsigned int i; - TYP_MSGLENTRY *pEntry; - time_t t; - - if (!m_hMsgList) return; - time(&t); - t-=MSGLIST_TIMEOUT; - for (i=0; it < t) - { - LOG (("MsgList_CollectGarbage throwing out msg %d", pEntry->uMsgNum)); - HeapFree (GetProcessHeap(), 0, List_RemoveElementAt (m_hMsgList, i)); - i--; - } - } -} - diff --git a/protocols/SkypeClassic/src/msglist.cpp b/protocols/SkypeClassic/src/msglist.cpp new file mode 100644 index 0000000000..aedb4d1257 --- /dev/null +++ b/protocols/SkypeClassic/src/msglist.cpp @@ -0,0 +1,86 @@ +#define WIN32_LEAN_AND_MEAN +#include +#include "memlist.h" +#include "debug.h" +#include "msglist.h" + +#define MSGLIST_TIMEOUT 1800 // Chatmessage references will be kept for 30 minutes + +static TYP_LIST *m_hMsgList = NULL; + +static int CmpProc(const void *pstPElement,const void *pstPToFind) +{ + return (DWORD)pstPToFind - ((TYP_MSGLENTRY*)pstPElement)->uMsgNum; +} + +void MsgList_Init(void) +{ + m_hMsgList = List_Init(128); +} + +void MsgList_Exit(void) +{ + if (!m_hMsgList) return; + List_FreeElements (m_hMsgList); + List_Exit(m_hMsgList); + m_hMsgList = NULL; +} + +TYP_MSGLENTRY *MsgList_Add(DWORD uMsgNum, HANDLE hEvent) +{ + TYP_MSGLENTRY *pEntry; + int iListInd; + BOOL bFound; + + LOG (("MsgList_Add (%d, %08X)", uMsgNum, hEvent)); + if (!m_hMsgList || !hEvent) return FALSE; + bFound = List_BinarySearch(m_hMsgList,CmpProc,(void *)uMsgNum,&iListInd); + if (!bFound) pEntry = (TYP_MSGLENTRY*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TYP_MSGLENTRY)); + else pEntry = (TYP_MSGLENTRY*)List_ElementAt (m_hMsgList, iListInd); + if (!pEntry) return NULL; + pEntry->uMsgNum = uMsgNum; + pEntry->hEvent = hEvent; + pEntry->tEdited = 0; + time(&pEntry->t); + if (!bFound) return List_InsertElementAt (m_hMsgList, pEntry, iListInd)?pEntry:NULL; + return pEntry; +} + + +TYP_MSGLENTRY *MsgList_FindMessage(DWORD uMsgNum) +{ + TYP_MSGLENTRY *pEntry; + int iPos; + + LOG (("MsgList_FindEvent (%d)", uMsgNum)); + if (m_hMsgList && List_BinarySearch(m_hMsgList, CmpProc, (void*)uMsgNum, &iPos)) + { + pEntry = (TYP_MSGLENTRY*)List_ElementAt (m_hMsgList, iPos); + time(&pEntry->t); // Touch it, so that it doesn't get thrown away too soon + LOG (("MsgList_FindEvent(%d): %08X", uMsgNum, pEntry->hEvent)); + return pEntry; + } + return NULL; +} + +void MsgList_CollectGarbage(void) +{ + unsigned int i; + TYP_MSGLENTRY *pEntry; + time_t t; + + if (!m_hMsgList) return; + time(&t); + t-=MSGLIST_TIMEOUT; + for (i=0; it < t) + { + LOG (("MsgList_CollectGarbage throwing out msg %d", pEntry->uMsgNum)); + HeapFree (GetProcessHeap(), 0, List_RemoveElementAt (m_hMsgList, i)); + i--; + } + } +} + diff --git a/protocols/SkypeClassic/src/msgq.c b/protocols/SkypeClassic/src/msgq.c deleted file mode 100644 index e1ab0d1998..0000000000 --- a/protocols/SkypeClassic/src/msgq.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Implements a simple message queue for send and receive queue. - * We could use memlist.c, but it's not efficient - * enough for this purpose (would always memmove on removing first - * element), therefore it's implemented as tail queue. - */ - -#include "skype.h" -#include "msgq.h" -#include "debug.h" - - -void MsgQ_Init(TYP_MSGQ *q) -{ - TAILQ_INIT(&q->l); - InitializeCriticalSection (&q->cs); -} - -void MsgQ_Exit(TYP_MSGQ *q) -{ - struct MsgQueue *ptr; - - EnterCriticalSection(&q->cs); - while ((ptr=q->l.tqh_first) != NULL) - free(MsgQ_RemoveMsg(q, ptr)); - LeaveCriticalSection(&q->cs); - DeleteCriticalSection (&q->cs); -} - -BOOL MsgQ_Add(TYP_MSGQ *q, char *msg) -{ - struct MsgQueue *ptr; - - if ((ptr=(struct MsgQueue*)malloc(sizeof(struct MsgQueue))) == NULL) - return FALSE; - ptr->message = _strdup(msg); // Don't forget to free! - ptr->tAdded = SkypeTime(NULL); - SkypeTime(&ptr->tReceived); - EnterCriticalSection(&q->cs); - TAILQ_INSERT_TAIL(&q->l, ptr, l); - //LOG (("MsgQ_Add (%s) @%lu/%ld", msg, ptr->tReceived, ptr->tAdded)); - LeaveCriticalSection(&q->cs); - return TRUE; -} - -char *MsgQ_RemoveMsg(TYP_MSGQ *q, struct MsgQueue *ptr) -{ - char *msg; - - if (!ptr) return NULL; - EnterCriticalSection(&q->cs); - TAILQ_REMOVE(&q->l, ptr, l); - LeaveCriticalSection(&q->cs); - msg=ptr->message; - free(ptr); - return msg; -} - -char *MsgQ_Get(TYP_MSGQ *q) -{ - char *msg; - - msg=MsgQ_RemoveMsg(q, q->l.tqh_first); - return msg; -} - -int MsgQ_CollectGarbage(TYP_MSGQ *q, time_t age) -{ - struct MsgQueue *ptr; - int i=0; - - EnterCriticalSection(&q->cs); - ptr=q->l.tqh_first; - while (ptr) - { - if (ptr->tAdded && SkypeTime(NULL)-ptr->tAdded>age) - { - struct MsgQueue *ptr_; - LOG(("GarbageCollector throwing out message: %s", ptr->message)); - ptr_=ptr; - ptr=ptr->l.tqe_next; - free(MsgQ_RemoveMsg(q, ptr_)); - i++; - continue; - } - ptr=ptr->l.tqe_next; - } - LeaveCriticalSection(&q->cs); - return i; -} diff --git a/protocols/SkypeClassic/src/msgq.cpp b/protocols/SkypeClassic/src/msgq.cpp new file mode 100644 index 0000000000..e1ab0d1998 --- /dev/null +++ b/protocols/SkypeClassic/src/msgq.cpp @@ -0,0 +1,90 @@ +/* + * Implements a simple message queue for send and receive queue. + * We could use memlist.c, but it's not efficient + * enough for this purpose (would always memmove on removing first + * element), therefore it's implemented as tail queue. + */ + +#include "skype.h" +#include "msgq.h" +#include "debug.h" + + +void MsgQ_Init(TYP_MSGQ *q) +{ + TAILQ_INIT(&q->l); + InitializeCriticalSection (&q->cs); +} + +void MsgQ_Exit(TYP_MSGQ *q) +{ + struct MsgQueue *ptr; + + EnterCriticalSection(&q->cs); + while ((ptr=q->l.tqh_first) != NULL) + free(MsgQ_RemoveMsg(q, ptr)); + LeaveCriticalSection(&q->cs); + DeleteCriticalSection (&q->cs); +} + +BOOL MsgQ_Add(TYP_MSGQ *q, char *msg) +{ + struct MsgQueue *ptr; + + if ((ptr=(struct MsgQueue*)malloc(sizeof(struct MsgQueue))) == NULL) + return FALSE; + ptr->message = _strdup(msg); // Don't forget to free! + ptr->tAdded = SkypeTime(NULL); + SkypeTime(&ptr->tReceived); + EnterCriticalSection(&q->cs); + TAILQ_INSERT_TAIL(&q->l, ptr, l); + //LOG (("MsgQ_Add (%s) @%lu/%ld", msg, ptr->tReceived, ptr->tAdded)); + LeaveCriticalSection(&q->cs); + return TRUE; +} + +char *MsgQ_RemoveMsg(TYP_MSGQ *q, struct MsgQueue *ptr) +{ + char *msg; + + if (!ptr) return NULL; + EnterCriticalSection(&q->cs); + TAILQ_REMOVE(&q->l, ptr, l); + LeaveCriticalSection(&q->cs); + msg=ptr->message; + free(ptr); + return msg; +} + +char *MsgQ_Get(TYP_MSGQ *q) +{ + char *msg; + + msg=MsgQ_RemoveMsg(q, q->l.tqh_first); + return msg; +} + +int MsgQ_CollectGarbage(TYP_MSGQ *q, time_t age) +{ + struct MsgQueue *ptr; + int i=0; + + EnterCriticalSection(&q->cs); + ptr=q->l.tqh_first; + while (ptr) + { + if (ptr->tAdded && SkypeTime(NULL)-ptr->tAdded>age) + { + struct MsgQueue *ptr_; + LOG(("GarbageCollector throwing out message: %s", ptr->message)); + ptr_=ptr; + ptr=ptr->l.tqe_next; + free(MsgQ_RemoveMsg(q, ptr_)); + i++; + continue; + } + ptr=ptr->l.tqe_next; + } + LeaveCriticalSection(&q->cs); + return i; +} diff --git a/protocols/SkypeClassic/src/ng-compat/m_core.h b/protocols/SkypeClassic/src/ng-compat/m_core.h deleted file mode 100644 index f96fd5bc83..0000000000 --- a/protocols/SkypeClassic/src/ng-compat/m_core.h +++ /dev/null @@ -1,52 +0,0 @@ -#define IS_MIRANDAIM - -typedef HANDLE MCONTACT; - -#define db_get_ws DBGetContactSettingWString -#define db_free DBFreeVariant -#define db_get_b DBGetContactSettingByte -#define db_get_s DBGetContactSettingString -#define db_get_ts DBGetContactSettingTString -#define db_set_s DBWriteContactSettingString -#define db_set_b DBWriteContactSettingByte -#define db_get_w DBGetContactSettingWord -#define db_set_w DBWriteContactSettingWord -#define db_set_ts DBWriteContactSettingTString -#define db_get_dw DBGetContactSettingDword -#define db_set_dw DBWriteContactSettingDword -#define db_set_utf SkypeDBWriteContactSettingUTF8String -#define db_set_ws DBWriteContactSettingWString - - -#define Menu_AddContactMenuItem(mi) (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)mi) -#define Menu_AddMainMenuItem(mi) (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM, (WPARAM)NULL,(LPARAM)mi) - -#define db_find_first() (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0) -#define db_find_next(hContact) (HANDLE)CallService( MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0) -#define db_event_getContact(hContact) (HANDLE)CallService (MS_DB_EVENT_GETCONTACT, (WPARAM)hContact, 0) -#define db_event_delete(hContact,hEvent) CallService (MS_DB_EVENT_DELETE, (WPARAM)hContact, (LPARAM)hEvent) -#define db_event_first(hContact) (HANDLE)CallService(MS_DB_EVENT_FINDFIRST,(WPARAM)hContact,0) -#define db_event_get(hDbEvent,dbei) CallService(MS_DB_EVENT_GET,(WPARAM)hDbEvent,(LPARAM)dbei) -#define db_event_last(hContact) (HANDLE)CallService(MS_DB_EVENT_FINDLAST,(WPARAM)hContact,0) -#define db_event_add(hContact,dbei) (HANDLE)CallServiceSync(MS_DB_EVENT_ADD, (WPARAM)(HANDLE)hContact, (LPARAM)dbei) -#define db_event_firstUnread(hContact) (HANDLE)CallService(MS_DB_EVENT_FINDFIRSTUNREAD,(WPARAM)hContact,0) -#define db_event_markRead(hContact,hDbEvent) CallService(MS_DB_EVENT_MARKREAD,(WPARAM)hContact,(LPARAM)hDbEvent) -#define db_event_getBlobSize(hEvent) CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hEvent, 0) -#define db_mc_isSub(hContact) DBGetContactSettingByte(hContact, "MetaContacts", "IsSubcontact", 0) -#define db_event_next(hContact,hDbEvent) (HANDLE)CallService(MS_DB_EVENT_FINDNEXT,(WPARAM)hDbEvent,0) - -#define Thread_Push(a,b) CallService(MS_SYSTEM_THREAD_PUSH, a, b) -#define Thread_Pop() CallService(MS_SYSTEM_THREAD_POP, 0, 0); - -#define GetContactProto(hContact) (char*)CallService( MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0 ) - -#define Options_AddPage(h,odp) CallService(MS_OPT_ADDPAGE, h, (LPARAM)odp); -#define UserInfo_AddPage(h,odp) CallService(MS_USERINFO_ADDPAGE, h, (LPARAM)odp); - -#define _A2T(x) x -#define _T2A(x) x -#define SIZEOF(x) sizeof(x)/sizeof(x[0]) -#define GSMDF_TCHAR GCMDF_TCHAR - -// Write contact setting as UTF-8 for convenience, if possible. Older Miranda IM versions will store it as ANSI -INT_PTR SkypeDBWriteContactSettingUTF8String(HANDLE hContact,const char *szModule,const char *szSetting,const char *val); diff --git a/protocols/SkypeClassic/src/ng-compat/stdver.h b/protocols/SkypeClassic/src/ng-compat/stdver.h deleted file mode 100644 index 6f40f9e4bd..0000000000 --- a/protocols/SkypeClassic/src/ng-compat/stdver.h +++ /dev/null @@ -1,9 +0,0 @@ -#define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM -#define __FILEVERSION_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM - -#define __STRINGIFY_IMPL(x) #x -#define __STRINGIFY(x) __STRINGIFY_IMPL(x) - -#define __VERSION_DWORD PLUGIN_MAKE_VERSION(__MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM) -#define __VERSION_STRING __STRINGIFY(__FILEVERSION_STRING) -#define __VERSION_STRING_DOTS __STRINGIFY(__FILEVERSION_DOTS) diff --git a/protocols/SkypeClassic/src/pthread.c b/protocols/SkypeClassic/src/pthread.c deleted file mode 100644 index 12da5a7a4f..0000000000 --- a/protocols/SkypeClassic/src/pthread.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * $Id: pthread.c,v 1.4 2003/12/19 12:53:36 gena01 Exp $ - * - * Skype Miranda Plugin - * - * Authors: Gennady Feldman (aka Gena01) - * Laurent Marechal (aka Peorth) - * - * Code borrowed for Skype plugin. Fixed to compile on Mingw by G.Feldman - * Original Copyright (c) 2003 Robert Rainwater - * - * This code is under GPL and is based on AIM, MSN and Miranda source code. - * I want to thank Robert Rainwater and George Hazan for their code and support - * and for answering some of my questions during development of this plugin. - */ - -#include "skype.h" - -/* Gena01 - added some defined to fix compilation with mingw gcc */ -/* __try/__finally taken from abiword patch found on the web */ -#if 0 - #include -#else -#define __try -#define __except(x) if (0) /* don't execute handler */ -#define __finally - -#define _try __try -#define _except __except -#define _finally __finally -#endif - -#include - -struct pthread_arg -{ - HANDLE hEvent; - void (*threadcode) (void *); - void *arg; -}; - -void pthread_r(struct pthread_arg *fa) -{ - void (*callercode) (void *) = fa->threadcode; - void *arg = fa->arg; - Thread_Push(0, 0); - SetEvent(fa->hEvent); - __try { - callercode(arg); - } - __finally { - Thread_Pop(); - } -} - -unsigned long pthread_create(pThreadFunc parFunc, void *arg) -{ - unsigned long rc; - struct pthread_arg fa; - fa.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - fa.threadcode = parFunc; - fa.arg = arg; - rc = _beginthread((pThreadFunc) pthread_r, 0, &fa); - if ((unsigned long) -1L != rc) { - WaitForSingleObject(fa.hEvent, INFINITE); - } - CloseHandle(fa.hEvent); - return rc; -} - diff --git a/protocols/SkypeClassic/src/pthread.cpp b/protocols/SkypeClassic/src/pthread.cpp new file mode 100644 index 0000000000..12da5a7a4f --- /dev/null +++ b/protocols/SkypeClassic/src/pthread.cpp @@ -0,0 +1,70 @@ +/* + * $Id: pthread.c,v 1.4 2003/12/19 12:53:36 gena01 Exp $ + * + * Skype Miranda Plugin + * + * Authors: Gennady Feldman (aka Gena01) + * Laurent Marechal (aka Peorth) + * + * Code borrowed for Skype plugin. Fixed to compile on Mingw by G.Feldman + * Original Copyright (c) 2003 Robert Rainwater + * + * This code is under GPL and is based on AIM, MSN and Miranda source code. + * I want to thank Robert Rainwater and George Hazan for their code and support + * and for answering some of my questions during development of this plugin. + */ + +#include "skype.h" + +/* Gena01 - added some defined to fix compilation with mingw gcc */ +/* __try/__finally taken from abiword patch found on the web */ +#if 0 + #include +#else +#define __try +#define __except(x) if (0) /* don't execute handler */ +#define __finally + +#define _try __try +#define _except __except +#define _finally __finally +#endif + +#include + +struct pthread_arg +{ + HANDLE hEvent; + void (*threadcode) (void *); + void *arg; +}; + +void pthread_r(struct pthread_arg *fa) +{ + void (*callercode) (void *) = fa->threadcode; + void *arg = fa->arg; + Thread_Push(0, 0); + SetEvent(fa->hEvent); + __try { + callercode(arg); + } + __finally { + Thread_Pop(); + } +} + +unsigned long pthread_create(pThreadFunc parFunc, void *arg) +{ + unsigned long rc; + struct pthread_arg fa; + fa.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + fa.threadcode = parFunc; + fa.arg = arg; + rc = _beginthread((pThreadFunc) pthread_r, 0, &fa); + if ((unsigned long) -1L != rc) { + WaitForSingleObject(fa.hEvent, INFINITE); + } + CloseHandle(fa.hEvent); + return rc; +} + diff --git a/protocols/SkypeClassic/src/sdk/m_chat.h b/protocols/SkypeClassic/src/sdk/m_chat.h deleted file mode 100644 index ae034350be..0000000000 --- a/protocols/SkypeClassic/src/sdk/m_chat.h +++ /dev/null @@ -1,635 +0,0 @@ -/* -Chat module plugin for Miranda IM - -Copyright (C) 2003 Jörgen Persson - -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. -*/ - - - -/* - This plugin provides event driven chat rooms for protocols that wish to use it. - It is built for IRC, which I also develop and is naturally biased towards IRC, - but it should work very well with other protocols too. I will try to explain as - careful as possible in this document how to use chat.dll - - -- General guidelines -- - - There is ONE rule a protocol MUST follow to use this: - - 1. Do NOT touch hContacts that has a byte "ChatRoom" set to ANYTHING other than 0! (Could be 1, 2, 3, ...) - This is because chat.dll adds contacts to the clist using the protocol name - supplied by the protocol. But this will naturally not work well if the - protocol also tampers with the contacts. The value of the BYTE indicates which type of - window/contact it is (see the GCW_* flags below). There is two exceptions to this rule: - - * You should continue to handle the right click menu items of these - contacts as usual, by hooking the menu prebuild hook etc. Chat.dll can not - handle this in an efficient manner! - - * You should also handle when the user deletes the contact/room from the - contact list, as the protocol will then most likely have to send some message - to the server that the user has left the room. - - NOTE. Chat keeps its own copies of strings passed. - - - * * Example of implementing this rule * *: - * * This is a code snippet that is common in protocols * *: - - - - hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); - while (hContact) - { - szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); - if (szProto != NULL && !lstrcmpi(szProto, PROTONAME)) - { - ... do something with the hContact here; - } - hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); - } - - - - * * You should do this instead * *: - - - - hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); - while (hContact) - { - szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); - if (szProto != NULL && !lstrcmpi(szProto, PROTONAME)) - { - if (DBGetContactSettingByte(hContact, PROTONAME, "ChatRoom", 0) == 0) - { - ... do something with the hContact here; - } - } - hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); - } - - - There is not more to it than that! To recapitulate: do NOT touch contacts where the - BYTE "ChatRoom" is set to anything other than 0, - - - - - - - OK, enough of the precautions, HOW DO YOU USE CHAT? In short you need to do FOUR things: - - 1. REGISTER your protocol with Chat - Only registered protocols can use Chat - - 2. CREATE SESSIONS when your protocol are joining a group chat room. (One per room joined) - These sessions will be put on the contact-list and are managed totally by chat. - This is the reason you must obey to the "precautions" I mentioned above. - Do not tamper directly with Chat's hContacts. Use Services provided by Chat instead. - - 3. SEND EVENTS to the sessions created in #3. - These events reflect users joining/leaving/speaking etc. - - 4. DESTROY SESSIONS when the user leaves the room (ie the session is not needed anymore). - - These four points are implemented in three services: MS_GC_REGISTER, MS_GC_NEWSESSION - and MS_GC_EVENT. -*/ - - -//------------------------- SERVICES ------------------------ -/* - Step 1. -- REGISTER with Chat -- - - The first thing that a protocol need to do is register with Chat. This is best done - when ALL modules has loaded (ME_SYSTEM_MODULESLOADED). The registration is - needed to make sure that the protocol obey rule 1 mentioned above, but also to - set protocol specific preferences. - - * Use MS_GC_REGISTER like this: CallService(MS_GC_REGISTER, 0, (LPARAM)(GCREGISTER *) &gcr; - - * returns 0 on success or error code on failure. -*/ - -// Flags -#define GC_BOLD 0x0001 // enable the 'bold' button -#define GC_ITALICS 0x0002 // enable the 'italics' button -#define GC_UNDERLINE 0x0004 // enable the 'underline' button -#define GC_COLOR 0x0008 // enable the 'foreground color' button -#define GC_BKGCOLOR 0x0010 // enable the 'background color' button -#define GC_ACKMSG 0x0020 // the protocol must acknowlege messages sent -#define GC_TYPNOTIF 0x0040 // enable typing notifications. -#define GC_CHANMGR 0x0080 // enable the 'channel settings' button -#define GC_SINGLEFORMAT 0x0100 // the protocol supports only 1 formatting per message -#define GC_FONTSIZE 0x0200 // enable font size selection - -// Error messages -#define GC_REGISTER_WRONGVER 1 // You appear to be using the wrong version of this API. Registration failed. -#define GC_REGISTER_ERROR 2 // An internal error occurred. Registration failed. -#define GC_REGISTER_NOUNICODE 3 // MS_GC_REGISTER returns this error if the Unicode version of chat - // is not installed and GC_UNICODE is set. Registration failed - -// GCREGISTER struct -struct GCREGISTER -{ - int cbSize; // Set to sizeof(GCREGISTER); - DWORD dwFlags; // Use GC_* flags above to indicate features supported - LPCSTR pszModule; // This MUST be the protocol name as registered with Miranda IM - LPCTSTR ptszDispName; // This is the protocol's real name as it will be displayed to the user - int iMaxText; // Max message length the protocol supports. Will limit the typing area input. 0 = no limit - int nColors; // Number of colors in the colorchooser menu for the color buttons. Max = 100 - COLORREF* pColors; // pointer to the first item in a static COLORREF array containing the colors - // that should be showed in the colorchooser menu. - // ie: COLORREF crCols[nColors]; - // pColors = &crCols[0]; -}; - -#define MS_GC_REGISTER "GChat/Register" - -/* - Step 2. -- CREATE a new SESSION -- - - Create a new session (chat room) and set various settings related to it. - The chat room will not be shown to the user until the 'set up' phase is - completed and SESSION_INITDONE is sent. See the MS_GC_EVENT for that. - - * Use MS_GC_NEWSESSION like this: CallService(MS_GC_NEWSESSION, 0, (LPARAM)(GCSESSION *) &gcr; - - * returns 0 on success or error code on failure -*/ - - -// Session type -#define GCW_CHATROOM 1 // the session is a dedicated multi user chat room. ex "IRC channels". - // A hContact will be added for the session -#define GCW_SERVER 2 // the session is used as a network console. ex "IRC server window" - // A hContact will be added for the session, but it will default to being hidden (on the CList) -#define GCW_PRIVMESS 3 // NOT SUPPORTED YET! the session is a 1 to 1 session, but with additional - // support for adding more users etc. ex "MSN session". - -// Error messages -#define GC_NEWSESSION_WRONGVER 1 // You appear to be using the wrong version of this API. -#define GC_NEWSESSION_ERROR 2 // An internal error occurred. - -// GCSESSION structure -struct GCSESSION -{ - int cbSize; // set to sizeof(GCSESSION); - int iType; // Use one of the GCW_* flags above to set the type of session - LPCSTR pszModule; // The name of the protocol owning the session (the same as pszModule when you register) - LPCTSTR ptszName; // The name of the session as it will be displayed to the user - LPCTSTR ptszID; // The unique identifier for the session. - LPCTSTR ptszStatusbarText; // Optional text to set in the statusbar of the chat room window, or NULL. - DWORD dwFlags; - INT_PTR dwItemData; // Set user defined data for this session. Retrieve it by using the GC_EVENT_GETITEMDATA event -}; - -#define MS_GC_NEWSESSION "GChat/NewChat" - -/* - Step 3 -- SEND an EVENT -- - - Events is what drives Chat! After having created the session in Step 2 - it is time to make it work for real. Follow these guidelines: - - 1. Start off by telling Chat what possible statuses a user can have (in the nicklist) - by sending GC_EVENT_ADDGROUP as many times as needed. Also supply an icon - to go with this status. Ex "Voice status" on IRC - - 2.Then send "JOIN" events (GC_EVENT_JOIN) to populate the user list. - You will need to send one event per user that should be added. As long as - SESSION_INITDONE has not been sent these events will not show up in the log. - - 3.When you are done with filling the user list it is a good time to end - the set up phase and make the window visible by calling GC_EVENT_CONTROL event - with wParam = SESSION_INITDONE. - - 4.You will also want to send a GC_EVENT_CONTROL with wParam = SESSION_ONLINE to - make the statusbar and the CList item go to "online" status - - You have now set up the session and made it active. A CList hContact has been added - to the contact list and a chat room window is associated to the session. Send EVENTS to - Chat users speaking, users joining and so on. See below for full - list of what events are possible. - - IMPORTANT: For sending events you'll use the GCEVENT and GCDEST structures. A GCDEST - structure pointer is passed inside GCEVENT and it tells Chat what event type it is - and what session it is related to. The GCDEST structure and its members are ALWAYS - used (but the members can be NULL in some occasions). Depending on what type of event - you are sending, the members of GCEVENT have different usage. Each event and how to - use the members are discussed below. The "AddToLog" and "time" members are always valid - and always mean the same. bAddToLog = TRUE means that the event is added to the disk log - (at least when this makes sense). This can be used by Jabber for instance, when - it needs to add channel history to the window, but without logging to disk. - The "time" member is the timestamp of the event.(Tip. use the function time(NULL) - to set the current time) - - NOTE. It is possible to send formatted text (bold, italics, underlined, foreground color - and background color) to Chat by using the following identifiers in the text (pszText): - - %cXX - set the foreground color ( XX is the zero based decimal index of the color registered in MS_GC_REGISTER.. Always use two digits ) - %C - reset foreground color to default - %fXX - set the background color ( XX is the zero based decimal index of the color registered in MS_GC_REGISTER.. Always use two digits ) - %F - reset the background color to default - %b - enable bold - %B - disable bold - %u - enable underlined - %U - disable underlined - %i - enable italics - %I - disable italics - %r - reset all to default - %% - escape the formatting. Translates to % - - IMPORTANT. If you have specified GC_COLOR or GC_BKGCOLOR when you registered you can expect to - get these identifiers in the text you receive from Chat as well. Make sure % is ALWAYS - translated to %% in text you send to Chat to avoid accidental formatting. - NOTE. You will not get %cRRRGGGBBB back, instead you will get the index of the colour as - registered with GC_REGISTER. Eg %c3 (the fourth colour of your index) - - * Use MS_GC_EVENT like this: CallService(MS_GC_EVENT, 0, (LPARAM)(GCEVENT *) &gce; - - * returns 0 on success or error code on failure - -*/ - -// * List of possible events to send to Chat. Unlisted members are not valid * -// * for the event. Listed members are mandatory unless otherwise specified * - - -// GC_EVENT_JOIN - " has joined" (A user is joining the session) -// pszNick - Display name -// pszUID - Unique identifier of the user -// pszStatus - Which status does the user have. Should be a status previously -// registered with GC_EVENT_ADDGROUP. Ex "Voice" in IRC -// bIsMe - Set to TRUE if it is the Miranda user -// Chat needs to know which user in the userlist that is "self" -// It cannot highlight a message containing the "own" nick without this info -// NOTE. if time == NULL, then the event will not be shown in the message log -#define GC_EVENT_JOIN 0x0001 - -// GC_EVENT_PART - " has left: " (A user left the session) -// pszNick - Display name -// pszUID - Unique identifier -// pszText - Optional part message, can be NULL -#define GC_EVENT_PART 0x0002 - -// GC_EVENT_QUIT - " disconnected: pszText" (A user disconnected from the network) -// pszID(in GCDEST) - Should be NULL as a disconnect event is global. -// pszNick - Display name -// pszUID - Unique identifier -// pszText - Optional disconnect message, can be NULL -#define GC_EVENT_QUIT 0x0004 - -// GC_EVENT_KICK - " kicked : " (A user is kicking another user from the room) -// pszNick - Display name of the one being being kicked -// pszUID - Unique identifier of the one being kicked -// pszStatus - Name of user who is doing the kicking -// pszText - Optional kick message, can be NULL -#define GC_EVENT_KICK 0x0008 - -// GC_EVENT_NICK - " is now known as " (A user changed his name) -// NOTE, see GC_EVENT_CHUID also -// pszID(in GCDEST) - Should be NULL as a nick change event is global. -// pszNick - Old display name -// pszUID - Unique identifier -// pszText - New display name of the user. Color codes are not valid -#define GC_EVENT_NICK 0x0010 - -// GC_EVENT_NOTICE - "Notice from : " (An IRC type notice) -// pszID(in GCDEST) - Should be NULL to send to the active window -// pszNick - Display name -// pszUID - Unique identifier -// pszText - Notice text -#define GC_EVENT_NOTICE 0x0020 - -// GC_EVENT_MESSAGE - ": (A user is speaking) -// pszNick - Display name -// pszUID - Unique identifier -// bIsMe - Set to TRUE if it is the Miranda user -// pszText - Message text. -#define GC_EVENT_MESSAGE 0x0040 - -// GC_EVENT_TOPIC - "Topic is (Set by: " (The room topic was changed/set) -// pszNick - Optional display name of who set the topic, can be NULL -// pszUID - Optional unique identifier of who set the topic, can be NULL -// pszText - Topic text -#define GC_EVENT_TOPIC 0x0080 - -// GC_EVENT_INFORMATION (Informational text) Ex a server response to a /WHO command in IRC -// pszID(in GCDEST) - NULL to send to the active window -// pszText - Information text -#define GC_EVENT_INFORMATION 0x0100 - -// GC_EVENT_ACTION - " " (An IRC Style action event) -// pszNick - Display name -// pszUID - Unique identifier -// bIsMe - Set to TRUE if it is the Miranda user -// pszText - Message text. -#define GC_EVENT_ACTION 0x0200 - -// GC_EVENT_ADDSTATUS - " enables '' for " (A status change has occured for a user) -// NOTE. Status changes are cumulative. The user will show in the nicklist with the highest status received. -// Ex, IRC users can have "Op" and "Voice" statuses simultaneously but s/he will be displayed as "Op" -// pszNick - Display name of the one who receives a new status -// pszUID - Unique identifier of the one who receives a new status -// pszText - The display name of the one who is setting the status. Color codes are not valid -// pszStatus - The status. Should be a status previously -// registered with GC_EVENT_ADDGROUP. Ex "Voice" in IRC -#define GC_EVENT_ADDSTATUS 0x0400 - -// GC_EVENT_REMOVESTATUS - " disables '' for " (A status change has occured for a user) -// NOTE. Status changes are cumulative. The user will show in the nicklist with the highest status received. -// Ex, IRC users can have "Op" and "Voice" statuses simultaneously but s/he will be displayed as "Op" -// pszNick - Display name of the one who got a status mode disabled -// pszUID - Unique identifier of the one who got a status mode disabled -// pszText - The display name of the one disabling the status. Color codes are not valid -// pszStatus - The status. Should be a status previously -// registered with GC_EVENT_ADDGROUP. Ex "Voice" in IRC -#define GC_EVENT_REMOVESTATUS 0x0800 - -// GC_EVENT_CHUID - not shown in the log (Change the unique identifier of a contact) -// pszID(in GCDEST) - Should be NULL as a unique id's are global. -// pszUID - The current unique identifier -// pszText - The new unique identifier. Color codes are not valid -#define GC_EVENT_CHUID 0x1000 - -// GC_EVENT_CHANGESESSIONAME - not shown in the log (Change the display name of a session) -// pszText - The new name. Color codes are not valid -#define GC_EVENT_CHANGESESSIONAME 0x1001 - -// GC_EVENT_ADDGROUP - not shown in the log (Add a possible status mode to the nicklist, ex IRC uses "Op", "Voice", "Normal" etc ) -// NOTE. When adding several statuses, start with the highest status -// pszStatus - The new group name -// dwItemData - Optional HICON handle to a 10x10 icon. Set to NULL to use the built in icons. -#define GC_EVENT_ADDGROUP 0x1002 - -// GC_EVENT_SETITEMDATA & GC_EVENT_SETITEMDATA - not shown in the log (Get/Set the user defined data of a session) -// dwItemData - The itemdata to set or get -#define GC_EVENT_SETITEMDATA 0x1003 -#define GC_EVENT_GETITEMDATA 0x1004 - -// GC_EVENT_SETSBTEXT - not shown in the log (Set the text of the statusbar for a chat room window) -// pszText - Statusbar text. Color codes are not valid -#define GC_EVENT_SETSBTEXT 0x1006 - -// GC_EVENT_ACK - not shown in the log (Acknowledge a outgoing message, when GC_ACKMSG is set -#define GC_EVENT_ACK 0x1007 - -// GC_EVENT_SENDMESSAGE - not shown in the log ("Fake" a message from a chat room as if the user had typed it). Used by IRC to broadcast /AME and /AMSG messages -// pszText - The text -#define GC_EVENT_SENDMESSAGE 0x1008 - -// GC_EVENT_SETSTATUSEX - not shown in the log (Space or tab delimited list of pszUID's to indicate as away). -// Used by IRC to mark users as away in the nicklist. If UIDs can contain spaces, use tabs -// pszText - Space or tab delimited list of pszUID's - -#define GC_SSE_ONLYLISTED 0x0001 // processes only listed contacts, resets all contacts otherwise -#define GC_SSE_ONLINE 0x0002 // displays a contact online, otherwise away -#define GC_SSE_TABDELIMITED 0x0004 // use tabs as delimiters -#define GC_SSE_OFFLINE 0x0008 // displays a contact offline, otherwise away - -#define GC_EVENT_SETSTATUSEX 0x1009 - -// GC_EVENT_SETCONTACTSTATUS - sets status icon for contact -// pszUID - Unique identifier of the one who receives a new status -// dwItemData - (DWORD)ID_STATUS_* or zero to remove status icon -#define GC_EVENT_SETCONTACTSTATUS 0x100A - -// GC_EVENT_CONTROL - not shown in the log (Control window associated to a session and the session itself) -// NOTE 1: No members of GCEVENT are used, send one of the below flags in wParam instead, -// Ex CallService(GC_EVENT_CONTROL, SESSION_INITDONE, (LPARAM)&gce); -// NOTE 2: The first four control events are the only ones you should use most likely! -// The ones below them are used by IRC to join channels hidden or maximized and show the server window from the system menu. -// The SESSION_VISIBLE, SESSION_HIDDEN, SESSION_MAXIMIZE and SESSION_MINIMIZE events CAN replace SESSION_INITDONE but I urge you not to -// do that as it will override any settings the user has made in the Chat options -// NOTE 3: If pszID (of GCDEST) = NULL then this message will be broadcasted to all sessions, which can be usefule for terminating -// all sessions when the protocol was disconnected -#define SESSION_INITDONE 1 // send this when the session is fully set up (all users have ben added to the nicklist) -#define SESSION_TERMINATE 7 // send to terminate a session and close the window associated with it -#define SESSION_OFFLINE 8 // send to set the session as "online" (hContact is set to Online etc) -#define SESSION_ONLINE 9 // send to set the session as "offline" (hContact is set to Offline etc) - -#define WINDOW_VISIBLE 2 // make the room window visible -#define WINDOW_HIDDEN 3 // close the room window. Session is not terminated. -#define WINDOW_MAXIMIZE 4 // make the room window maximized -#define WINDOW_MINIMIZE 5 // make the room window minimized -#define WINDOW_CLEARLOG 6 // clear the log of the room window - -#define GC_EVENT_CONTROL 0x1005 - -// Error messages -#define GC_EVENT_WRONGVER 1 // You appear to be using the wrong version of this API. -#define GC_EVENT_ERROR 2 // An internal error occurred. - -// The GCDEST structure. It is passed to Chat inside GCEVENT. -struct GCDEST -{ - LPCSTR pszModule; // Name of the protocol (same as you registered with) - LPCTSTR ptszID; // Unique identifier of the session, or NULL to broadcast to all sessions as specified above - int iType; // Use GC_EVENT_* as defined above. Only one event per service call. -}; - -// The GCEVENT structure -struct GCEVENT -{ - int cbSize; // set to sizeof(GCEVENT); - GCDEST *pDest; // pointer to a GCDEST structure which specifies the session to receive the event - LPCTSTR ptszText; // - LPCTSTR ptszNick; // - LPCTSTR ptszUID; // - LPCTSTR ptszStatus; // - LPCTSTR ptszUserInfo; // - - BOOL bIsMe; // Is this event from the Miranda user? - DWORD dwFlags; // event flags: GCEF_ADDTOLOG, GCEF_NOTNOTIFY - - INT_PTR dwItemData; // User specified data. - DWORD time; // Timestamp of the event -}; - -#define MS_GC_EVENT "GChat/NewEvent" - -// This hook is fired when MS_GC_EVENT is called, with the same wParam and lParam as above. -// It allows external plugins to intercept chat events and display then in other ways -#define ME_GC_HOOK_EVENT "GChat/HookEvent" - -#define GCEF_ADDTOLOG 0x0001 -#define GCEF_REMOVECONTACT 0x0002 -// Added in Miranda NG 0.94.4+ -#define GCEF_NOTNOTIFY 0x0004 - -// OK! That was about everything that you need to know about for operating Chat in a basic way. -// There are however some more things you will need to know about. Some you may use and some you may not need, - -/* - -- GETTING info about a SESSION or session data -- - - Use this service to get information on different aspects of the sessions that are registered with Chat. - - * Use MS_GC_GETINFO like this: CallService(MS_GC_GETSESSIONCOUNT, 0, (LPARAM)(char *) pszModule); - * returns -1 on failure and the sessioncount on success -*/ - -#define MS_GC_GETSESSIONCOUNT "GChat/GetCount" - -/* - -- GETTING info about a SESSION or session data -- - Use this service to get information on different aspects of the sessions that are registered with Chat. - - * Use MS_GC_GETINFO like this: CallService(MS_GC_GETINFO, 0, (LPARAM)(GC_INFO *) &gci; - * returns 0 on success or error code on failure -*/ - -// Flags -#define GCF_BYINDEX 0x0001 // iItem is valid and should contain the index of the session to get -#define GCF_BYID 0x0002 // pszID is valid and should contain the ID of the session to get. This is the default if no -#define GCF_HCONTACT 0x0004 // hContact is valid -#define GCF_DATA 0x0008 // wItemData is valid -#define GCF_ID 0x0010 // pszID is valid. -#define GCF_NAME 0x0020 // pszName is valid -#define GCF_TYPE 0x0040 // iType is valid -#define GCF_COUNT 0x0080 // iCount is valid -#define GCF_USERS 0x0100 // pszUsers is valid - -// The GC_INFO structure -struct GC_INFO -{ - DWORD Flags; // use a combination of the above flags - int iItem; // session type (GCW_*) - int iType; // session type (GCW_*) - LPCSTR pszModule; // the module name as registered in MS_GC_REGISTER - LPCTSTR pszID; // unique ID of the session - LPTSTR pszName; // display name of the session - INT_PTR dwItemData; // user specified data. - int iCount; // count of users in the nicklist - LPSTR pszUsers; // space separated string containing the UID's of the users in the user list. - // NOTE. Use Mirandas mmi_free() on the returned string. - MCONTACT hContact; // hContact for the session (can be NULL) -}; - -#define MS_GC_GETINFO "GChat/GetInfo" - -//------------------------- HOOKS ------------------------ -/* - -- user interaction -- - Hook this to receive notifications about when user take actions in a chat room window. - Check for the below flags to find out what type of user interaction it is. See the - to find out which members of GCHOOK that are valid. - - * wParam=0 - * lParam=(LPARAM)(GCEVENT *)pgch - - * Returning nonzero from your hook will stop other hooks from being called. -*/ - -#define GC_USER_MESSAGE 1 // user sent a message, with \n delimiting lines, pszText contains the text. -#define GC_USER_CHANMGR 2 // user clicked the settings button in a chat room -#define GC_USER_LOGMENU 3 // user has selected a message log menu item, dwData is valid. See ME_GC_BUILDMENU -#define GC_USER_NICKLISTMENU 4 // user has selected a userlist menu item, valid members: dwData. See ME_GC_BUILDMENU -#define GC_USER_TYPNOTIFY 5 // NOT IMPLEMENTED YET! user is typing -#define GC_USER_PRIVMESS 6 // user requests to send a private message to a user. pszUID is valid -#define GC_SESSION_TERMINATE 7 // the session is about to be terminated, the "user defined data" is passed in dwData, which can be good free'ing any allocated memory. -#define GC_USER_LEAVE 8 // user requests to leave the session -#define GC_USER_CLOSEWND 9 // user closed the window (this is usually not an indication that the protocol - // should take action, but MSN may want to terminate the session here) -#define ME_GC_EVENT "GChat/OutgoingEvent" - -struct GCHOOK -{ - GCDEST *pDest; // pointer to a GCDEST structure which specifies from which session the hook was triggered - LPTSTR ptszText; // usage depends on type of event - LPTSTR ptszUID; // unique identifier, usage depends on type of event - INT_PTR dwData; // user defined data, usage depends on type of event -}; - -/* - -- Build the pop up menus -- - The user wants to show a right click (popup) menu and your protocol should tell what - items should be added to the menu. You should create a static array of struct gc_item's. - When you get this notification you should set "nItems" to the number of gc_item's - you want to show on the user's popup menu and then set the "Item" member to point to that array. - - * wParam=0 - * lParam=(LPARAM)(GCMENUITEM *)gcmi - - Returning nonzero from your hook will stop other hooks from being called. -*/ - -// type of item to add to the popup menu -#define MENU_NEWPOPUP 1 // add submenu -#define MENU_POPUPITEM 2 // add item to current submenu -#define MENU_POPUPSEPARATOR 3 // add separator to current submenu -#define MENU_SEPARATOR 4 // add separator to menu -#define MENU_ITEM 5 // add item -#define MENU_POPUPCHECK 6 // add checked item to current submenu -#define MENU_CHECK 7 // add checked item -#define MENU_POPUPHMENU 8 // add custom submenu to current submenu, use dwID to specify HMENU -#define MENU_HMENU 9 // add custom submenu, use dwID to specify HMENU - -// type of menu that is being requested -#define MENU_ON_LOG 1 // pop up menu on the message log -#define MENU_ON_NICKLIST 2 // pop up menu on the user list - -// contains info on a menuitem to be added -struct gc_item { - TCHAR *pszDesc; // Textual description of the menu item to add - DWORD dwID; // when/if the user selects this menu item this - // value will be returned via the above hook, GC_USER_LOGMENU - // or GC_USER_NICKLISTMENU. Must not be 0 and must be unique. - int uType; // What kind of menu item is it? Use MENU_* flags above - BOOL bDisabled; // should the menu item be shown as disabled -}; - -typedef struct { - LPSTR pszModule; // Contains the protocol name, do NOT change. - LPTSTR pszID; // The unique identifier of the session that triggered the hook, do NOT change. - LPTSTR pszUID; // Contains the unique identifier if Type = MENU_ON_NICKLIST. do NOT change. - int Type; // Type of menu. MENU_ON_* flags used. do NOT change. - int nItems; // Set this to the number of menu items you want to add - gc_item *Item; // pointer to the first in the array of gc_item's -} - GCMENUITEMS; - -#define ME_GC_BUILDMENU "GChat/BuildMenu" - -/* - * Example of how to add 2 items to the popup menu for the userlist * - - GCMENUITEMS *gcmi= (GCMENUITEMS*) lParam; - if (gcmi->Type == MENU_ON_NICKLIST) - { - static struct gc_item Item[] = { - {Translate("User &details"), 1, MENU_ITEM, FALSE}, - {Translate("&Op"), 2, MENU_POPUPITEM, FALSE}, - }; - - gcmi->nItems = sizeof(Item)/sizeof(Item[0]); - gcmi->Item = &Item[0]; - gcmi->Item[gcmi->nItems-1].bDisabled = bFlag; - - return 0; - } -*/ - -////////////////////////////////////////////////////////////////////////// -// Get Chat ToolTip Text for buddy -// wParam = (WPARAM)(TCHAR*) roomID parentdat->ptszID -// lParam = (WPARAM)(TCHAR*) userID ui1->pszUID -// result (int)(TCHAR*)mir_tstrdup("tooltip text") -// returns pointer to text of tooltip and starts owns it -#define MS_GC_PROTO_GETTOOLTIPTEXT "/GetChatToolTipText" diff --git a/protocols/SkypeClassic/src/sdk/m_folders.h b/protocols/SkypeClassic/src/sdk/m_folders.h deleted file mode 100644 index a112b05d59..0000000000 --- a/protocols/SkypeClassic/src/sdk/m_folders.h +++ /dev/null @@ -1,207 +0,0 @@ -/* -Custom profile folders plugin for Miranda IM - -Copyright © 2005 Cristian Libotean - -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 M_CUSTOM_FOLDERS_H -#define M_CUSTOM_FOLDERS_H - -#define FOLDERS_API 501 //dunno why it's here but it is :) - -#define PROFILE_PATH "%profile_path%" -#define CURRENT_PROFILE "%current_profile%" -#define MIRANDA_PATH "%miranda_path%" -#define PLUGINS_PATH "%miranda_path%" "\\plugins" - -#define TO_WIDE(x) L ## x - -#define PROFILE_PATHW L"%profile_path%" -#define CURRENT_PROFILEW L"%current_profile%" -#define MIRANDA_PATHW L"%miranda_path%" - -#define FOLDER_AVATARS PROFILE_PATH "\\" CURRENT_PROFILE "\\avatars" -#define FOLDER_VCARDS PROFILE_PATH "\\" CURRENT_PROFILE "\\vcards" -#define FOLDER_LOGS PROFILE_PATH "\\" CURRENT_PROFILE "\\logs" -#define FOLDER_RECEIVED_FILES PROFILE_PATH "\\" CURRENT_PROFILE "\\received files" -#define FOLDER_DOCS MIRANDA_PATH "\\" "docs" - -#define FOLDER_CONFIG PLUGINS_PATH "\\" "config" - -#define FOLDER_SCRIPTS MIRANDA_PATH "\\" "scripts" - -#define FOLDER_UPDATES MIRANDA_PATH "\\" "updates" - -#define FOLDER_CUSTOMIZE MIRANDA_PATH "\\" "customize" -#define FOLDER_CUSTOMIZE_SOUNDS FOLDER_CUSTOMIZE "\\sounds" -#define FOLDER_CUSTOMIZE_ICONS FOLDER_CUSTOMIZE "\\icons" -#define FOLDER_CUSTOMIZE_SMILEYS FOLDER_CUSTOMIZE "\\smileys" -#define FOLDER_CUSTOMIZE_SKINS FOLDER_CUSTOMIZE "\\skins" -#define FOLDER_CUSTOMIZE_THEMES FOLDER_CUSTOMIZE "\\themes" - - -#define FOLDERS_NAME_MAX_SIZE 64 //maximum name and section size - -#define FF_UNICODE 0x00000001 - -typedef struct{ - int cbSize; //size of struct - char szSection[FOLDERS_NAME_MAX_SIZE]; //section name, if it doesn't exist it will be created otherwise it will just add this entry to it - char szName[FOLDERS_NAME_MAX_SIZE]; //entry name - will be shown in options - union{ - const char *szFormat; //default string format. Fallback string in case there's no entry in the database for this folder. This should be the initial value for the path, users will be able to change it later. - const wchar_t *szFormatW; //String is dup()'d so you can free it later. If you set the unicode string don't forget to set the flag accordingly. - const TCHAR *szFormatT; - }; - DWORD flags; //FF_* flags -} FOLDERSDATA; - -/*Folders/Register/Path service - wParam - not used, must be 0 - lParam - (LPARAM) (const FOLDERDATA *) - Data structure filled with - the necessary information. - Returns a handle to the registered path or 0 on error. - You need to use this to call the other services. -*/ -#define MS_FOLDERS_REGISTER_PATH "Folders/Register/Path" - -/*Folders/Get/PathSize service - wParam - (WPARAM) (int) - handle to registered path - lParam - (LPARAM) (int *) - pointer to the variable that receives the size of the path - string (not including the null character). Depending on the flags set when creating the path - it will either call strlen() or wcslen() to get the length of the string. - Returns the size of the buffer. -*/ -#define MS_FOLDERS_GET_SIZE "Folders/Get/PathSize" - -typedef struct{ - int cbSize; - int nMaxPathSize; //maximum size of buffer. This represents the number of characters that can be copied to it (so for unicode strings you don't send the number of bytes but the length of the string). - union{ - char *szPath; //pointer to the buffer that receives the path without the last "\\" - wchar_t *szPathW; //unicode version of the buffer. - TCHAR *szPathT; - }; -} FOLDERSGETDATA; - -/*Folders/Get/Path service - wParam - (WPARAM) (int) - handle to registered path - lParam - (LPARAM) (FOLDERSGETDATA *) pointer to a FOLDERSGETDATA that has all the relevant fields filled. - Should return 0 on success, or nonzero otherwise. -*/ -#define MS_FOLDERS_GET_PATH "Folders/Get/Path" - -typedef struct{ - int cbSize; - union{ - char **szPath; //address of a string variable (char *) or (wchar_t*) where the path should be stored (the last \ won't be copied). - wchar_t **szPathW; //unicode version of string. - TCHAR **szPathT; - }; -} FOLDERSGETALLOCDATA; - -/*Folders/GetRelativePath/Alloc service - wParam - (WPARAM) (int) - Handle to registered path - lParam - (LPARAM) (FOLDERSALLOCDATA *) data - This service is the same as MS_FOLDERS_GET_PATH with the difference that this service - allocates the needed space for the buffer. It uses miranda's memory functions for that and you need - to use those to free the resulting buffer. - Should return 0 on success, or nonzero otherwise. Currently it only returns 0. -*/ -#define MS_FOLDERS_GET_PATH_ALLOC "Folders/Get/Path/Alloc" - - -/*Folders/On/Path/Changed - wParam - (WPARAM) 0 - lParam - (LPARAM) 0 - Triggered when the folders change, you should reget the paths you registered. -*/ -#define ME_FOLDERS_PATH_CHANGED "Folders/On/Path/Changed" - -#ifndef FOLDERS_NO_HELPER_FUNCTIONS -//#include "../../../include/newpluginapi.h" - -__inline static int FoldersRegisterCustomPath(const char *section, const char *name, const char *defaultPath) -{ - FOLDERSDATA fd = {0}; - if (!ServiceExists(MS_FOLDERS_REGISTER_PATH)) return 1; - fd.cbSize = sizeof(FOLDERSDATA); - strncpy(fd.szSection, section, FOLDERS_NAME_MAX_SIZE); - fd.szSection[FOLDERS_NAME_MAX_SIZE - 1] = '\0'; - strncpy(fd.szName, name, FOLDERS_NAME_MAX_SIZE); - fd.szName[FOLDERS_NAME_MAX_SIZE - 1] = '\0'; - fd.szFormat = defaultPath; - return CallService(MS_FOLDERS_REGISTER_PATH, 0, (LPARAM) &fd); -} - -__inline static int FoldersRegisterCustomPathW(const char *section, const char *name, const wchar_t *defaultPathW) -{ - FOLDERSDATA fd = {0}; - if (!ServiceExists(MS_FOLDERS_REGISTER_PATH)) return 1; - fd.cbSize = sizeof(FOLDERSDATA); - strncpy(fd.szSection, section, FOLDERS_NAME_MAX_SIZE); - fd.szSection[FOLDERS_NAME_MAX_SIZE - 1] = '\0'; //make sure it's NULL terminated - strncpy(fd.szName, name, FOLDERS_NAME_MAX_SIZE); - fd.szName[FOLDERS_NAME_MAX_SIZE - 1] = '\0'; //make sure it's NULL terminated - fd.szFormatW = defaultPathW; - fd.flags = FF_UNICODE; - return CallService(MS_FOLDERS_REGISTER_PATH, 0, (LPARAM) &fd); -} - -__inline static int FoldersGetCustomPath(HANDLE hFolderEntry, char *path, const int size, char *notFound) -{ - FOLDERSGETDATA fgd = {0}; - int res; - fgd.cbSize = sizeof(FOLDERSGETDATA); - fgd.nMaxPathSize = size; - fgd.szPath = path; - res = CallService(MS_FOLDERS_GET_PATH, (WPARAM) hFolderEntry, (LPARAM) &fgd); - if (res) - { - strncpy(path, notFound, size); - path[size - 1] = '\0'; //make sure it's NULL terminated - } - return res; -} - -__inline static int FoldersGetCustomPathW(HANDLE hFolderEntry, wchar_t *pathW, const int count, wchar_t *notFoundW) -{ - FOLDERSGETDATA fgd = {0}; - int res; - fgd.cbSize = sizeof(FOLDERSGETDATA); - fgd.nMaxPathSize = count; - fgd.szPathW = pathW; - res = CallService(MS_FOLDERS_GET_PATH, (WPARAM) hFolderEntry, (LPARAM) &fgd); - if (res) - { - wcsncpy(pathW, notFoundW, count); - pathW[count - 1] = '\0'; - } - return res; -} - -# ifdef _UNICODE -# define FoldersGetCustomPathT FoldersGetCustomPathW -# define FoldersRegisterCustomPathT FoldersRegisterCustomPathW -#else -# define FoldersGetCustomPathT FoldersGetCustomPath -# define FoldersRegisterCustomPathT FoldersRegisterCustomPath -#endif - -#endif - -#endif //M_CUSTOM_FOLDERS_H \ No newline at end of file diff --git a/protocols/SkypeClassic/src/sdk/m_metacontacts.h b/protocols/SkypeClassic/src/sdk/m_metacontacts.h deleted file mode 100644 index fe19c32d6a..0000000000 --- a/protocols/SkypeClassic/src/sdk/m_metacontacts.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - -Miranda IM: the free IM client for Microsoft* Windows* - -Copyright © 2004 Universite Louis PASTEUR, STRASBOURG. -Copyright © 2004 Scott Ellis (www.scottellis.com.au mail@scottellis.com.au) - -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 M_METACONTACTS_H__ -#define M_METACONTACTS_H__ 1 - -//gets the handle for the default contact -//wParam=(HANDLE)hMetaContact -//lParam=0 -//returns a handle to the default contact, or null on failure -#define MS_MC_GETDEFAULTCONTACT "MetaContacts/GetDefault" - -//gets the contact number for the default contact -//wParam=(HANDLE)hMetaContact -//lParam=0 -//returns a DWORD contact number, or -1 on failure -#define MS_MC_GETDEFAULTCONTACTNUM "MetaContacts/GetDefaultNum" - -//gets the handle for the 'most online' contact -//wParam=(HANDLE)hMetaContact -//lParam=0 -//returns a handle to the 'most online' contact -#define MS_MC_GETMOSTONLINECONTACT "MetaContacts/GetMostOnline" - -//gets the number of subcontacts for a metacontact -//wParam=(HANDLE)hMetaContact -//lParam=0 -//returns a DWORD representing the number of subcontacts for the given metacontact -#define MS_MC_GETNUMCONTACTS "MetaContacts/GetNumContacts" - -//gets the handle of a subcontact, using the subcontact's number -//wParam=(HANDLE)hMetaContact -//lParam=(DWORD)contact number -//returns a handle to the specified subcontact -#define MS_MC_GETSUBCONTACT "MetaContacts/GetSubContact" - -//sets the default contact, using the subcontact's contact number -//wParam=(HANDLE)hMetaContact -//lParam=(DWORD)contact number -//returns 0 on success -#define MS_MC_SETDEFAULTCONTACTNUM "MetaContacts/SetDefault" - -//sets the default contact, using the subcontact's handle -//wParam=(HANDLE)hMetaContact -//lParam=(HANDLE)hSubcontact -//returns 0 on success -#define MS_MC_SETDEFAULTCONTACT "MetaContacts/SetDefaultByHandle" - -//forces the metacontact to send using a specific subcontact, using the subcontact's contact number -//wParam=(HANDLE)hMetaContact -//lParam=(DWORD)contact number -//returns 0 on success -#define MS_MC_FORCESENDCONTACTNUM "MetaContacts/ForceSendContact" - -//forces the metacontact to send using a specific subcontact, using the subcontact's handle -//wParam=(HANDLE)hMetaContact -//lParam=(HANDLE)hSubcontact -//returns 0 on success (will fail if 'force default' is in effect) -#define MS_MC_FORCESENDCONTACT "MetaContacts/ForceSendContactByHandle" - -//'unforces' the metacontact to send using a specific subcontact -//wParam=(HANDLE)hMetaContact -//lParam=0 -//returns 0 on success (will fail if 'force default' is in effect) -#define MS_MC_UNFORCESENDCONTACT "MetaContacts/UnforceSendContact" - -//'forces' or 'unforces' (i.e. toggles) the metacontact to send using it's default contact -// overrides (and clears) 'force send' above, and will even force use of offline contacts -// will send ME_MC_FORCESEND or ME_MC_UNFORCESEND event -//wParam=(HANDLE)hMetaContact -//lParam=0 -//returns 1(true) or 0(false) representing new state of 'force default' -#define MS_MC_FORCEDEFAULT "MetaContacts/ForceSendDefault" - -// method to get state of 'force' for a metacontact -// wParam=(HANDLE)hMetaContact -// lParam= (DWORD)&contact_number or NULL -// -// if lparam supplied, the contact_number of the contatct 'in force' will be copied to the address it points to, -// or if none is in force, the value (DWORD)-1 will be copied -// (v0.8.0.8+ returns 1 if 'force default' is true with *lParam == default contact number, else returns 0 with *lParam as above) -#define MS_MC_GETFORCESTATE "MetaContacts/GetForceState" - -// fired when a metacontact's default contact changes (fired upon creation of metacontact also, when default is initially set) -// wParam=(HANDLE)hMetaContact -// lParam=(HANDLE)hDefaultContact -#define ME_MC_DEFAULTTCHANGED "MetaContacts/DefaultChanged" - -// fired when a metacontact's subcontacts change (fired upon creation of metacontact, when contacts are added or removed, and when -// contacts are reordered) - a signal to re-read metacontact data -// wParam=(HANDLE)hMetaContact -// lParam=0 -#define ME_MC_SUBCONTACTSCHANGED "MetaContacts/SubcontactsChanged" - -// fired when a metacontact is forced to send using a specific subcontact -// wParam=(HANDLE)hMetaContact -// lParam=(HANDLE)hForceContact -#define ME_MC_FORCESEND "MetaContacts/ForceSend" - -// fired when a metacontact is 'unforced' to send using a specific subcontact -// wParam=(HANDLE)hMetaContact -// lParam=0 -#define ME_MC_UNFORCESEND "MetaContacts/UnforceSend" - -// method to get protocol name - used to be sure you're dealing with a "real" metacontacts plugin :) -// wParam=lParam=0 -#define MS_MC_GETPROTOCOLNAME "MetaContacts/GetProtoName" - -#endif diff --git a/protocols/SkypeClassic/src/sdk/m_toptoolbar.h b/protocols/SkypeClassic/src/sdk/m_toptoolbar.h deleted file mode 100644 index 5628f68de8..0000000000 --- a/protocols/SkypeClassic/src/sdk/m_toptoolbar.h +++ /dev/null @@ -1,125 +0,0 @@ - -#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 \ No newline at end of file diff --git a/protocols/SkypeClassic/src/sdk/m_updater.h b/protocols/SkypeClassic/src/sdk/m_updater.h deleted file mode 100644 index 371b7437a0..0000000000 --- a/protocols/SkypeClassic/src/sdk/m_updater.h +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef _M_UPDATER_H -#define _M_UPDATER_H - -// 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); -} - - -// 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/protocols/SkypeClassic/src/sdk/m_voice.h b/protocols/SkypeClassic/src/sdk/m_voice.h deleted file mode 100644 index a81d866754..0000000000 --- a/protocols/SkypeClassic/src/sdk/m_voice.h +++ /dev/null @@ -1,158 +0,0 @@ -/* -Copyright (C) 2006 Ricardo Pescuma Domenecci - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This 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 -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this file; see the file license.txt. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. -*/ - - -#ifndef __M_VOICE_H__ -# define __M_VOICE_H__ - - -#define EVENTTYPE_VOICE_CALL 8739 - - -#define PROTOTYPE_VOICE (PROTOTYPE_ENCRYPTION-9) - - -#define VOICE_UNICODE 0x80000000 - -#ifdef UNICODE -# define VOICE_TCHAR VOICE_UNICODE -#else -# define VOICE_TCHAR 0 -#endif - -#define VOICE_STATE_TALKING 0 -#define VOICE_STATE_RINGING 1 -#define VOICE_STATE_CALLING 2 -#define VOICE_STATE_ON_HOLD 3 -#define VOICE_STATE_ENDED 4 - -typedef struct { - int cbSize; // Struct size - const char *szModule; // The name of the protocol module (used only in notifications) - char *id; // Protocol especific ID for this call - int flags; // Can be VOICE_CALL_CONTACT or VOICE_CALL_STRING (VOICE_UNICODE to say the string is unicode) - union { // Who to call - HANDLE hContact; - TCHAR *ptszContact; - char *pszContact; - WCHAR *pwszContact; - }; - int state; // VOICE_STATE_* - -} VOICE_CALL; - - -/* -Notifies that a voice call changed state - -wParam: const VOICE_CALL * -lParam: ignored -return: 0 on success -*/ -#define PE_VOICE_CALL_STATE "/Voice/State" - - -#define VOICE_SUPPORTED 1 // Set if proto support voice calls. Probabilly will be 1 ;) -#define VOICE_CALL_CONTACT 2 // Set if a call can be made to a hContact -#define VOICE_CALL_CONTACT_NEED_TEST 4 // Set if the contact need to be tested with PS_VOICE_CALL_CONTACT_VALID (needs VOICE_CALL_CONTACT set to work) -#define VOICE_CALL_STRING 8 // Set if a call can be made to some string (PS_VOICE_CALL_STRING_VALID is used to validate the string) -#define VOICE_CAN_SET_DEVICE 16 // Set if the devices to mic in and sound out can be set (or the protocol will handle it internally) -#define VOICE_CAN_HOLD 32 // Set if a call can be put on hold -/* -Get protocol voice support flags - -wParam: ignored -lParam: ignored -return: 0 on success -*/ -#define PS_VOICE_GETINFO "/Voice/GetInfo" - -/* -Request to the protocol a voice call to hContact. - -wParam: (HANDLE) hContact -lParam: ignored -return: 0 on success -*/ -#define PS_VOICE_CALL "/Voice/Call" - -/* -Service called to make the protocol answer a call. -It is an async call. If the call was answered, the PE_VOICE_STARTEDCALL -notification will be fired. - -wParam: (const char *) id -lParam: ignored -return: 0 on success -*/ -#define PS_VOICE_ANSWERCALL "/Voice/AnswerCall" - -/* -Service called to make the protocol answer a call. This can be called if the -call is ringing or has started. If called any other time it should be ignored. -It is an async call. If the call was droped, the PE_VOICE_ENDEDCALL -notification will be fired. - -wParam: (const char *) id -lParam: ignored -return: 0 on success -*/ -#define PS_VOICE_DROPCALL "/Voice/DropCall" - -/* -Service called to make the protocol hold a call. This means that the call should not -be droped, but it should be muted and put in a hold, to allow other call to be answered. -If the protocol can't hold a cal, it should be droped. - -This can be called if the call has started. If called any other time it should be ignored. -It is an async call. If the call was droped, the PE_VOICE_HOLDEDCALL -notification will be fired. - -wParam: (const char *) id -lParam: ignored -return: 0 on success -*/ -#define PS_VOICE_HOLDCALL "/Voice/HoldCall" - -/* -Used if protocol support VOICE_CALL_STRING. The call string is passed as -wParam and the proto should validate it. - -wParam: (const TCHAR *) call string -lParam: ignored -return: 0 if wrong, 1 if correct -*/ -#define PS_VOICE_CALL_STRING_VALID "/Voice/CallStringValid" - -/* -Used if protocol support VOICE_CALL_CONTACT and VOICE_CALL_CONTACT_NEED_TEST. -The hContact is passed as wParam and the proto should tell if this contact can be -called. - -wParam: (HANDLE) hContact -lParam: (BOOL) TRUE if it is a test for 'can call now?', FALSE if is a test for 'will be possible to call someday?' -return: 0 if can't be called, 1 if can -*/ -#define PS_VOICE_CALL_CONTACT_VALID "/Voice/CallContactValid" - - - - - -#endif // __M_VOICE_H__ diff --git a/protocols/SkypeClassic/src/sdk/m_voiceservice.h b/protocols/SkypeClassic/src/sdk/m_voiceservice.h deleted file mode 100644 index 98c3580aea..0000000000 --- a/protocols/SkypeClassic/src/sdk/m_voiceservice.h +++ /dev/null @@ -1,86 +0,0 @@ -/* -Copyright (C) 2007 Ricardo Pescuma Domenecci - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This 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 -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this file; see the file license.txt. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. -*/ - - -#ifndef __M_VOICESERVICE_H__ -# define __M_VOICESERVICE_H__ - -#include "m_voice.h" - - -#define MIID_VOICESERVICE { 0x7d64437, 0xef2e, 0x4f60, { 0xbb, 0x2d, 0x3c, 0x51, 0x8f, 0xe2, 0x4d, 0x63 } } - - -/* -This services are a mirror of the services/notifications in m_voice.h, -with the difference that that ones are to be used by protocols, and this ones -are to be used by plugins that can make calls to contacts in multiple protocols. -*/ - - -/* -Notifies that a voice call changed state - -wParam: const VOICE_CALL * -lParam: ignored -return: 0 on success -*/ -#define MS_VOICESERVICE_STATE "VoiceService/State" - - - -struct VOICE_MODULE -{ - int cbSize; // sizeof(VOICE_MODULE) - char *name; // The internal name of the plugin. All PS_* serivces (except PS_VOICE_GETINFO) - // defined in m_voide.h need to be created based in this name. For example, - // PS_VOICE_CALL (/Voice/Call) need to be created as /Voice/Call - int flags; // VOICE_* from m_voice.h -}; -/* -Register a new plugin that can make/receive voice calls. - -wParam: const VOICE_MODULE * -lParam: ignored -return: 0 on success -*/ -#define MS_VOICESERVICE_REGISTER "VoiceService/Register" - - -/* -Request a voice call to hContact. - -wParam: (HANDLE) hContact -lParam: ignored -return: the number of option calls for a contact. If > 0, it can be called -*/ -#define MS_VOICESERVICE_CAN_CALL "VoiceService/CanCall" - -/* -Request a voice call to hContact. - -wParam: (HANDLE) hContact -lParam: (char *) Protocol or NULL to use any proto avaiable -return: 0 on success -*/ -#define MS_VOICESERVICE_CALL "VoiceService/Call" - - - -#endif // __M_VOICESERVICE_H__ diff --git a/protocols/SkypeClassic/src/skype.c b/protocols/SkypeClassic/src/skype.c deleted file mode 100644 index 8abb67c9de..0000000000 --- a/protocols/SkypeClassic/src/skype.c +++ /dev/null @@ -1,3569 +0,0 @@ -/* - -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 "skype.h" -#include "debug.h" -#include "skypeapi.h" -#include "skypesvc.h" -#include "contacts.h" -#include "utf8.h" -#include "pthread.h" -#include "gchat.h" -#include "m_toptoolbar.h" -#include "voiceservice.h" -#include "msglist.h" -#include "memlist.h" -#include -#ifndef INVALID_FILE_ATTRIBUTES -#define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF -#endif -#ifdef _WIN64 -#if (_MSC_VER < 1500) -#pragma comment (lib, "bufferoverflowU.lib") -#endif -#endif -#ifdef __cplusplus -#define EXPORT extern "C" __declspec(dllexport) -#else -#define EXPORT __declspec(dllexport) -#endif - -#pragma warning (disable: 4706) // assignment within conditional expression - -#ifdef IS_MIRANDAIM -PLUGINLINK *pluginLink; -struct MM_INTERFACE mmi; -#define SKYPE_DEF_PROTONAME "SKYPE" -#else -#define SKYPE_DEF_PROTONAME "SkypeClassic" -#endif - -POPUPDATAT MessagePopup; - -// Exported Globals -HWND hSkypeWnd = NULL, g_hWnd = NULL, hSkypeWndSecondary = NULL, hForbiddenSkypeWnd = NULL; -HANDLE SkypeReady, SkypeMsgReceived, hInitChat = NULL, httbButton = NULL, FetchMessageEvent = NULL; -BOOL SkypeInitialized = FALSE, MirandaShuttingDown = FALSE, PopupServiceExists = FALSE; -BOOL UseSockets = FALSE, bSkypeOut = FALSE, bProtocolSet = FALSE, bIsImoproxy = FALSE; -char skype_path[MAX_PATH], protocol = 2, *pszProxyCallout = NULL, g_szProtoName[_MAX_FNAME] = SKYPE_DEF_PROTONAME; -int SkypeStatus = ID_STATUS_OFFLINE, hSearchThread = -1, receivers = 1; -long sendwatchers = 0, rcvwatchers = 0; -UINT ControlAPIAttach, ControlAPIDiscover; -LONG AttachStatus = -1; -HINSTANCE hInst; -HANDLE hProtocolAvatarsFolder; -char DefaultAvatarsFolder[MAX_PATH + 1]; -DWORD mirandaVersion; -int hLangpack = 0; - -CRITICAL_SECTION RingAndEndcallMutex, QueryThreadMutex, TimeMutex; - -// Module Internal Globals -HANDLE MessagePumpReady; -HANDLE hChatEvent = NULL, hChatMenu = NULL; -HANDLE hEvInitChat = NULL, hBuddyAdded = NULL; -HANDLE hMenuAddSkypeContact = NULL; - -DWORD msgPumpThreadId = 0; -#ifdef SKYPEBUG_OFFLN -HANDLE GotUserstatus; -#endif - -BOOL bModulesLoaded = FALSE; -char *RequestedStatus = NULL; // To fix Skype-API Statusmode-bug -char cmdMessage[12] = "MESSAGE", cmdPartner[8] = "PARTNER"; // Compatibility commands - - - -// Direct assignment of user properties to a DB-Setting -static const settings_map m_settings[] = { - { "LANGUAGE", "Language1" }, - { "PROVINCE", "State" }, - { "CITY", "City" }, - { "PHONE_HOME", "Phone" }, - { "PHONE_OFFICE", "CompanyPhone" }, - { "PHONE_MOBILE", "Cellular" }, - { "HOMEPAGE", "Homepage" }, - { "ABOUT", "About" } -}; - -// Imported Globals -extern status_map status_codes[]; - -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 - -typedef struct { - char msgnum[16]; - BOOL getstatus; - BOOL bIsRead; - BOOL bDontMarkSeen; - BOOL QueryMsgDirection; - TYP_MSGLENTRY *pMsgEntry; -} fetchmsg_arg; - -typedef struct { - MCONTACT hContact; - char szId[16]; -} msgsendwt_arg; - -/* - * 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; -} - -// Plugin Info -PLUGININFOEX pluginInfo = { - sizeof(PLUGININFOEX), - __PLUGIN_NAME, - PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), - __DESCRIPTION, - __AUTHOR, - __AUTHOREMAIL, - __COPYRIGHT, - __AUTHORWEB, - UNICODE_AWARE, -#ifdef IS_MIRANDAIM - 0, //doesn't replace anything built-in -#endif - // {A71F8335-7B87-4432-B8A3-81479431C6F5} - { 0xa71f8335, 0x7b87, 0x4432, { 0xb8, 0xa3, 0x81, 0x47, 0x94, 0x31, 0xc6, 0xf5 } } -}; - -#define MAPDND 1 // Map Occupied to DND status and say that you support it -//#define MAPNA 1 // Map NA status to Away and say that you support it - -/* P R O G R A M */ - -void RegisterToDbeditorpp(void) -{ - // known modules list - if (ServiceExists("DBEditorpp/RegisterSingleModule")) - CallService("DBEditorpp/RegisterSingleModule", (WPARAM)SKYPE_PROTONAME, 0); -} - -void RegisterToUpdate(void) -{ -#ifdef IS_MIRANDAIM - //Use for the Updater plugin - if(ServiceExists(MS_UPDATE_REGISTER)) - { - Update update = {0}; - char szVersion[16]; - - update.szComponentName = pluginInfo.shortName; - update.pbVersion = (BYTE *)CreateVersionStringPlugin((PLUGININFO *)&pluginInfo, szVersion); - update.cpbVersion = (DWORD)strlen((char *)update.pbVersion); - -#ifdef _WIN64 -#ifdef _UNICODE - update.szBetaUpdateURL = "http://dose.0wnz.at/miranda/Skype/Skype_protocol_unicode_x64.zip"; -#else - update.szBetaUpdateURL = "http://dose.0wnz.at/miranda/Skype/Skype_protocol_x64.zip"; -#endif - update.szBetaVersionURL = "http://dose.0wnz.at/miranda/Skype/"; - update.pbBetaVersionPrefix = (BYTE *)"SKYPE version "; - update.szUpdateURL = update.szBetaUpdateURL; // FIXME!! - update.szVersionURL = update.szBetaVersionURL; // FIXME - update.pbVersionPrefix = update.pbBetaVersionPrefix; //FIXME -#else /* _WIN64 */ -#ifdef _UNICODE - update.szBetaUpdateURL = "http://dose.0wnz.at/miranda/Skype/Skype_protocol_unicode.zip"; -#else - update.szBetaUpdateURL = "http://dose.0wnz.at/miranda/Skype/Skype_protocol.zip"; -#endif - update.szBetaVersionURL = "http://dose.0wnz.at/miranda/Skype/"; - update.pbBetaVersionPrefix = (BYTE *)"SKYPE version "; -#ifdef _UNICODE - update.szUpdateURL = update.szBetaUpdateURL; // FIXME!! - update.szVersionURL = update.szBetaVersionURL; // FIXME - update.pbVersionPrefix = update.pbBetaVersionPrefix; //FIXME -#else - update.szUpdateURL = "http://addons.miranda-im.org/feed.php?dlfile=3200"; - update.szVersionURL = "http://addons.miranda-im.org/details.php?action=viewfile&id=3200"; - update.pbVersionPrefix = (BYTE *)"Skype Protocol"; -#endif -#endif - - update.cpbVersionPrefix = (DWORD)strlen((char *)update.pbVersionPrefix); - update.cpbBetaVersionPrefix = (DWORD)strlen((char *)update.pbBetaVersionPrefix); - - CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update); - - } -#endif -} - -/* - * ShowMessage - * - * Shows a popup, if the popup plugin is enabled. - * mustShow: 1 -> If Popup-Plugin is not available/disabled, show Message - * in a Messagewindow - * If the Popup-Plugin is enabled, let the message stay on - * screen until someone clicks it away. - * 0 -> If Popup-Plugin is not available/disabled, skip message - * Returns 0 on success, -1 on failure - * - */ -int ShowMessage(int iconID, TCHAR *lpzText, int mustShow) { - - - - if (db_get_b(NULL, SKYPE_PROTONAME, "SuppressErrors", 0)) return -1; - lpzText = TranslateTS(lpzText); - - if (bModulesLoaded && PopupServiceExists && ServiceExists(MS_POPUP_ADDPOPUPT) && db_get_b(NULL, SKYPE_PROTONAME, "UsePopup", 0) && !MirandaShuttingDown) { - BOOL showPopup, popupWindowColor; - unsigned int popupBackColor, popupTextColor; - int popupTimeSec; - - popupTimeSec = db_get_dw(NULL, SKYPE_PROTONAME, "popupTimeSecErr", 4); - popupTextColor = db_get_dw(NULL, SKYPE_PROTONAME, "popupTextColorErr", GetSysColor(COLOR_WINDOWTEXT)); - popupBackColor = db_get_dw(NULL, SKYPE_PROTONAME, "popupBackColorErr", GetSysColor(COLOR_BTNFACE)); - popupWindowColor = (0 != db_get_b(NULL, SKYPE_PROTONAME, "popupWindowColorErr", TRUE)); - showPopup = (0 != db_get_b(NULL, SKYPE_PROTONAME, "showPopupErr", TRUE)); - - MessagePopup.lchContact = NULL; - MessagePopup.lchIcon = LoadIcon(hInst, MAKEINTRESOURCE(iconID)); - MessagePopup.colorBack = !popupWindowColor ? popupBackColor : GetSysColor(COLOR_BTNFACE); - MessagePopup.colorText = !popupWindowColor ? popupTextColor : GetSysColor(COLOR_WINDOWTEXT); - MessagePopup.iSeconds = popupTimeSec; - MessagePopup.PluginData = (void *)1; - - lstrcpy(MessagePopup.lptzText, lpzText); - -#ifdef _UNICODE - mbstowcs(MessagePopup.lptzContactName, SKYPE_PROTONAME, strlen(SKYPE_PROTONAME) + 1); -#else - lstrcpy(MessagePopup.lptzContactName, SKYPE_PROTONAME); -#endif - - if (showPopup) - CallService(MS_POPUP_ADDPOPUPT, (WPARAM)&MessagePopup, 0); - - return 0; - } - else { - - if (mustShow == 1) MessageBox(NULL, lpzText, _T("Skype Protocol"), MB_OK | MB_ICONWARNING); - return 0; - } -} -#ifdef _UNICODE -int ShowMessageA(int iconID, char *lpzText, int mustShow) { - WCHAR *lpwText; - int iRet; - size_t len = mbstowcs(NULL, lpzText, strlen(lpzText)); - if (len == -1 || !(lpwText = (WCHAR*)calloc(len + 1, sizeof(WCHAR)))) return -1; - mbstowcs(lpwText, lpzText, strlen(lpzText)); - iRet = ShowMessage(iconID, lpwText, mustShow); - free(lpwText); - return iRet; -} -#endif - -// processing Hooks - -int HookContactAdded(WPARAM wParam, LPARAM lParam) { - char *szProto; - - UNREFERENCED_PARAMETER(lParam); - - szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); - if (szProto != NULL && !strcmp(szProto, SKYPE_PROTONAME)) - add_contextmenu((MCONTACT)wParam); - return 0; -} - -int HookContactDeleted(WPARAM wParam, LPARAM lParam) { - char *szProto; - - UNREFERENCED_PARAMETER(lParam); - - szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); - if (szProto != NULL && !strcmp(szProto, SKYPE_PROTONAME)) { - DBVARIANT dbv; - int retval; - - if (db_get_s((MCONTACT)wParam, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) return 1; - retval = SkypeSend("SET USER %s BUDDYSTATUS 1", dbv.pszVal); - db_free(&dbv); - if (retval) return 1; - } - return 0; -} - -void GetInfoThread(void *hContact) -{ - DBVARIANT dbv; - int i; - char *ptr; - BOOL bSetNick = FALSE; - // All properties are already handled in the WndProc, so we just consume the - // messages here to do proper ERROR handling - // If you add something here, be sure to handle it in WndProc, but let it - // fall through there so that message gets added to the queue in order to be - // consumed by SkypeGet - char *pszProps[] = { - "BIRTHDAY", "COUNTRY", "SEX", "MOOD_TEXT", "TIMEZONE", "IS_VIDEO_CAPABLE" }; - - LOG(("GetInfoThread started.")); - EnterCriticalSection(&QueryThreadMutex); - if (db_get_s((MCONTACT)hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) - { - LOG(("GetInfoThread terminated, cannot find Skype Name for contact %08X.", hContact)); - LeaveCriticalSection(&QueryThreadMutex); - return; - } - - if (ptr = SkypeGet("USER", dbv.pszVal, "DISPLAYNAME")) { - // WndProc sets Nick accordingly - if (*ptr) bSetNick = TRUE; - free(ptr); - } - - if (ptr = SkypeGet("USER", dbv.pszVal, "FULLNAME")) { - if (*ptr && !bSetNick && db_get_b(NULL, SKYPE_PROTONAME, "ShowFullname", 1)) { - // No Displayname and FULLNAME requested - db_set_utf((MCONTACT)hContact, SKYPE_PROTONAME, "Nick", ptr); - bSetNick = TRUE; - } - free(ptr); - } - - if (!bSetNick) { - // Still no nick set, so use SKYPE Nickname - db_set_s((MCONTACT)hContact, SKYPE_PROTONAME, "Nick", dbv.pszVal); - } - - - if (!bIsImoproxy) - { - for (i = 0; i < sizeof(pszProps) / sizeof(pszProps[0]); i++) - if (ptr = SkypeGet("USER", dbv.pszVal, pszProps[i])) free(ptr); - } - else { - if (ptr = SkypeGet("USER", dbv.pszVal, "MOOD_TEXT")) free(ptr); - } - - if (protocol >= 7 || bIsImoproxy) { - // Notify about the possibility of an avatar - ACKDATA ack = { 0 }; - ack.cbSize = sizeof(ACKDATA); - ack.szModule = SKYPE_PROTONAME; - ack.hContact = (MCONTACT)hContact; - ack.type = ACKTYPE_AVATAR; - ack.result = ACKRESULT_STATUS; - - CallService(MS_PROTO_BROADCASTACK, 0, (LPARAM)&ack); - //if (ptr=SkypeGet ("USER", dbv.pszVal, "RICH_MOOD_TEXT")) free (ptr); - } - - if (!bIsImoproxy) - { - for (i = 0; i < sizeof(m_settings) / sizeof(m_settings[0]); i++) - if (ptr = SkypeGet("USER", dbv.pszVal, m_settings[i].SkypeSetting)) free(ptr); - } - - ProtoBroadcastAck(SKYPE_PROTONAME, (MCONTACT)hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE)1, 0); - LeaveCriticalSection(&QueryThreadMutex); - db_free(&dbv); - LOG(("GetInfoThread terminated gracefully.")); -} - -time_t SkypeTime(time_t *timer) -{ - struct _timeb tb; - - EnterCriticalSection(&TimeMutex); - _ftime(&tb); - if (timer) *timer = tb.time; - LeaveCriticalSection(&TimeMutex); - return tb.time; -} - - -void BasicSearchThread(char *nick) { - PROTOSEARCHRESULT psr = { 0 }; - char *cmd = NULL, *token = NULL, *ptr = NULL, *nextoken; - time_t st; - - LOG(("BasicSearchThread started.")); - EnterCriticalSection(&QueryThreadMutex); - SkypeTime(&st); - if (SkypeSend("SEARCH USERS %s", nick) == 0 && (cmd = SkypeRcvTime("USERS", st, INFINITE))) { - if (strncmp(cmd, "ERROR", 5)) { - psr.cbSize = sizeof(psr); - for (token = strtok_r(cmd + 5, ", ", &nextoken); token; token = strtok_r(NULL, ", ", &nextoken)) { - psr.nick = psr.id = _A2T(token); - psr.lastName = NULL; - psr.firstName = NULL; - psr.email = NULL; - if (ptr = SkypeGet("USER", token, "FULLNAME")) { - // We cannot use strtok() to seperate first & last name here, - // because we already use it for parsing the user list - // So we use our own function - if (psr.lastName = _A2T(strchr(ptr, ' '))) { - *psr.lastName = 0; - psr.lastName++; - LOG(("BasicSearchThread: lastName=%s", psr.lastName)); - } - psr.firstName = _A2T(ptr); - LOG(("BasicSearchThread: firstName=%s", psr.firstName)); - } - ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)hSearchThread, (LPARAM)(PROTOSEARCHRESULT*)&psr); - if (ptr) free(ptr); - } - } - else { - OUT(cmd); - } - free(cmd); - } - ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)hSearchThread, 0); - free(nick); - LeaveCriticalSection(&QueryThreadMutex); - LOG(("BasicSearchThread terminated gracefully.")); - return; -} - -#ifdef IS_MIRANDAIM -INT_PTR SkypeDBWriteContactSettingUTF8String(HANDLE hContact,const char *szModule,const char *szSetting,const char *val) -{ - DBCONTACTWRITESETTING cws; - INT_PTR iRet; - - // Try to save it as UTF8 sting to DB. If this doesn't succeed (i.e. older Miranda version), we convert - // accordingly and try to save again. - - cws.szModule=szModule; - cws.szSetting=szSetting; - cws.value.type=DBVT_UTF8; - cws.value.pszVal=(char*)val; - // DBVT_UTF8 support started with version 0.5.0.0, right...? - if (mirandaVersion < 0x050000 || (iRet = CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)hContact,(LPARAM)&cws))) - { - // Failed, try to convert and then try again - cws.value.type=DBVT_TCHAR; - if (!(cws.value.ptszVal = make_tchar_string((const unsigned char*)val))) return -1; - iRet = CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)hContact,(LPARAM)&cws); - free (cws.value.pszVal); - } - return iRet; -} -#endif - -// added by TioDuke -void GetDisplaynameThread(char *dummy) { - DBVARIANT dbv; - char *ptr; - - UNREFERENCED_PARAMETER(dummy); - - LOG(("GetDisplaynameThread started.")); - if (db_get_s(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) { - LOG(("GetDisplaynameThread terminated.")); - return; - } - EnterCriticalSection(&QueryThreadMutex); - if ((ptr = SkypeGet("USER", dbv.pszVal, "FULLNAME"))) { - if (*ptr) db_set_utf(NULL, SKYPE_PROTONAME, "Nick", ptr); - free(ptr); - } - db_free(&dbv); - LeaveCriticalSection(&QueryThreadMutex); - LOG(("GetDisplaynameThread terminated gracefully.")); -} - - -// Starts importing history from Skype -INT_PTR ImportHistory(WPARAM wParam, LPARAM lParam) { - DBVARIANT dbv; - - UNREFERENCED_PARAMETER(lParam); - - if (db_get_b((MCONTACT)wParam, SKYPE_PROTONAME, "ChatRoom", 0)) { - if (db_get_s((MCONTACT)wParam, SKYPE_PROTONAME, "ChatRoomID", &dbv)) return 0; - SkypeSend("GET CHAT %s CHATMESSAGES", dbv.pszVal); - } - else { - if (db_get_s((MCONTACT)wParam, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) return 0; - SkypeSend("SEARCH %sS %s", cmdMessage, dbv.pszVal); - } - db_free(&dbv); - return 0; -} - -int SearchFriends(void) { - char *ptr, *token, *pStat, *nextoken; - int iRet = 0; - time_t st; - - SkypeTime(&st); - if (SkypeSend("SEARCH FRIENDS") != -1 && (ptr = SkypeRcvTime("USERS", st, INFINITE))) - { - if (strncmp(ptr, "ERROR", 5)) { - if (ptr + 5) { - for (token = strtok_r(ptr + 5, ", ", &nextoken); token; token = strtok_r(NULL, ", ", &nextoken)) { - if (!(pStat = SkypeGet("USER", token, "ONLINESTATUS"))) - { - iRet = -1; - break; - } - free(pStat); - } - } - } - else iRet = -1; - free(ptr); - } - else iRet = -1; - return iRet; -} - -static void QueryUserWaitingAuthorization(char *pszNick, char *pszAuthRq) -{ - CCSDATA ccs={0}; - PROTORECVEVENT pre={0}; - MCONTACT hContact; - char *firstname=NULL, *lastname=NULL, *pCurBlob, *authmsg=NULL; - - LOG(("Awaiting auth: %s", pszNick)); - ccs.szProtoService=PSR_AUTH; - ccs.hContact = hContact = add_contact(pszNick, PALF_TEMPORARY); - ccs.wParam = 0; - ccs.lParam = (LPARAM)⪯ - pre.flags = 0; - pre.timestamp = (DWORD)SkypeTime(NULL); - - /* blob is: */ - //DWORD protocolSpecific HANDLE hContact - //ASCIIZ nick, firstName, lastName, e-mail, requestReason - if (firstname=SkypeGet("USER", pszNick, "FULLNAME")) { - if (mirandaVersion < 0x070000) { - char *tmp; - - if (utf8_decode(firstname, &tmp)!=-1) { - free (firstname); - firstname = tmp; - } - } - if (lastname=strchr(firstname, ' ')) { - *lastname=0; - lastname++; - } - } - - pre.lParam = sizeof(DWORD) + sizeof(HANDLE) + strlen(pszNick) + 5; - if (firstname) pre.lParam += strlen(firstname); - if (lastname) pre.lParam += strlen(lastname); - if (pszAuthRq) authmsg = strdup(pszAuthRq); - if (authmsg || ((protocol>=4 || bIsImoproxy) && (authmsg=SkypeGetID("USER", pszNick, "RECEIVEDAUTHREQUEST")))) - pre.lParam+=strlen(authmsg); - if (pre.szMessage = pCurBlob = (char *)calloc(1, pre.lParam)) { - pCurBlob+=sizeof(DWORD); // Not used - memcpy(pCurBlob, &hContact, sizeof(HANDLE)); pCurBlob += sizeof(HANDLE); - - if (mirandaVersion >= 0x070000) // 0.7.0+ supports PREF_UTF flag, no need to decode UTF8 - pre.flags |= PREF_UTF; - else { - char *tmp; - - if (authmsg && utf8_decode(authmsg, &tmp)!=-1) { - free (authmsg); - authmsg = tmp; - } - } - - sprintf (pCurBlob, "%s%c%s%c%s%c%c%s", pszNick, 0, firstname?firstname:"", 0, lastname?lastname:"", 0, 0, authmsg?authmsg:""); - - CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs); - free(pre.szMessage); - } - if (firstname) free(firstname); - if (authmsg) free (authmsg); - return; -} - - -void __cdecl ProcessAuthRq(void *pPmsg) { - char *nick, *auth; - - strtok ((char*)pPmsg, " "); - nick = strtok (NULL, " "); - strtok (NULL, " "); - auth = strtok (NULL, ""); - QueryUserWaitingAuthorization(nick, auth); - free (pPmsg); -} - -void __cdecl SearchUsersWaitingMyAuthorization(void *dummy) { - char *cmd, *token, *nextoken; - - UNREFERENCED_PARAMETER(dummy); - - if (SkypeSend("#UWA SEARCH USERSWAITINGMYAUTHORIZATION")) return; - if (!(cmd = SkypeRcv("#UWA USERS", INFINITE))) return; - if (!strncmp(cmd, "ERROR", 5)) { - free(cmd); - return; - } - - token = strtok_r(cmd + 10, ", ", &nextoken); - while (token) { - QueryUserWaitingAuthorization (token, NULL); - token=strtok_r(NULL, ", ", &nextoken); - } - free(cmd); - return; -} - -void SearchFriendsThread(char *dummy) { - UNREFERENCED_PARAMETER(dummy); - - if (!SkypeInitialized) return; - LOG(("SearchFriendsThread started.")); - EnterCriticalSection(&QueryThreadMutex); - SkypeInitialized = FALSE; - SearchFriends(); - SkypeInitialized = TRUE; - LeaveCriticalSection(&QueryThreadMutex); - LOG(("SearchFriendsThread terminated gracefully.")); -} - -void __cdecl SearchRecentChats(void *dummy) { - char *cmd, *token, *nextoken; - - UNREFERENCED_PARAMETER(dummy); - - if (SkypeSend("#RCH SEARCH RECENTCHATS")) return; - if (!(cmd = SkypeRcv("#RCH CHATS", INFINITE))) return; - if (!strncmp(cmd, "ERROR", 5)) { - free(cmd); - return; - } - - for (token = strtok_r(cmd + 10, ", ", &nextoken); token; token = strtok_r(NULL, ", ", &nextoken)) { - char *pszStatus = SkypeGet("CHAT", token, "STATUS"); - - if (pszStatus) { - if (!strcmp(pszStatus, "MULTI_SUBSCRIBED")) { - // Add chatrooms for active multisubscribed chats - /*if (!find_chatA(token)) */{ - char *pszTopic; - - EnterCriticalSection(&QueryThreadMutex); - ChatStart(token, TRUE); - if (pszTopic = SkypeGet("CHAT", token, "TOPIC")) { - TCHAR *psztChatName, *psztTopic; - - if (!*pszTopic) { - free(pszTopic); - pszTopic = SkypeGet("CHAT", token, "FRIENDLYNAME"); - } - psztChatName = make_nonutf_tchar_string((const unsigned char*)token); - psztTopic = make_tchar_string((const unsigned char*)pszTopic); - SetChatTopic(psztChatName, psztTopic, FALSE); - free_nonutf_tchar_string(psztChatName); - free(psztTopic); - free(pszTopic); - } - LeaveCriticalSection(&QueryThreadMutex); - } - } - free(pszStatus); - } - } - free(cmd); - return; -} - - -void __cdecl SkypeSystemInit(char *dummy) { - static BOOL Initializing = FALSE; - DBVARIANT dbv = { 0 }; - - UNREFERENCED_PARAMETER(dummy); - - LOG(("SkypeSystemInit thread started.")); - if (SkypeInitialized || Initializing) - { - LOG(("SkypeSystemInit terminated, nothing to do.")); - return; - } - Initializing = TRUE; - // Do initial Skype-Tasks - logoff_contacts(FALSE); - // Add friends - - // Clear currentuserhandle entries from queue - while (testfor("CURRENTUSERHANDLE", 0)); - if (SkypeSend(SKYPE_PROTO) == -1 || !testfor("PROTOCOL", INFINITE) || - SkypeSend("GET CURRENTUSERHANDLE") == -1 || - SkypeSend("GET PRIVILEGE SKYPEOUT") == -1) { - Initializing = FALSE; - LOG(("SkypeSystemInit thread stopped with failure.")); - return; - } - - if (db_get_s(NULL, SKYPE_PROTONAME, "LoginUserName", &dbv) == 0) - { - if (*dbv.pszVal) - { - char *pszUser; - - // Username is set in Plugin, therefore we need to match it - // against CURRENTUSERHANDLE - if (pszUser = SkypeRcv("CURRENTUSERHANDLE", INFINITE)) - { - memmove(pszUser, pszUser + 18, strlen(pszUser + 17)); - if (_stricmp(dbv.pszVal, pszUser)) - { - char szError[256]; - - // Doesn't match, maybe we have a second Skype instance we have to take - // care of? If in doubt, let's wait a while for it to report its hWnd to us. - LOG(("Userhandle %s doesn't match username %s from settings", pszUser, dbv.pszVal)); - if (!hSkypeWndSecondary) Sleep(3000); - if (hSkypeWndSecondary) - { - hSkypeWnd = hSkypeWndSecondary; - hSkypeWndSecondary = NULL; - Initializing = FALSE; - while (testfor("CURRENTUSERHANDLE", 0)); - LOG(("Trying to init secondary Skype instance")); - SkypeSystemInit(dummy); - } - else - { - hForbiddenSkypeWnd = hSkypeWnd; - - // If we need to start Skype as secondary instance, we should do it now - if (db_get_b(NULL, SKYPE_PROTONAME, "StartSkype", 1) && - db_get_b(NULL, SKYPE_PROTONAME, "secondary", 0)) - { - int oldstatus; - - hSkypeWnd = NULL; - AttachStatus = -1; - if (g_hWnd) KillTimer(g_hWnd, 1); - oldstatus = SkypeStatus; - InterlockedExchange((long *)&SkypeStatus, ID_STATUS_CONNECTING); - ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldstatus, SkypeStatus); - ConnectToSkypeAPI(skype_path, 1); - } - if (hForbiddenSkypeWnd == hSkypeWnd && !hSkypeWndSecondary) - { - int oldstatus; - - sprintf(szError, "Username '%s' provided by Skype API doesn't match username '%s' in " - "your settings. Please either remove username setting in you configuration or correct " - "it. Will not connect!", pszUser, dbv.pszVal); - OUTPUTA(szError); - Initializing = FALSE; - AttachStatus = -1; - logoff_contacts(FALSE); - if (g_hWnd) KillTimer(g_hWnd, 1); - hSkypeWnd = NULL; - oldstatus = SkypeStatus; - InterlockedExchange((long *)&SkypeStatus, ID_STATUS_OFFLINE); - ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldstatus, SkypeStatus); - } - } - } - free(pszUser); - } - } - db_free(&dbv); - if (!Initializing) return; - } - -#ifdef SKYPEBUG_OFFLN - if (!ResetEvent(GotUserstatus) || SkypeSend("GET USERSTATUS") == -1 || - WaitForSingleObject(GotUserstatus, INFINITE) == WAIT_FAILED) - { - LOG(("SkypeSystemInit thread stopped with failure.")); - Initializing = FALSE; - return; - } - if (SkypeStatus != ID_STATUS_OFFLINE) -#endif - if (SearchFriends() == -1) { - LOG(("SkypeSystemInit thread stopped with failure.")); - Initializing = FALSE; - return; - } - if (protocol >= 5 || bIsImoproxy) { - SkypeSend("CREATE APPLICATION libpurple_typing"); - testfor("CREATE APPLICATION libpurple_typing", 2000); - } - if (protocol>=5) { - SearchUsersWaitingMyAuthorization(NULL); - if (db_get_b(NULL, SKYPE_PROTONAME, "UseGroupchat", 0)) - SearchRecentChats(NULL); - } - SkypeSend("SEARCH MISSED%sS", cmdMessage); - - -#ifndef SKYPEBUG_OFFLN - if (SkypeSend("GET USERSTATUS")==-1) - { - LOG (("SkypeSystemInit thread stopped with failure.")); - Initializing=FALSE; - return; - } -#endif - SetTimer(g_hWnd, 1, PING_INTERVAL, NULL); - SkypeInitialized = TRUE; - Initializing = FALSE; - LOG(("SkypeSystemInit thread terminated gracefully.")); - return; -} - -void FirstLaunch(char *dummy) { - int counter = 0; - - UNREFERENCED_PARAMETER(dummy); - - LOG(("FirstLaunch thread started.")); - if (!db_get_b(NULL, SKYPE_PROTONAME, "StartSkype", 1) || ConnectToSkypeAPI(skype_path, FALSE) == -1) - { - int oldstatus = SkypeStatus; - - LOG(("OnModulesLoaded starting offline..")); - InterlockedExchange((long *)&SkypeStatus, ID_STATUS_OFFLINE); - ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldstatus, SkypeStatus); - } - if (AttachStatus == -1 || AttachStatus == SKYPECONTROLAPI_ATTACH_REFUSED || AttachStatus == SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE) { - LOG(("FirstLaunch thread stopped because of invalid Attachstatus.")); - return; - } - - // When you launch Skype and Attach is Successfull, it still takes some time - // until it becomes available for receiving messages. - // Let's probe this with PINGing - LOG(("CheckIfApiIsResponding Entering test loop")); - for (;;) { - LOG(("Test #%d", counter)); - if (SkypeSend("PING") == -1) counter++; else break; - if (counter >= 20) { - OUTPUT(_T("Cannot reach Skype API, plugin disfunct.")); - LOG(("FirstLaunch thread stopped: cannot reach Skype API.")); - return; - } - Sleep(500); - } - LOG(("CheckIfApiIsResponding: Testing for PONG")); - testfor("PONG", 2000); // Flush PONG from MsgQueue - - pthread_create((pThreadFunc)SkypeSystemInit, NULL); - LOG(("FirstLaunch thread terminated gracefully.")); -} - -int CreateTopToolbarButton(WPARAM wParam, LPARAM lParam) { - TTBButton ttb = { 0 }; - - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(lParam); - - ttb.cbSize = sizeof(ttb); - ttb.dwFlags = TTBBF_VISIBLE | TTBBF_SHOWTOOLTIP; - ttb.name = Translate("Do a SkypeOut-call"); -#ifdef TTB_WINDOW_HANDLE - /* New Top toolbar */ - ttb.hIconHandleDn = ttb.hIconHandleUp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_CALL)); - ttb.pszService = SKYPEOUT_CALL; - if ((int)(TopToolbar_AddButton(&ttb)) == -1) httbButton = 0; -#else - /* Old Top toolbar */ - ttb.dwFlags |= TTBBF_DRAWBORDER; - ttb.hbBitmapDown = ttb.hbBitmapUp = LoadBitmap(hInst,MAKEINTRESOURCE(IDB_CALL)); - ttb.pszServiceDown = ttb.pszServiceUp = SKYPEOUT_CALL; - if ((int)(httbButton=(HANDLE)CallService(MS_TTB_ADDBUTTON, (WPARAM)&ttb, 0))==-1) httbButton=0; -#endif - return 0; -} - - -int OnModulesLoaded(WPARAM wParam, LPARAM lParam) { - bModulesLoaded = TRUE; - - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(lParam); - - PopupServiceExists = ServiceExists(MS_POPUP_ADDPOPUPT); - - logoff_contacts(FALSE); - - HookEventsLoaded(); - RegisterToUpdate(); - RegisterToDbeditorpp(); - VoiceServiceModulesLoaded(); - GCInit(); - - add_contextmenu(NULL); - if (ServiceExists(MS_GC_REGISTER)) - { - GCREGISTER gcr = {0}; - static COLORREF crCols[1] = {0}; - char szEvent[MAXMODULELABELLENGTH]; - - - gcr.cbSize = sizeof( GCREGISTER ); - gcr.dwFlags = GC_CHANMGR; // |GC_ACKMSG; // TODO: Not implemented yet -#ifdef GC_UNICODE - gcr.dwFlags |= GC_TCHAR; - gcr.ptszModuleDispName = _T("Skype protocol"); -#else - gcr.ptszDispName = _T("Skype protocol"); -#endif - gcr.pszModule = SKYPE_PROTONAME; - if (CallService(MS_GC_REGISTER, 0, (LPARAM)&gcr)) - OUTPUT(_T("Unable to register with Groupchat module!")); - - _snprintf(szEvent, sizeof(szEvent), "%s\\ChatInit", SKYPE_PROTONAME); - hInitChat = CreateHookableEvent(szEvent); - hEvInitChat = HookEvent(szEvent, ChatInit); - - hChatEvent = HookEvent(ME_GC_EVENT, GCEventHook); - hChatMenu = HookEvent(ME_GC_BUILDMENU, GCMenuHook); - CreateServiceFunction(SKYPE_CHATNEW, SkypeChatCreate); - CreateProtoService(PS_LEAVECHAT, GCOnLeaveChat); - CreateProtoService(PS_JOINCHAT, GCOnJoinChat); - } - // Try folder service first - hProtocolAvatarsFolder = NULL; - if (ServiceExists(MS_FOLDERS_REGISTER_PATH)) - { - char *tmpPath; - - if (!ServiceExists(MS_UTILS_REPLACEVARS) || !(tmpPath = Utils_ReplaceVars("%miranda_avatarcache%"))) - tmpPath = PROFILE_PATH; - mir_snprintf(DefaultAvatarsFolder, sizeof(DefaultAvatarsFolder), "%s\\%s", tmpPath, SKYPE_PROTONAME); - hProtocolAvatarsFolder = (HANDLE)FoldersRegisterCustomPath(SKYPE_PROTONAME, "Avatars Cache", DefaultAvatarsFolder); - } - - if (hProtocolAvatarsFolder == NULL) - { - // Use defaults - CallService(MS_DB_GETPROFILEPATH, (WPARAM)MAX_PATH, (LPARAM)DefaultAvatarsFolder); - mir_snprintf(DefaultAvatarsFolder, sizeof(DefaultAvatarsFolder), "%s\\%s", DefaultAvatarsFolder, SKYPE_PROTONAME); - CreateDirectoryA(DefaultAvatarsFolder, NULL); - } - - pthread_create((pThreadFunc)FirstLaunch, NULL); - return 0; -} - -void FetchMessageThread(fetchmsg_arg *pargs) { - char *who = NULL, *type = NULL, *chat = NULL, *users = NULL, *msg = NULL, *status = NULL; - char *ptr, *msgptr, szPartnerHandle[32], szBuf[128]; - int direction = 0, msglen = 0; - DWORD timestamp = 0, lwr = 0; - CCSDATA ccs = { 0 }; - PROTORECVEVENT pre = { 0 }; - MCONTACT hContact = NULL, hChat = NULL; - HANDLE hDbEvent; - DBEVENTINFO dbei = { 0 }; - DBVARIANT dbv = { 0 }; - fetchmsg_arg args; - BOOL bEmoted = FALSE, isGroupChat = FALSE, bHasPartList = FALSE; - BOOL bUseGroupChat = db_get_b(NULL, SKYPE_PROTONAME, "UseGroupchat", 0); - - if (!pargs) return; - args = *pargs; - free(pargs); - - sprintf(szPartnerHandle, "%s_HANDLE", cmdPartner); - pre.lParam = strtoul(args.msgnum, NULL, 10); - if (args.bIsRead) pre.flags |= PREF_CREATEREAD; - //pEvent = MsgList_FindMessage(pre.lParam); - - // Get Timestamp - if (!args.pMsgEntry || !args.pMsgEntry->tEdited) { - if (!(ptr=SkypeGet (cmdMessage, args.msgnum, "TIMESTAMP"))) return; - if (strncmp(ptr, "ERROR", 5)) { - timestamp=atol(ptr); - // Ensure time correction on clock skew... - if (timestamp>(DWORD)SkypeTime(NULL)) timestamp=(DWORD)SkypeTime(NULL); - } - else timestamp=(DWORD)SkypeTime(NULL); - free(ptr); - } - else timestamp = (DWORD)(args.pMsgEntry->tEdited); - - __try { - // Get Chatname (also to determine if we need to relay this to a groupchat) - if (!(chat = SkypeGetErr(cmdMessage, args.msgnum, "CHATNAME"))) __leave; - if (hChat = find_chatA(chat)) isGroupChat = TRUE; - - // Get chat status - if ((status = SkypeGetErr("CHAT", chat, "STATUS")) && - !strcmp(status, "MULTI_SUBSCRIBED")) isGroupChat = TRUE; - - // Get chat type - if (!(type = SkypeGetErr(cmdMessage, args.msgnum, "TYPE"))) __leave; - bEmoted = strcmp(type, "EMOTED") == 0; - if (strcmp(type, "MULTI_SUBSCRIBED") == 0) isGroupChat = TRUE; - - // Group chat handling - if (isGroupChat && strcmp(type, "TEXT") && strcmp(type, "SAID") && strcmp(type, "UNKNOWN") && !bEmoted) { - if (bUseGroupChat) { - BOOL bAddedMembers = FALSE; - - if (!strcmp(type, "SAWMEMBERS") || !strcmp(type, "CREATEDCHATWITH")) - { - // We have a new Groupchat - LOG(("FetchMessageThread CHAT SAWMEMBERS")); - if (!hChat) ChatStart(chat, FALSE); - __leave; - } - if (!strcmp(type, "KICKED")) - { - GCDEST gcd = {0}; - GCEVENT gce = {0}; - CONTACTINFO ci = {0}; - - if (!hChat) __leave; - gcd.pszModule = SKYPE_PROTONAME; - gcd.ptszID = make_nonutf_tchar_string((const unsigned char*)chat); - gcd.iType = GC_EVENT_KICK; - gce.cbSize = sizeof(GCEVENT); - gce.pDest = &gcd; - gce.dwFlags = GCEF_ADDTOLOG | GC_TCHAR; - gce.time = timestamp; - - if (users = SkypeGetErr(cmdMessage, args.msgnum, "USERS")) { - - ci.hContact = find_contact(users); - gce.ptszUID = make_nonutf_tchar_string((const unsigned char*)users); - if (who = SkypeGetErr(cmdMessage, args.msgnum, szPartnerHandle)) { - gce.ptszStatus = make_nonutf_tchar_string((const unsigned char*)who); - ci.cbSize = sizeof(ci); - ci.szProto = SKYPE_PROTONAME; - ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; - if (ci.hContact && !CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci)) gce.ptszNick = ci.pszVal; - else gce.ptszNick = gce.ptszUID; - - CallService(MS_GC_EVENT, 0, (LPARAM)&gce); - RemChatContact(GetChat(gcd.ptszID), gce.ptszUID); - free_nonutf_tchar_string((void*)gce.ptszStatus); - if (ci.pszVal) mir_free(ci.pszVal); - } - free_nonutf_tchar_string((void*)gce.ptszUID); - } - free_nonutf_tchar_string((void*)gcd.ptszID); - __leave; - } - if (!strcmp(type, "SETROLE")) - { - GCDEST gcd = {0}; - GCEVENT gce = {0}; - CONTACTINFO ci = {0}; - gchat_contact *gcContact; - char *pszRole; - - // FROM_HANDLE - Wer hats gesetzt - // USERS - Wessen Rolle wurde gesetzt - // ROLE - Die neue Rolle - if (!hChat) __leave; - gcd.pszModule = SKYPE_PROTONAME; - gcd.ptszID = make_nonutf_tchar_string((const unsigned char*)chat); - gcd.iType = GC_EVENT_REMOVESTATUS; - gce.cbSize = sizeof(GCEVENT); - gce.pDest = &gcd; - gce.dwFlags = GCEF_ADDTOLOG | GC_TCHAR; - gce.time = timestamp; - - if (users = SkypeGetErr(cmdMessage, args.msgnum, "USERS")) { - gce.ptszUID = make_nonutf_tchar_string((const unsigned char*)users); - if (who = SkypeGetErr(cmdMessage, args.msgnum, szPartnerHandle)) { - - ci.cbSize = sizeof(ci); - ci.szProto = SKYPE_PROTONAME; - ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; - ci.hContact = find_contact(who); - if (ci.hContact && !CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci)) { - gce.ptszText = _tcsdup(ci.pszVal); - mir_free(ci.pszVal); - ci.pszVal = NULL; - } - else gce.ptszText = make_tchar_string((const unsigned char*)who); - - ci.hContact = find_contact(users); - if (ci.hContact && !CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci)) gce.ptszNick = ci.pszVal; - else gce.ptszNick = gce.ptszUID; - - if (gcContact = GetChatContact(GetChat(gcd.ptszID), gce.ptszUID)) - { - gce.ptszStatus = gcContact->szRole; - CallService(MS_GC_EVENT, 0, (LPARAM)&gce); - } - if (pszRole = SkypeGetErr(cmdMessage, args.msgnum, "ROLE")) { - gce.ptszStatus = make_nonutf_tchar_string((const unsigned char*)pszRole); - gcd.iType = GC_EVENT_ADDSTATUS; - CallService(MS_GC_EVENT, 0, (LPARAM)&gce); - free_nonutf_tchar_string((void*)gce.ptszStatus); - free(pszRole); - } - free((void*)gce.ptszText); - if (ci.pszVal) mir_free(ci.pszVal); - } - free_nonutf_tchar_string((void*)gce.ptszUID); - } - free_nonutf_tchar_string((void*)gcd.ptszID); - __leave; - } - if (!strcmp(type, "SETTOPIC")) - { - GCDEST gcd = {0}; - GCEVENT gce = {0}; - CONTACTINFO ci = {0}; - - LOG(("FetchMessageThread CHAT SETTOPIC")); - gcd.pszModule = SKYPE_PROTONAME; - gcd.ptszID = make_nonutf_tchar_string((const unsigned char*)chat); - gcd.iType = GC_EVENT_TOPIC; - gce.cbSize = sizeof(GCEVENT); - gce.pDest = &gcd; - gce.dwFlags = GCEF_ADDTOLOG | GC_TCHAR; - gce.time = timestamp; - if (who = SkypeGetErr(cmdMessage, args.msgnum, szPartnerHandle)) { - - ci.hContact = find_contact(who); - gce.ptszUID = make_nonutf_tchar_string((const unsigned char*)who); - ci.cbSize = sizeof(ci); - ci.szProto = SKYPE_PROTONAME; - ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; - if (ci.hContact && !CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci)) gce.ptszNick = ci.pszVal; - else gce.ptszNick = gce.ptszUID; - - if (ptr = SkypeGetErr(cmdMessage, args.msgnum, "BODY")) { - gce.ptszText = make_tchar_string((const unsigned char*)ptr); - CallService(MS_GC_EVENT, 0, (LPARAM)&gce); - free((void*)gce.ptszText); - free(ptr); - } - free_nonutf_tchar_string((void*)gce.ptszUID); - if (ci.pszVal) mir_free(ci.pszVal); - } - free_nonutf_tchar_string((void*)gcd.ptszID); - if (!args.bDontMarkSeen) - { - MsgList_Add(pre.lParam, INVALID_HANDLE_VALUE); - SkypeSend("SET %s %s SEEN", cmdMessage, args.msgnum); - } - __leave; - } - if (!strcmp(type, "LEFT") || (bAddedMembers = strcmp(type, "ADDEDMEMBERS") == 0)) - { - GCDEST gcd = {0}; - GCEVENT gce = {0}; - CONTACTINFO ci = {0}; - char *pszInvited = Translate("invited"); - - LOG(("FetchMessageThread CHAT LEFT or ADDEDMEMBERS")); - if (bAddedMembers) { - gcd.pszModule = SKYPE_PROTONAME; - gcd.ptszID = make_nonutf_tchar_string((const unsigned char*)chat); - gcd.iType = GC_EVENT_ACTION; - gce.cbSize = sizeof(GCEVENT); - gce.pDest = &gcd; - gce.dwFlags = GCEF_ADDTOLOG | GC_TCHAR; - gce.time = timestamp; - if (users = SkypeGetErr(cmdMessage, args.msgnum, "USERS")) { - // We assume that users buffer has enough room for "invited" string - memmove (users+strlen(pszInvited), users, strlen(users)+1); - memcpy (users, pszInvited, strlen(pszInvited)); - gce.ptszText = make_tchar_string((const unsigned char*)users); - if (who = SkypeGetErr(cmdMessage, args.msgnum, szPartnerHandle)) { - DBVARIANT dbv; - if (db_get_s(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv) == 0) { - gce.bIsMe = strcmp(who, dbv.pszVal) == 0; - db_free(&dbv); - } - gce.ptszUID = make_nonutf_tchar_string((const unsigned char*)who); - - ci.cbSize = sizeof(ci); - if (!gce.bIsMe) - ci.hContact = find_contact(who); - ci.szProto = SKYPE_PROTONAME; - ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; - if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci)) - gce.ptszNick = ci.pszVal; - else - gce.ptszNick = gce.ptszUID; - - CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce); - free_nonutf_tchar_string((void*)gce.ptszUID); - if (ci.pszVal) mir_free(ci.pszVal); - } - if (gce.ptszText) free((void*)gce.ptszText); - } - free_nonutf_tchar_string((void*)gcd.ptszID); - } - if (!args.QueryMsgDirection) SkypeSend("GET CHAT %s MEMBERS", chat); - __leave; - } - } - __leave; - } - - // Need to get the status? - if (args.getstatus) { - char *status; - - if (protocol < 4) InterlockedIncrement(&rcvwatchers); - status = SkypeGetID(cmdMessage, args.msgnum, "STATUS"); - if (protocol < 4) InterlockedDecrement(&rcvwatchers); - if (!status) __leave; - if (!strcmp(status, "SENT")) direction = DBEF_SENT; - free(status); - } - - // Who sent it? - if (!(who = SkypeGetErr(cmdMessage, args.msgnum, szPartnerHandle))) __leave; - - // Get contact handle - LOG(("FetchMessageThread Finding contact handle")); - db_get_s(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv); - if (dbv.pszVal && !strcmp(who, dbv.pszVal)) - { - char *pTok, *nextoken; - - // It's from me.. But to whom? - // CHATMESSAGE .. USERS doesn't return anything, so we have to query the CHAT-Object - if (!(ptr = SkypeGetErr("CHAT", chat, "ACTIVEMEMBERS"))) { - db_free(&dbv); - __leave; - } - - for (pTok = strtok_r(ptr, " ", &nextoken); pTok; pTok = strtok_r(NULL, " ", &nextoken)) { - if (strcmp(pTok, dbv.pszVal)) break; // Take the first dude in the list who is not me - } - - if (!pTok) { - free(ptr); - db_free(&dbv); - __leave; // We failed - } - free(who); - who = (char *)memmove(ptr, pTok, strlen(pTok) + 1); - direction = DBEF_SENT; - } - db_free(&dbv); - - if (!(hContact = find_contact(who))) { - // Permanent adding of user obsolete, we use the BUDDYSTATUS now (bug #0000005) - ResetEvent(hBuddyAdded); - SkypeSend("GET USER %s BUDDYSTATUS", who); - WaitForSingleObject(hBuddyAdded, INFINITE); - if (!(hContact = find_contact(who))) { - // Arrgh, the user has been deleted from contact list. - // In this case, we add him temp. to receive the msg at least. - hContact = add_contact(who, PALF_TEMPORARY); - } - } - // Text which was sent (on edited msg, BODY may already be in queue, check) - sprintf(szBuf, "GET %s %s BODY", cmdMessage, args.msgnum); - if (!args.pMsgEntry || !args.pMsgEntry->tEdited || !(ptr = SkypeRcv(szBuf + 4, 1000))) - { - if (SkypeSend(szBuf) == -1 || !(ptr = SkypeRcv(szBuf + 4, INFINITE))) - __leave; - } - if (strncmp(ptr, "ERROR", 5)) { - msgptr = ptr + strlen(szBuf + 4) + 1; - bHasPartList = strncmp(msgptr, "tEdited) { - // Mark the message as edited - if (!*msgptr && args.pMsgEntry->hEvent != INVALID_HANDLE_VALUE) { - // Empty message and edited -> Delete event - if ((int)(hContact = db_event_getContact(args.pMsgEntry->hEvent)) != -1) { - db_event_delete(hContact, args.pMsgEntry->hEvent); - free(ptr); - __leave; - } - } - else { - msgptr -= 9; - memcpy(msgptr, "[EDITED] ", 9); - } - } - if (bEmoted && !isGroupChat) { - CONTACTINFO ci = { 0 }; - int newlen; - char *pMsg, *pszUTFnick = NULL; - ci.cbSize = sizeof(ci); - ci.szProto = SKYPE_PROTONAME; - ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; - if (ci.hContact = hContact) { - CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci); - if (ci.pszVal) { -#ifdef _UNICODE - pszUTFnick = (char*)make_utf8_string(ci.pszVal); -#else - utf8_encode (ci.pszVal, &pszUTFnick); -#endif - mir_free(ci.pszVal); - } - } - newlen = strlen(msgptr) + (pszUTFnick ? strlen(pszUTFnick) : 0) + 9; - if (pMsg = (char *)malloc(newlen)) { - sprintf(pMsg, "** %s%s%s **", (pszUTFnick ? pszUTFnick : ""), (pszUTFnick ? " " : ""), (char*)msgptr); - free(ptr); - ptr = msgptr = pMsg; - } - if (pszUTFnick) free(pszUTFnick); - } - - if (mirandaVersion >= 0x070000 && // 0.7.0+ supports PREF_UTF flag, no need to decode UTF8 - !isGroupChat) { // I guess Groupchat doesn't support UTF8? - msg = ptr; - pre.flags |= PREF_UTF; - } - else { // Older version has to decode either UTF8->ANSI or UTF8->UNICODE - // This could be replaced by mir_getUTFI - functions for Miranda 0.5+ builds, but we stay - // 0.4 compatible for backwards compatibility. Unfortunately this requires us to link with utf8.c -#ifdef _UNICODE - int wcLen; -#endif - - if (utf8_decode(msgptr, &msg) == -1) { - free(ptr); - __leave; - } -#ifdef _UNICODE - msglen = (int)strlen(msg) + 1; - msgptr = (char*)make_unicode_string((const unsigned char*)msgptr); - wcLen = (int)(_tcslen((TCHAR*)msgptr) + 1)*sizeof(TCHAR); - msg = (char*)realloc(msg, msglen + wcLen); - memcpy(msg + msglen, msgptr, wcLen); - free(msgptr); - pre.flags |= PREF_UNICODE; -#endif - msgptr = msg; - free(ptr); - } - msglen = (int)strlen(msgptr) + 1; - } - else { - free(ptr); - __leave; - } - // skype sends some xml statics after a call has finished. Check if thats the case and suppress it if necessary... - if ((db_get_b(NULL, SKYPE_PROTONAME, "SuppressCallSummaryMessage", 1) && - bHasPartList) || msgptr[0] == 0) __leave; - - if (isGroupChat && bUseGroupChat) { - - GCDEST gcd = { 0 }; - GCEVENT gce = { sizeof(gce), &gcd }; - DBVARIANT dbv = { 0 }; - CONTACTINFO ci = { 0 }; - - LOG(("FetchMessageThread This is a group chat message")); - if (!hChat) ChatStart(chat, FALSE); - gcd.pszModule = SKYPE_PROTONAME; - gcd.ptszID = make_nonutf_tchar_string((const unsigned char*)chat); - gcd.iType = bEmoted?GC_EVENT_ACTION:GC_EVENT_MESSAGE; - if ((gce.bIsMe = (direction&DBEF_SENT) ? TRUE : FALSE) && db_get_s(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv) == 0) - { - free(who); - who = _strdup(dbv.pszVal); - db_free(&dbv); - } - gce.ptszUID = make_nonutf_tchar_string((const unsigned char*)who); - gce.ptszNick = gce.ptszUID; - - ci.cbSize = sizeof(ci); - ci.szProto = SKYPE_PROTONAME; - ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; - ci.hContact = !gce.bIsMe ? hContact : NULL; - if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci)) - gce.ptszNick = ci.pszVal; - gce.time = timestamp > 0 ? timestamp : (DWORD)SkypeTime(NULL); - gce.ptszText = (TCHAR*)msgptr; - if (pre.flags & PREF_UNICODE) *((char**)&gce.ptszText) += msglen; - gce.dwFlags = GCEF_ADDTOLOG | GC_TCHAR; - CallService(MS_GC_EVENT, 0, (LPARAM)&gce); - MsgList_Add(pre.lParam, INVALID_HANDLE_VALUE); // Mark as groupchat - if (ci.pszVal) mir_free(ci.pszVal); - free_nonutf_tchar_string((void*)gce.ptszUID); - free_nonutf_tchar_string((void*)gcd.ptszID); - - // Yes, we have successfully read the msg - if (!args.bDontMarkSeen) - SkypeSend("SET %s %s SEEN", cmdMessage, args.msgnum); - __leave; - } - - if (args.QueryMsgDirection || (direction&DBEF_SENT)) { - // Check if the timestamp is valid - dbei.cbSize = sizeof(dbei); - dbei.cbBlob = 0; - if (hDbEvent = db_event_first(hContact)) { - db_event_get(hDbEvent, &dbei); - lwr = dbei.timestamp; - } - dbei.cbSize = sizeof(dbei); - dbei.cbBlob = 0; - dbei.timestamp = 0; - if (hDbEvent = db_event_last(hContact)) - db_event_get(hDbEvent, &dbei); - LOG(("FetchMessageThread timestamp %ld between %ld and %ld", timestamp, lwr, dbei.timestamp)); - if (timestamp < lwr || (direction&DBEF_SENT)) { - TYP_MSGLENTRY *pme; - - LOG(("FetchMessageThread Adding event")); - if (!(dbei.szModule = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0))) - dbei.szModule = SKYPE_PROTONAME; - dbei.cbBlob = msglen; - if (pre.flags & PREF_UNICODE) - dbei.cbBlob += sizeof(WCHAR)*((DWORD)wcslen((WCHAR*)&msgptr[dbei.cbBlob]) + 1); - dbei.pBlob = (PBYTE)msgptr; - dbei.timestamp = timestamp > 0 ? timestamp : (DWORD)SkypeTime(NULL); - dbei.flags = direction; - if (pre.flags & PREF_CREATEREAD) dbei.flags |= DBEF_READ; - if (pre.flags & PREF_UTF) dbei.flags |= DBEF_UTF; - dbei.eventType = EVENTTYPE_MESSAGE; - pme = MsgList_Add(pre.lParam, db_event_add(hContact, &dbei)); - - // We could call MS_PROTO_CHAINSEND if we want to have MetaContact adding the history for us, - // however we all know that CCSDATA doesn't contain timestamp-information which is - // really bad on importing history for example, as all messages would be added with current - // timestamp. This would cause unreliable jumbled timestamps in metacontact, so we better do this - // ourself. - if (db_mc_isSub(hContact)) { - DWORD dwMetaLink = db_get_dw(hContact, "MetaContacts", "MetaLink", MAXDWORD); - MCONTACT hMetaContact; - - if (dwMetaLink != MAXDWORD && (hMetaContact = GetMetaHandle(dwMetaLink))) { - dbei.szModule = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hMetaContact, 0); - pme->hMetaEvent = db_event_add(hMetaContact, &dbei); - } - } - - if (!args.QueryMsgDirection && !args.bDontMarkSeen) - SkypeSend("SET %s %s SEEN", cmdMessage, args.msgnum); - } - } - - - if (!(direction&DBEF_SENT) && (!args.QueryMsgDirection || (args.QueryMsgDirection && timestamp > dbei.timestamp))) { - LOG(("FetchMessageThread Normal message add...")); - // Normal message received, process it - ccs.szProtoService = PSR_MESSAGE; - ccs.hContact = hContact; - ccs.wParam = 0; - ccs.lParam = (LPARAM)⪯ - pre.flags |= direction; - if (isGroupChat && db_get_b(NULL, SKYPE_PROTONAME, "MarkGroupchatRead", 0)) - pre.flags |= PREF_CREATEREAD; - pre.timestamp = timestamp > 0 ? timestamp : (DWORD)SkypeTime(NULL); - pre.szMessage = msgptr; - CallServiceSync(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs); - - // Yes, we have successfully read the msg - if (!args.bDontMarkSeen) SkypeSend("SET %s %s SEEN", cmdMessage, args.msgnum); - } - } - __finally { - if (status) free(status); - if (msg) free(msg); - if (users) free(users); - if (chat) free(chat); - if (type) free(type); - if (who) free(who); - } - -} - -void FetchMessageThreadSync(fetchmsg_arg *pargs) { - // Secure this thread with a mutex. - // This is needed to ensure that we get called after an old msg in the queue has - // been added so that MsgList_FindEntry will find it. - WaitForSingleObject(FetchMessageEvent, 30000); // Wait max. 30 sec. for previous message fetch to complete - if ((pargs->pMsgEntry = MsgList_FindMessage(strtoul(pargs->msgnum, NULL, 10))) && !pargs->pMsgEntry->tEdited) { - // Better don't do this, as we set the msg as read and with this code, we would - // mark messages not opened by user as read which isn't that good - /* - if (pargs->bIsRead && pMsgEvent->hEvent != INVALID_HANDLE_VALUE) - { - MCONTACT hContact; - if ((int)(hContact = (MCONTACT)CallService (MS_DB_EVENT_GETCONTACT, (WPARAM)pMsgEntry->hEvent, 0)) != -1) - CallService (MS_DB_EVENT_MARKREAD, hContact, (LPARAM)hDBEvent); - } - */ - free(pargs); - } - else FetchMessageThread(pargs); - SetEvent(FetchMessageEvent); -} - -static int MsglCmpProc(const void *pstPElement, const void *pstPToFind) -{ - return strcmp((char*)((fetchmsg_arg*)pstPElement)->pMsgEntry, (char*)((fetchmsg_arg*)pstPToFind)->pMsgEntry); -} - -void MessageListProcessingThread(char *str) { - char *token, *nextoken, *chat = NULL; - fetchmsg_arg *args; - TYP_LIST *hListMsgs = List_Init(32); - int i, nCount; - - // Frst we need to sort the message timestamps - for ((token = strtok_r(str, ", ", &nextoken)); token; token = strtok_r(NULL, ", ", &nextoken)) { - if (args = (fetchmsg_arg*)calloc(1, sizeof(fetchmsg_arg) + sizeof(DWORD))) { - strncpy(args->msgnum, token, sizeof(args->msgnum)); - args->getstatus = TRUE; - args->bIsRead = TRUE; - args->bDontMarkSeen = TRUE; - args->QueryMsgDirection = TRUE; - args->pMsgEntry = (TYP_MSGLENTRY*)SkypeGet("CHATMESSAGE", token, "TIMESTAMP"); - if (!chat) chat = SkypeGet("CHATMESSAGE", token, "CHATNAME"); - if (args->pMsgEntry) List_InsertSort(hListMsgs, MsglCmpProc, args); - else free(args); - } - } - for (i = 0, nCount = List_Count(hListMsgs); i < nCount; i++) { - args = (fetchmsg_arg*)List_ElementAt(hListMsgs, i); - free(args->pMsgEntry); - args->pMsgEntry = NULL; - FetchMessageThreadSync(args); - } - if (chat) { - SkypeSend("GET CHAT %s MEMBERS", chat); - free(chat); - } - List_Exit(hListMsgs); - free(str); -} - -char *GetCallerHandle(char *szSkypeMsg) { - return SkypeGet(szSkypeMsg, "PARTNER_HANDLE", ""); -} - - -MCONTACT GetCallerContact(char *szSkypeMsg) -{ - char *szHandle; - MCONTACT hContact = NULL; - - if (!(szHandle = GetCallerHandle(szSkypeMsg))) return NULL; - if (!(hContact = find_contact(szHandle))) { - // If it's a SkypeOut-contact, PARTNER_HANDLE = SkypeOUT number - DBVARIANT dbv; - int tCompareResult; - - for (hContact = db_find_first(SKYPE_PROTONAME); hContact != NULL; hContact = db_find_next(hContact)) { - if (db_get_s(hContact, SKYPE_PROTONAME, "SkypeOutNr", &dbv)) continue; - tCompareResult = strcmp(dbv.pszVal, szHandle); - db_free(&dbv); - if (tCompareResult) continue; else break; - } - } - free(szHandle); - if (!hContact) { LOG(("GetCallerContact Not found!")); } - return hContact; -} - -MCONTACT GetMetaHandle(DWORD dwId) -{ - MCONTACT hContact; - - for (hContact = db_find_first(SKYPE_PROTONAME); hContact != NULL; hContact = db_find_next(hContact)) { - char *szProto = GetContactProto(hContact); - if (szProto != NULL && !strcmp(szProto, "MetaContacts") && - db_get_dw(hContact, "MetaContacts", "MetaID", MAXDWORD) == dwId) - return hContact; - } - return 0; -} - -LRESULT CALLBACK InCallPopUpProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) - { - case WM_COMMAND: - break; - - case WM_CONTEXTMENU: - SendMessage(hwnd, UM_DESTROYPOPUP, 0, 0); - break; - case UM_FREEPLUGINDATA: - //Here we'd free our own data, if we had it. - return FALSE; - case UM_INITPOPUP: - break; - case UM_DESTROYPOPUP: - break; - case WM_NOTIFY: - default: - break; - } - return DefWindowProc(hwnd, msg, wParam, lParam); -} - -void RingThread(char *szSkypeMsg) { - MCONTACT hContact; - DBEVENTINFO dbei = { 0 }; - DBVARIANT dbv; - char *ptr = NULL; - - // We use a single critical section for the RingThread- and the EndCallThread-functions - // so that only one function is running at the same time. This is needed, because when - // a initated and unaccepted call (which is still ringing) is hangup/canceled, skype - // sends two messages. First "CALL xxx STATUS RINGING" .. second "CALL xx STATUS CANCELED". - // This starts two independend threads (first: RingThread; second: EndCallThread). Now - // the two message are processed in reverse order sometimes. This causes the EndCallThread to - // delete the contacts "CallId" property and after that the RingThread saves the contacts - // "CallId" again. After that its not possible to call this contact, because the plugin - // thinks that there is already a call going and the hangup-function isnt working, because - // skype doesnt accept status-changes for finished calls. The CriticalSection syncronizes - // the threads and the messages are processed in correct order. - // Not the best solution, but it works. - EnterCriticalSection(&RingAndEndcallMutex); - - LOG(("RingThread started.")); - if (protocol >= 5) SkypeSend("MINIMIZE"); - if (hContact = GetCallerContact(szSkypeMsg)) { - // Make sure that an answering thread is not already in progress so that we don't get - // the 'Incoming call' event twice - if (!db_get_s(hContact, SKYPE_PROTONAME, "CallId", &dbv)) { - db_free(&dbv); - LOG(("RingThread terminated.")); - goto l_exitRT; - } - db_set_s(hContact, SKYPE_PROTONAME, "CallId", szSkypeMsg); - } - - if (!(ptr = SkypeGet(szSkypeMsg, "TYPE", ""))) { - LOG(("RingThread terminated.")); - goto l_exitRT;; - } - - if (!strncmp(ptr, "INCOMING", 8)) - NofifyVoiceService(hContact, szSkypeMsg, VOICE_STATE_RINGING); - else - NofifyVoiceService(hContact, szSkypeMsg, VOICE_STATE_CALLING); - - if (!strncmp(ptr, "INCOMING", 8)) { - if (!hContact) { - char *szHandle; - - if (szHandle = GetCallerHandle(szSkypeMsg)) { - if (!(hContact = add_contact(szHandle, PALF_TEMPORARY))) { - free(szHandle); - goto l_exitRT; - } - db_unset(hContact, "CList", "Hidden"); - db_set_w(hContact, SKYPE_PROTONAME, "Status", (WORD)SkypeStatusToMiranda("SKYPEOUT")); - db_set_s(hContact, SKYPE_PROTONAME, "SkypeOutNr", szHandle); - free(szHandle); - } - else goto l_exitRT; - } - } - - if (HasVoiceService()) { - // Voice service will handle it - goto l_exitRT; - } - - dbei.cbSize = sizeof(dbei); - dbei.eventType = EVENTTYPE_CALL; - dbei.szModule = SKYPE_PROTONAME; - dbei.timestamp = (DWORD)SkypeTime(NULL); - dbei.pBlob = (unsigned char*)Translate("Phone call"); - dbei.cbBlob = strlen((const char*)dbei.pBlob) + 1; - if (!strncmp(ptr, "INCOMING", 8)) - { - CLISTEVENT cle = { 0 }; - char toolTip[256]; - - if (PopupServiceExists) - { - BOOL showPopup, popupWindowColor; - unsigned int popupBackColor, popupTextColor; - int popupTimeSec; - POPUPDATAT InCallPopup; - TCHAR * lpzContactName = (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR); - - popupTimeSec = db_get_dw(NULL, SKYPE_PROTONAME, "popupTimeSec", 4); - popupTextColor = db_get_dw(NULL, SKYPE_PROTONAME, "popupTextColor", GetSysColor(COLOR_WINDOWTEXT)); - popupBackColor = db_get_dw(NULL, SKYPE_PROTONAME, "popupBackColor", GetSysColor(COLOR_BTNFACE)); - popupWindowColor = (0 != db_get_b(NULL, SKYPE_PROTONAME, "popupWindowColor", TRUE)); - showPopup = (0 != db_get_b(NULL, SKYPE_PROTONAME, "showPopup", TRUE)); - - InCallPopup.lchContact = hContact; - InCallPopup.lchIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_CALL)); - InCallPopup.colorBack = !popupWindowColor ? popupBackColor : GetSysColor(COLOR_BTNFACE); - InCallPopup.colorText = !popupWindowColor ? popupTextColor : GetSysColor(COLOR_WINDOWTEXT); - InCallPopup.iSeconds = popupTimeSec; - InCallPopup.PluginWindowProc = (WNDPROC)InCallPopUpProc; - InCallPopup.PluginData = (void *)1; - - lstrcpy(InCallPopup.lptzText, TranslateT("Incoming Skype Call")); - - lstrcpy(InCallPopup.lptzContactName, lpzContactName); - - if (showPopup) - CallService(MS_POPUP_ADDPOPUPT, (WPARAM)&InCallPopup, 0); - - } - cle.cbSize = sizeof(cle); - cle.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_CALL)); - cle.pszService = SKYPE_ANSWERCALL; - dbei.flags = DBEF_READ; - cle.hContact = hContact; - cle.hDbEvent = db_event_add(hContact, &dbei); - _snprintf(toolTip, sizeof(toolTip), Translate("Incoming call from %s"), (char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0)); - cle.pszTooltip = toolTip; - CallServiceSync(MS_CLIST_ADDEVENT, 0, (LPARAM)&cle); - } - else - { - dbei.flags = DBEF_SENT; - db_event_add(hContact, &dbei); - } - -l_exitRT: - if (ptr) free(ptr); - free(szSkypeMsg); - LeaveCriticalSection(&RingAndEndcallMutex); -} - -void EndCallThread(char *szSkypeMsg) { - MCONTACT hContact = NULL; - HANDLE hDbEvent; - DBEVENTINFO dbei = { 0 }; - DBVARIANT dbv; - int tCompareResult; - - // We use a single critical section for the RingThread- and the EndCallThread-functions - // so that only one function is running at the same time. This is needed, because when - // a initated and unaccepted call (which is still ringing) is hangup/canceled, skype - // sends two messages. First "CALL xxx STATUS RINGING" .. second "CALL xx STATUS CANCELED". - // This starts two independend threads (first: RingThread; second: EndCallThread). Now - // the two message are processed in reverse order sometimes. This causes the EndCallThread to - // delete the contacts "CallId" property and after that the RingThread saves the contacts - // "CallId" again. After that its not possible to call this contact, because the plugin - // thinks that there is already a call going and the hangup-function isnt working, because - // skype doesnt accept status-changes for finished calls. The CriticalSection syncronizes - // the threads and the messages are processed in correct order. - // Not the best solution, but it works. - EnterCriticalSection(&RingAndEndcallMutex); - - LOG(("EndCallThread started.")); - if (szSkypeMsg) { - for (hContact = db_find_first(SKYPE_PROTONAME); hContact != NULL; hContact = db_find_next(hContact)) { - if (db_get_s(hContact, SKYPE_PROTONAME, "CallId", &dbv)) continue; - tCompareResult = strcmp(dbv.pszVal, szSkypeMsg); - db_free(&dbv); - if (tCompareResult) continue; else break; - } - } - if (hContact) - { - NofifyVoiceService(hContact, szSkypeMsg, VOICE_STATE_ENDED); - - db_unset(hContact, SKYPE_PROTONAME, "CallId"); - - if (!HasVoiceService()) { - dbei.cbSize = sizeof(dbei); - hDbEvent = db_event_firstUnread(hContact); - while (hDbEvent) { - dbei.cbBlob = 0; - db_event_get(hDbEvent, &dbei); - if (!(dbei.flags&(DBEF_SENT | DBEF_READ)) && dbei.eventType == EVENTTYPE_CALL) { - db_event_markRead(hContact, hDbEvent); - CallService(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)hDbEvent); - } - if (dbei.pBlob) free(dbei.pBlob); - hDbEvent = db_event_next(hContact, hDbEvent); - } - } - - if (!db_get_s(hContact, SKYPE_PROTONAME, "SkypeOutNr", &dbv)) { - db_free(&dbv); - if (!strcmp((char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0), SKYPE_PROTONAME) && - db_get_b(hContact, "CList", "NotOnList", 0) - ) - CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0); - } - } - free(szSkypeMsg); - LeaveCriticalSection(&RingAndEndcallMutex); -} - -void HoldCallThread(char *szSkypeMsg) { - MCONTACT hContact; - - LOG(("HoldCallThread started")); - if (!szSkypeMsg) { - LOG(("HoldCallThread terminated.")); - return; - } - if (hContact = GetCallerContact(szSkypeMsg)) { - db_set_b(hContact, SKYPE_PROTONAME, "OnHold", 1); - NofifyVoiceService(hContact, szSkypeMsg, VOICE_STATE_ON_HOLD); - } - free(szSkypeMsg); - LOG(("HoldCallThread terminated gracefully")); -} - -void ResumeCallThread(char *szSkypeMsg) { - MCONTACT hContact; - - LOG(("ResumeCallThread started")); - if (!szSkypeMsg) { - LOG(("ResumeCallThread terminated.")); - return; - } - if (hContact = GetCallerContact(szSkypeMsg)) { - db_unset(hContact, SKYPE_PROTONAME, "OnHold"); - NofifyVoiceService(hContact, szSkypeMsg, VOICE_STATE_TALKING); - } - free(szSkypeMsg); - LOG(("ResumeCallThread terminated gracefully.")); -} - -int SetUserStatus(void) { - if (RequestedStatus && AttachStatus != -1) { - if (SkypeSend("SET USERSTATUS %s", RequestedStatus) == -1) return 1; - } - return 0; -} - -void LaunchSkypeAndSetStatusThread(void *newStatus) { - - /* if (!db_get_b(NULL, SKYPE_PROTONAME, "UnloadOnOffline", 0)) { - logoff_contacts(); - return 1; - } - */ - int oldStatus = SkypeStatus; - static BOOL bLaunching = FALSE; - - UNREFERENCED_PARAMETER(newStatus); - - if (bLaunching) return; - bLaunching = TRUE; - LOG(("LaunchSkypeAndSetStatusThread started.")); - InterlockedExchange((long *)&SkypeStatus, (int)ID_STATUS_CONNECTING); - ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, SkypeStatus); - - if (ConnectToSkypeAPI(skype_path, 1) != -1) { - pthread_create((pThreadFunc)SkypeSystemInit, NULL); - //InterlockedExchange((long *)&SkypeStatus, (int)newStatus); - //ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, SkypeStatus); - SetUserStatus(); - } - - LOG(("LaunchSkypeAndSetStatusThread terminated gracefully.")); - bLaunching = FALSE; -} - -LONG APIENTRY WndProc(HWND hWndDlg, UINT message, UINT wParam, LONG lParam) -{ - PCOPYDATASTRUCT CopyData; - char *ptr, *szSkypeMsg = NULL, *nick, *buf; - static char *onlinestatus = NULL; - static BOOL RestoreUserStatus = FALSE; - int sstat, oldstatus, flag; - MCONTACT hContact; - fetchmsg_arg *args; - static int iReentranceCnt = 0; - - iReentranceCnt++; - switch (message) - { - case WM_COPYDATA: - LOG(("WM_COPYDATA start")); - if (hSkypeWnd == (HWND)wParam) { - char *pData; - CopyData = (PCOPYDATASTRUCT)lParam; - pData = (char*)CopyData->lpData; - while (*pData == ' ') pData++; - szSkypeMsg = _strdup((char*)pData); - ReplyMessage(1); - LOG(("< %s", szSkypeMsg)); - - if (!strncmp(szSkypeMsg, "CONNSTATUS", 10)) { - if (!strncmp(szSkypeMsg + 11, "LOGGEDOUT", 9)) { - SkypeInitialized = FALSE; - ResetEvent(SkypeReady); - AttachStatus = -1; - sstat = ID_STATUS_OFFLINE; - if (g_hWnd) KillTimer(g_hWnd, 1); - logoff_contacts(TRUE); - } - else - sstat = SkypeStatusToMiranda(szSkypeMsg + 11); - - if (sstat) { - oldstatus = SkypeStatus; - InterlockedExchange((long*)&SkypeStatus, sstat); - ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldstatus, SkypeStatus); - if (sstat != ID_STATUS_OFFLINE) { - if (sstat != ID_STATUS_CONNECTING && (oldstatus == ID_STATUS_OFFLINE || oldstatus == ID_STATUS_CONNECTING)) { - - SkypeInitialized = FALSE; - pthread_create((pThreadFunc)SkypeSystemInit, NULL); - } - if (db_get_b(NULL, SKYPE_PROTONAME, "KeepState", 0)) RestoreUserStatus = TRUE; - } - - // if (SkypeStatus==ID_STATUS_ONLINE) SkypeSend("SEARCH MISSEDMESSAGES"); - } - // break; - } - if (!strncmp(szSkypeMsg, "USERSTATUS", 10)) { - // if ((sstat=SkypeStatusToMiranda(szSkypeMsg+11)) && SkypeStatus!=ID_STATUS_CONNECTING) { - if ((sstat = SkypeStatusToMiranda(szSkypeMsg + 11))) { - if (RestoreUserStatus && RequestedStatus) { - RestoreUserStatus = FALSE; - SkypeSend("SET USERSTATUS %s", RequestedStatus); - } - oldstatus = SkypeStatus; - InterlockedExchange((long*)&SkypeStatus, sstat); - ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldstatus, sstat); -#ifdef SKYPEBUG_OFFLN - if ((oldstatus == ID_STATUS_OFFLINE || oldstatus == ID_STATUS_CONNECTING) && - SkypeStatus != ID_STATUS_CONNECTING && SkypeStatus != ID_STATUS_OFFLINE) - pthread_create((pThreadFunc)SearchFriendsThread, NULL); -#endif - } -#ifdef SKYPEBUG_OFFLN - SetEvent(GotUserstatus); -#endif - break; - } - if (!strncmp(szSkypeMsg, "APPLICATION libpurple_typing", 28)) { - char *nextoken, *p; - - if (p = strtok_r(szSkypeMsg + 29, " ", &nextoken)) - { - if (!strcmp(p, "STREAMS")) { - char *pStr; - - while (p = strtok_r(NULL, " ", &nextoken)) { - if (pStr = strchr(p, ':')) { - *pStr = 0; - if (hContact = find_contact(p)) { - *pStr = ':'; - db_set_s(hContact, SKYPE_PROTONAME, "Typing_Stream", p); - } - } - } - } - else if (!strcmp(p, "DATAGRAM")) { - if (p = strtok_r(NULL, " ", &nextoken)) { - char *pStr; - - if (pStr = strchr(p, ':')) { - *pStr = 0; - if (hContact = find_contact(p)) { - *pStr = ':'; - db_set_s(hContact, SKYPE_PROTONAME, "Typing_Stream", p); - - if (p = strtok_r(NULL, " ", &nextoken)) { - LPARAM lTyping = PROTOTYPE_CONTACTTYPING_OFF; - - if (!strcmp(p, "PURPLE_TYPING")) lTyping = PROTOTYPE_CONTACTTYPING_INFINITE; - CallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hContact, lTyping); - break; - } - } - } - } - } - } - } - if (!strncmp(szSkypeMsg, "USER ", 5)) { - char *nextoken; - - buf = _strdup(szSkypeMsg + 5); - nick = strtok_r(buf, " ", &nextoken); - ptr = strtok_r(NULL, " ", &nextoken); - - if (strcmp(ptr, "BUDDYSTATUS")) { - if (!strcmp(ptr, "RECEIVEDAUTHREQUEST")) { - pthread_create(( pThreadFunc )ProcessAuthRq, strdup(szSkypeMsg)); - free(buf); - break; - } - - if (!(hContact = find_contact(nick)) && strcmp(ptr, "FULLNAME")) { - SkypeSend("GET USER %s BUDDYSTATUS", nick); - free(buf); - break; - } - - if (!strcmp(ptr, "ONLINESTATUS")) { - if (SkypeStatus != ID_STATUS_OFFLINE) - { - db_set_w(hContact, SKYPE_PROTONAME, "Status", (WORD)SkypeStatusToMiranda(ptr + 13)); - if ((WORD)SkypeStatusToMiranda(ptr + 13) != ID_STATUS_OFFLINE) - { - LOG(("WndProc Status is not offline so get user info")); - pthread_create(GetInfoThread, (void*)hContact); - } - } - } - - - /* We handle the following properties right here in the wndProc, in case that - * Skype protocol broadcasts them to us. - * - * However, we still let them be added to the Message queue im memory, as they - * may get consumed by GetInfoThread. - * This is necessary to have a proper error handling in case the property is - * not supported (i.e. imo2sproxy). - * - * If one of the property GETs returns an error, the error-message has to be - * removed from the message queue, as the error is the answer to the query. - * If we don't remove the ERRORs from the list, another consumer may see the ERROR - * as a reply to his query and process it. - * In case the SKYPE Protocol really broadcasts one of these messages without being - * requested by GetInfoThread (i.e. MOOD_TEXT), the garbage collector will take - * care of them and remove them after some time. - * This may not be the most efficient way, but ensures that we finally do proper - * error handling. - */ - if (!strcmp(ptr, "FULLNAME")) { - char *nm; - - if (nm = strtok_r(NULL, " ", &nextoken)) - { - db_set_utf(hContact, SKYPE_PROTONAME, "FirstName", nm); - if (!(nm = strtok_r(NULL, "", &nextoken))) {db_unset(hContact, SKYPE_PROTONAME, "LastName");} - else - db_set_utf(hContact, SKYPE_PROTONAME, "LastName", nm); - } - } - else - if (!strcmp(ptr, "BIRTHDAY")) { - unsigned int y, m, d; - if (sscanf(ptr + 9, "%04d%02d%02d", &y, &m, &d) == 3) { - db_set_w(hContact, SKYPE_PROTONAME, "BirthYear", (WORD)y); - db_set_b(hContact, SKYPE_PROTONAME, "BirthMonth", (BYTE)m); - db_set_b(hContact, SKYPE_PROTONAME, "BirthDay", (BYTE)d); - } - else { - db_unset(hContact, SKYPE_PROTONAME, "BirthYear"); - db_unset(hContact, SKYPE_PROTONAME, "BirthMonth"); - db_unset(hContact, SKYPE_PROTONAME, "BirthDay"); - } - } - else - if (!strcmp(ptr, "COUNTRY")) { - if (ptr[8]) { - struct CountryListEntry *countries; - int countryCount, i; - - CallService(MS_UTILS_GETCOUNTRYLIST, (WPARAM)&countryCount, (LPARAM)&countries); - for (i = 0; i < countryCount; i++) { - if (countries[i].id == 0 || countries[i].id == 0xFFFF) continue; - if (!_stricmp(countries[i].szName, ptr + 8)) - { - db_set_w(hContact, SKYPE_PROTONAME, "Country", (BYTE)countries[i].id); - break; - } - } - } - else db_unset(hContact, SKYPE_PROTONAME, "Country"); - } - else - if (!strcmp(ptr, "SEX")) { - if (ptr[4]) { - BYTE sex = 0; - if (!_stricmp(ptr + 4, "MALE")) sex = 0x4D; - if (!_stricmp(ptr + 4, "FEMALE")) sex = 0x46; - if (sex) db_set_b(hContact, SKYPE_PROTONAME, "Gender", sex); - } - else db_unset(hContact, SKYPE_PROTONAME, "Gender"); - } - else - if (!strcmp(ptr, "MOOD_TEXT")){ - - LOG(("WndProc MOOD_TEXT")); - db_set_utf(hContact, "CList", "StatusMsg", ptr + 10); - } - else - if (!strcmp(ptr, "TIMEZONE")){ - time_t temp; - struct tm tms; - int value = atoi(ptr + 9), tz; - - LOG(("WndProc: TIMEZONE %s", nick)); - - if (value && !db_get_b(NULL, SKYPE_PROTONAME, "IgnoreTimeZones", 0)) { - temp = SkypeTime(NULL); - tms = *localtime(&temp); - //memcpy(&tms,localtime(&temp), sizeof(tm)); - //tms = localtime(&temp) - tz = (value >= 86400) ? (256 - ((2 * (atoi(ptr + 9) - 86400)) / 3600)) : ((-2 * (atoi(ptr + 9) - 86400)) / 3600); - if (tms.tm_isdst == 1 && db_get_b(NULL, SKYPE_PROTONAME, "UseTimeZonePatch", 0)) - { - LOG(("WndProc: Using the TimeZonePatch")); - db_set_b(hContact, "UserInfo", "Timezone", (BYTE)(tz + 2)); - } - else - { - LOG(("WndProc: Not using the TimeZonePatch")); - db_set_b(hContact, "UserInfo", "Timezone", (BYTE)(tz + 0)); - } - } - else { - LOG(("WndProc: Deleting the TimeZone in UserInfo Section")); - db_unset(hContact, "UserInfo", "Timezone"); - } - } - else - if (!strcmp(ptr, "IS_VIDEO_CAPABLE")){ - if (!_stricmp(ptr + 17, "True")) - db_set_s(hContact, SKYPE_PROTONAME, "MirVer", "Skype 2.0"); - else - db_set_s(hContact, SKYPE_PROTONAME, "MirVer", "Skype"); - } - else - if (!strcmp(ptr, "RICH_MOOD_TEXT")) { - db_set_s(hContact, SKYPE_PROTONAME, "MirVer", "Skype 3.0"); - } - else - if (!strcmp(ptr, "DISPLAYNAME")) { - // Skype Bug? -> If nickname isn't customised in the Skype-App, this won't return anything :-( - if (ptr[12]) - db_set_utf(hContact, SKYPE_PROTONAME, "Nick", ptr + 12); - } - else // Other proerties that can be directly assigned to a DB-Value - { - int i; - char *pszProp; - - for (i = 0; i < sizeof(m_settings) / sizeof(m_settings[0]); i++) { - if (!strcmp(ptr, m_settings[i].SkypeSetting)) { - pszProp = ptr + strlen(m_settings[i].SkypeSetting) + 1; - if (*pszProp) - db_set_utf(hContact, SKYPE_PROTONAME, m_settings[i].MirandaSetting, pszProp); - else - db_unset(hContact, SKYPE_PROTONAME, m_settings[i].MirandaSetting); - } - } - } - } - else { // BUDDYSTATUS: - flag = 0; - switch (atoi(ptr + 12)) { - case 1: if (hContact = find_contact(nick)) CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0); break; - case 0: break; - case 2: flag = PALF_TEMPORARY; - case 3: add_contact(nick, flag); - SkypeSend("GET USER %s ONLINESTATUS", nick); - break; - } - free(buf); - if (!SetEvent(hBuddyAdded)) TellError(GetLastError()); - break; - } - free(buf); - } - if (!strncmp(szSkypeMsg, "CURRENTUSERHANDLE", 17)) { // My username - DBVARIANT dbv = { 0 }; - - if (db_get_s(NULL, SKYPE_PROTONAME, "LoginUserName", &dbv) || - !*dbv.pszVal || _stricmp(szSkypeMsg + 18, dbv.pszVal) == 0) - { - db_set_s(NULL, SKYPE_PROTONAME, SKYPE_NAME, szSkypeMsg + 18); - db_set_s(NULL, SKYPE_PROTONAME, "Nick", szSkypeMsg + 18); - pthread_create((pThreadFunc)GetDisplaynameThread, NULL); - } - if (dbv.pszVal) db_free(&dbv); - } - if (strstr(szSkypeMsg, "AUTOAWAY") || !strncmp(szSkypeMsg, "OPEN ", 5) || - (SkypeInitialized && !strncmp(szSkypeMsg, "PONG", 4)) || - !strncmp(szSkypeMsg, "MINIMIZE", 8)) - { - // Currently we do not process these messages - break; - } - if (!strncmp(szSkypeMsg, "CHAT ", 5)) { - // Currently we only process these notifications - if (db_get_b(NULL, SKYPE_PROTONAME, "UseGroupchat", 0) && - (ptr = strchr(szSkypeMsg, ' ')) && (ptr = strchr(++ptr, ' '))) - { - if (strncmp(ptr, " MEMBERS", 8) == 0) { - LOG(("WndProc AddMembers")); - pthread_create((pThreadFunc)AddMembersThread, _strdup(szSkypeMsg)); - } - else - if (strncmp(ptr, " FRIENDLYNAME ", 14) == 0) { - // Chat session name - MCONTACT hContact; - - *ptr = 0; - if (hContact = find_chatA(szSkypeMsg + 5)) - { - GCDEST gcd = {0}; - GCEVENT gce = {0}; - if (db_get_w(hContact, SKYPE_PROTONAME, "Status", ID_STATUS_OFFLINE) != - ID_STATUS_OFFLINE) - { - gcd.pszModule = SKYPE_PROTONAME; - gcd.ptszID = make_nonutf_tchar_string((const unsigned char*)szSkypeMsg+5); - gcd.iType = GC_EVENT_CHANGESESSIONAME; - gce.cbSize = sizeof(GCEVENT); - gce.pDest = &gcd; - gce.ptszText = make_tchar_string((const unsigned char*)ptr+14); - gce.dwFlags = GC_TCHAR; - if (gce.ptszText) { - CallService(MS_GC_EVENT, 0, (LPARAM)&gce); - db_set_ts(hContact, SKYPE_PROTONAME, "Nick", gce.ptszText); - free((void*)gce.ptszText); - } - free_nonutf_tchar_string((void*)gcd.ptszID); - } - } - *ptr = ' '; - } - else - if (strncmp(ptr, " CHATMESSAGES ", 14) == 0) { - pthread_create((pThreadFunc)MessageListProcessingThread, _strdup(ptr + 14)); - break; - } - } - } - if (!strncmp(szSkypeMsg, "CALL ", 5)) { - // incoming calls are already processed by Skype, so no need for us - // to do this. - // However we can give a user the possibility to hang up a call via Miranda's - // context menu - if (ptr = strstr(szSkypeMsg, " STATUS ")) { - ptr[0] = 0; ptr += 8; - if (!strcmp(ptr, "RINGING") || !strcmp(ptr, "ROUTING")) pthread_create((pThreadFunc)RingThread, _strdup(szSkypeMsg)); - if (!strcmp(ptr, "FAILED") || !strcmp(ptr, "FINISHED") || - !strcmp(ptr, "MISSED") || !strcmp(ptr, "REFUSED") || - !strcmp(ptr, "BUSY") || !strcmp(ptr, "CANCELLED")) - pthread_create((pThreadFunc)EndCallThread, _strdup(szSkypeMsg)); - if (!strcmp(ptr, "ONHOLD") || !strcmp(ptr, "LOCALHOLD") || - !strcmp(ptr, "REMOTEHOLD")) pthread_create((pThreadFunc)HoldCallThread, _strdup(szSkypeMsg)); - if (!strcmp(ptr, "INPROGRESS")) pthread_create((pThreadFunc)ResumeCallThread, _strdup(szSkypeMsg)); - break; - } - else if ((!strstr(szSkypeMsg, "PARTNER_HANDLE") && !strstr(szSkypeMsg, "FROM_HANDLE")) - && !strstr(szSkypeMsg, "TYPE")) break; - } - if (!strncmp(szSkypeMsg, "PRIVILEGE SKYPEOUT", 18)) { - if (!strncmp(szSkypeMsg + 19, "TRUE", 4)) { - if (!bSkypeOut) { - CLISTMENUITEM mi = { 0 }; - - bSkypeOut = TRUE; - mi.cbSize = sizeof(mi); - mi.position = -2000005000; - mi.flags = 0; - mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_CALLSKYPEOUT)); - mi.pszContactOwner = SKYPE_PROTONAME; - mi.pszName = Translate("Do a SkypeOut-call"); - mi.pszService = SKYPEOUT_CALL; - Menu_AddMainMenuItem(&mi); - } - - } - else { - bSkypeOut = FALSE; - if (httbButton) { - CallService(MS_TTB_REMOVEBUTTON, (WPARAM)httbButton, 0); - httbButton = 0; - } - } - break; - } - if (!strncmp(szSkypeMsg, "MESSAGES", 8) || !strncmp(szSkypeMsg, "CHATMESSAGES", 12)) { - if (strlen(szSkypeMsg) <= (UINT)(strchr(szSkypeMsg, ' ') - szSkypeMsg + 1)) - { - LOG(("%s %d %s %d", szSkypeMsg, (UINT)(strchr(szSkypeMsg, ' ') - szSkypeMsg + 1), - strchr(szSkypeMsg, ' '), strlen(szSkypeMsg))); - break; - } - LOG(("MessageListProcessingThread launched")); - pthread_create((pThreadFunc)MessageListProcessingThread, _strdup(strchr(szSkypeMsg, ' ') + 1)); - break; - } - if (!strncmp(szSkypeMsg, "MESSAGE", 7) || !strncmp(szSkypeMsg, "CHATMESSAGE", 11)) - { - char *pMsgNum; - TYP_MSGLENTRY *pEntry; - - if ((pMsgNum = strchr(szSkypeMsg, ' ')) && (ptr = strchr(++pMsgNum, ' '))) - { - BOOL bFetchMsg = FALSE; - - if (strncmp(ptr, " EDITED_TIMESTAMP", 17) == 0) { - ptr[0] = 0; - if (pEntry = MsgList_FindMessage(strtoul(pMsgNum, NULL, 10))) { - pEntry->tEdited = atol(ptr + 18); - } - bFetchMsg = TRUE; - } - else bFetchMsg = (strncmp(ptr, " STATUS RE", 10) == 0 && !rcvwatchers) || - (strncmp(ptr, " STATUS SENT", 12) == 0 && !sendwatchers); - - if (bFetchMsg) { - // If new message is available, fetch it - ptr[0] = 0; - if (!(args = (fetchmsg_arg *)calloc(1, sizeof(*args)))) break; - strncpy(args->msgnum, pMsgNum, sizeof(args->msgnum)); - args->getstatus = FALSE; - //args->bIsRead = strncmp(ptr+8, "READ", 4) == 0; - pthread_create((pThreadFunc)FetchMessageThreadSync, args); - break; - } - } - } - if (!strncmp(szSkypeMsg, "ERROR 68", 8)) { - LOG(("We got a sync problem :( -> SendMessage() will try to recover...")); - break; - } - if (!strncmp(szSkypeMsg, "PROTOCOL ", 9)) { - if ((protocol = (char)atoi(szSkypeMsg + 9)) >= 3) { - strcpy(cmdMessage, "CHATMESSAGE"); - strcpy(cmdPartner, "FROM"); - } - bProtocolSet = TRUE; - - if (protocol < 5 && !hMenuAddSkypeContact && - db_get_b(NULL, SKYPE_PROTONAME, "EnableMenu", 1)) - { - hMenuAddSkypeContact = add_mainmenu(); - } - } - LOG(("SkypeMsgAdd launched")); - SkypeMsgAdd(szSkypeMsg); - ReleaseSemaphore(SkypeMsgReceived, receivers, NULL); - } - break; - - case WM_TIMER: - if (iReentranceCnt > 1) break; - if (!bIsImoproxy) SkypeSend("PING"); - SkypeMsgCollectGarbage(MAX_MSG_AGE); - MsgList_CollectGarbage(); - if (receivers > 1) - { - LOG(("Watchdog WARNING: there are still %d receivers waiting for MSGs", receivers)); - } - break; - - case WM_CLOSE: - PostQuitMessage(0); - break; - case WM_DESTROY: - KillTimer(hWndDlg, 1); - break; - case WM_COPYDATALOCAL: - --iReentranceCnt; - return WndProc(hWndDlg, WM_COPYDATA, wParam, lParam); - - default: - if (message == ControlAPIAttach) { - // Skype responds with Attach to the discover-message - if ((HWND)wParam == hForbiddenSkypeWnd) { - ResetEvent(SkypeReady); - break; - } - AttachStatus = lParam; - if (lParam == SKYPECONTROLAPI_ATTACH_SUCCESS) { - LOG(("AttachStatus success, got hWnd %08X", (HWND)wParam)); - - if (hSkypeWnd && (HWND)wParam != hSkypeWnd && IsWindow(hSkypeWnd)) - hSkypeWndSecondary = (HWND)wParam; - else { - hSkypeWnd = (HWND)wParam; // Skype gave us the communication window handle - hSkypeWndSecondary = NULL; - } - } - if (AttachStatus != SKYPECONTROLAPI_ATTACH_API_AVAILABLE && - AttachStatus != SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE) - { - LOG(("Attaching: SkypeReady fired, Attachstatus is %d", AttachStatus)); - SetEvent(SkypeReady); - } - AttachStatus = lParam; - break; - } - --iReentranceCnt; - return DefWindowProc(hWndDlg, message, wParam, lParam); - } - LOG(("WM_COPYDATA exit (%08X)", message)); - if (szSkypeMsg) free(szSkypeMsg); - --iReentranceCnt; - return 1; -} - -void TellError(DWORD err) { - LPVOID lpMsgBuf; - - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); - MessageBox(NULL, (TCHAR*)lpMsgBuf, _T("GetLastError"), MB_OK | MB_ICONINFORMATION); - LocalFree(lpMsgBuf); - return; -} - - -// SERVICES // -INT_PTR SkypeSetStatus(WPARAM wParam, LPARAM lParam) -{ - int oldStatus, iRet; - BOOL UseCustomCommand, UnloadOnOffline; - - UNREFERENCED_PARAMETER(lParam); - - if (MirandaShuttingDown) return 0; - LOG(("SkypeSetStatus enter")); - UseCustomCommand = db_get_b(NULL, SKYPE_PROTONAME, "UseCustomCommand", 0); - UnloadOnOffline = db_get_b(NULL, SKYPE_PROTONAME, "UnloadOnOffline", 0); - - //if (!SkypeInitialized && !db_get_b(NULL, SKYPE_PROTONAME, "UnloadOnOffline", 0)) return 0; - - // Workaround for Skype status-bug - if ((int)wParam == ID_STATUS_OFFLINE) logoff_contacts(TRUE); - if (SkypeStatus == (int)wParam) return 0; - oldStatus = SkypeStatus; - - if ((int)wParam == ID_STATUS_CONNECTING) return 0; -#ifdef MAPDND - if ((int)wParam == ID_STATUS_OCCUPIED || (int)wParam == ID_STATUS_ONTHEPHONE) wParam = ID_STATUS_DND; - if ((int)wParam == ID_STATUS_OUTTOLUNCH) wParam = ID_STATUS_NA; -#endif -#ifdef MAPNA - if ((int)wParam==ID_STATUS_NA) wParam = ID_STATUS_AWAY; -#endif - - RequestedStatus = MirandaStatusToSkype((int)wParam); - - /* - if (SkypeStatus != ID_STATUS_OFFLINE) - { - InterlockedExchange((long*)&SkypeStatus, (int)wParam); - ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, SkypeStatus); - } - */ - - if ((int)wParam == ID_STATUS_OFFLINE && UnloadOnOffline) - { - if (UseCustomCommand) - { - DBVARIANT dbv; - if (!db_get_s(NULL, SKYPE_PROTONAME, "CommandLine", &dbv)) - { - CloseSkypeAPI(dbv.pszVal); - db_free(&dbv); - } - } - else - { - CloseSkypeAPI(skype_path); - } - - } - else if (AttachStatus == -1) - { - pthread_create(LaunchSkypeAndSetStatusThread, (void *)wParam); - return 0; - } - - iRet = SetUserStatus(); - LOG(("SkypeSetStatus exit")); - return iRet; -} - -int __stdcall SendBroadcast(MCONTACT hContact, int type, int result, HANDLE hProcess, LPARAM lParam) -{ - ACKDATA ack = {0}; - ack.cbSize = sizeof( ACKDATA ); - ack.szModule = SKYPE_PROTONAME; - ack.hContact = hContact; - ack.type = type; - ack.result = result; - ack.hProcess = hProcess; - ack.lParam = lParam; - return CallService(MS_PROTO_BROADCASTACK, 0, (LPARAM)&ack); -} - -static void __cdecl SkypeGetAwayMessageThread(void *hContact) -{ - DBVARIANT dbv; - if (!db_get_ts((MCONTACT)hContact, "CList", "StatusMsg", &dbv)) { - SendBroadcast((MCONTACT)hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, (LPARAM)dbv.ptszVal); - db_free(&dbv); - } - else SendBroadcast((MCONTACT)hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, (LPARAM)0); -} - -INT_PTR SkypeGetAwayMessage(WPARAM wParam, LPARAM lParam) -{ - CCSDATA* ccs = (CCSDATA*)lParam; - - UNREFERENCED_PARAMETER(wParam); - - pthread_create(SkypeGetAwayMessageThread, (void*)ccs->hContact); - return 1; -} - -#define POLYNOMIAL (0x488781ED) /* This is the CRC Poly */ -#define TOPBIT (1 << (WIDTH - 1)) /* MSB */ -#define WIDTH 32 - -static int GetFileHash(char* filename) -{ - HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - int remainder = 0, byte, bit; - char data[1024]; - DWORD dwRead; - - if (hFile == INVALID_HANDLE_VALUE) return 0; - - do - { - // Read file chunk - dwRead = 0; - ReadFile(hFile, data, 1024, &dwRead, NULL); - - /* loop through each byte of data */ - for (byte = 0; byte < (int)dwRead; ++byte) { - /* store the next byte into the remainder */ - remainder ^= (data[byte] << (WIDTH - 8)); - /* calculate for all 8 bits in the byte */ - for (bit = 8; bit > 0; --bit) { - /* check if MSB of remainder is a one */ - if (remainder & TOPBIT) - remainder = (remainder << 1) ^ POLYNOMIAL; - else - remainder = (remainder << 1); - } - } - } while (dwRead == 1024); - - CloseHandle(hFile); - - return remainder; -} - -static int _GetFileSize(char* filename) -{ - HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - int size; - - if (hFile == INVALID_HANDLE_VALUE) - return 0; - size = GetFileSize(hFile, NULL); - CloseHandle(hFile); - return size; -} - -/* RetrieveUserAvatar - * - * Purpose: Get a user avatar from skype itself - * Params : param=(void *)(HANDLE)hContact - */ -void RetrieveUserAvatar(void *param) -{ - MCONTACT hContact = (MCONTACT)param; - HANDLE file; - PROTO_AVATAR_INFORMATION AI = { 0 }; - ACKDATA ack = { 0 }; - DBVARIANT dbv; - char AvatarFile[MAX_PATH + 1], AvatarTmpFile[MAX_PATH + 10], *ptr, *pszTempFile; - - if (hContact == NULL) - return; - - // Mount default ack - ack.cbSize = sizeof(ACKDATA); - ack.szModule = SKYPE_PROTONAME; - ack.hContact = hContact; - ack.type = ACKTYPE_AVATAR; - ack.result = ACKRESULT_FAILED; - - AI.cbSize = sizeof(AI); - AI.hContact = hContact; - - // Get skype name - if (db_get_s(hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv) == 0) - { - if (dbv.pszVal) - { - // Get filename - FoldersGetCustomPath(hProtocolAvatarsFolder, AvatarFile, sizeof(AvatarFile), DefaultAvatarsFolder); - if (!*AvatarFile) strcpy(AvatarFile, DefaultAvatarsFolder); - mir_snprintf(AvatarTmpFile, sizeof(AvatarTmpFile), "AVATAR 1 %s\\%s_tmp.jpg", AvatarFile, dbv.pszVal); - pszTempFile = AvatarTmpFile + 9; - mir_snprintf(AvatarFile, sizeof(AvatarFile), "%s\\%s.jpg", AvatarFile, dbv.pszVal); - - // Just to be sure - DeleteFileA(pszTempFile); - file = CreateFileA(pszTempFile, 0, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (file != INVALID_HANDLE_VALUE) - { - CloseHandle(file); - if (ptr = SkypeGet("USER", dbv.pszVal, AvatarTmpFile)) - { - if (strncmp(ptr, "ERROR", 5) && - GetFileAttributesA(pszTempFile) != INVALID_FILE_ATTRIBUTES) - { - ack.result = ACKRESULT_SUCCESS; - - // Is no avatar image? - if (!db_get_b(NULL, SKYPE_PROTONAME, "ShowDefaultSkypeAvatar", 0) - && GetFileHash(pszTempFile) == 0x8d34e05d && _GetFileSize(pszTempFile) == 3751) - { - // Has no avatar - AI.format = PA_FORMAT_UNKNOWN; - ack.hProcess = (HANDLE)&AI; - DeleteFileA(AvatarFile); - } - else - { - // Got it - MoveFileExA(pszTempFile, AvatarFile, MOVEFILE_REPLACE_EXISTING); - AI.format = PA_FORMAT_JPEG; - strcpy(AI.filename, AvatarFile); - ack.hProcess = (HANDLE)&AI; - } - - } - free(ptr); - } - DeleteFileA(pszTempFile); - } - - } - db_free(&dbv); - } - CallService(MS_PROTO_BROADCASTACK, 0, (LPARAM)&ack); -} - - -/* SkypeGetAvatarInfo - * - * Purpose: Set user avatar in profile - * Params : wParam=0 - * lParam=(LPARAM)(const char*)filename - * Returns: 0 - Success - * -1 - Failure - */ -INT_PTR SkypeGetAvatarInfo(WPARAM wParam, LPARAM lParam) -{ - - DBVARIANT dbv; - PROTO_AVATAR_INFORMATION* AI = (PROTO_AVATAR_INFORMATION*)lParam; - if (AI->hContact == NULL) // User - { - if (!db_get_s(NULL, SKYPE_PROTONAME, "AvatarFile", &dbv)) - { - lstrcpynA(AI->filename, dbv.pszVal, sizeof(AI->filename)); - db_free(&dbv); - return GAIR_SUCCESS; - } - else - return GAIR_NOAVATAR; - } - else // Contact - { - DBVARIANT dbv; - char AvatarFile[MAX_PATH + 1]; - - if (protocol < 7 && !bIsImoproxy) - return GAIR_NOAVATAR; - - if (wParam & GAIF_FORCE) - { - // Request anyway - pthread_create(RetrieveUserAvatar, (void *)AI->hContact); - return GAIR_WAITFOR; - } - - if (db_get_s(AI->hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) - // No skype name ?? - return GAIR_NOAVATAR; - - if (dbv.pszVal == NULL) - { - // No skype name ?? - db_free(&dbv); - return GAIR_NOAVATAR; - } - - // Get filename - FoldersGetCustomPath(hProtocolAvatarsFolder, AvatarFile, sizeof(AvatarFile), DefaultAvatarsFolder); - mir_snprintf(AvatarFile, sizeof(AvatarFile), "%s\\%s.jpg", AvatarFile, dbv.pszVal); - db_free(&dbv); - - // Check if the file exists - if (GetFileAttributesA(AvatarFile) == INVALID_FILE_ATTRIBUTES) - return GAIR_NOAVATAR; - - // Return the avatar - AI->format = PA_FORMAT_JPEG; - strcpy(AI->filename, AvatarFile); - return GAIR_SUCCESS; - } -} - - -/* SkypeGetAvatarCaps - * - * Purpose: Query avatar caps for a protocol - * Params : wParam=One of AF_* - * lParam=Depends on wParam - * Returns: Depends on wParam - */ -INT_PTR SkypeGetAvatarCaps(WPARAM wParam, LPARAM lParam) -{ - switch (wParam) - { - case AF_MAXSIZE: - { - POINT *p = (POINT *)lParam; - if (p == NULL) - return -1; - - p->x = 96; - p->y = 96; - return 0; - } - case AF_PROPORTION: - { - return PIP_NONE; - } - case AF_FORMATSUPPORTED: - { - if (lParam == PA_FORMAT_PNG || lParam == PA_FORMAT_JPEG) - return TRUE; - else - return FALSE; - } - case AF_ENABLED: - { - return TRUE; - } - case AF_DONTNEEDDELAYS: - { - return FALSE; - } - } - return -1; -} - - -INT_PTR SkypeGetStatus(WPARAM wParam, LPARAM lParam) { - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(lParam); - - return SkypeStatus; -} - -INT_PTR SkypeGetInfo(WPARAM wParam, LPARAM lParam) { - CCSDATA *ccs = (CCSDATA *)lParam; - - UNREFERENCED_PARAMETER(wParam); - - pthread_create(GetInfoThread, (void*)ccs->hContact); - return 0; -} - -INT_PTR SkypeAddToList(WPARAM wParam, LPARAM lParam) { - PROTOSEARCHRESULT *psr = (PROTOSEARCHRESULT*)lParam; - - LOG(("SkypeAddToList Adding API function called")); - if (psr->cbSize != sizeof(PROTOSEARCHRESULT) || !psr->nick) return 0; - LOG(("SkypeAddToList OK")); - return (INT_PTR)add_contact(_T2A(psr->nick), wParam); -} - -INT_PTR SkypeBasicSearch(WPARAM wParam, LPARAM lParam) { - UNREFERENCED_PARAMETER(wParam); - - LOG(("SkypeBasicSearch %s", (char *)lParam)); - if (!SkypeInitialized) return 0; - return (hSearchThread = pthread_create((pThreadFunc)BasicSearchThread, _strdup((char *)lParam))); -} - -void MessageSendWatchThread(void *a) { - char *str, *err; - - msgsendwt_arg *arg = (msgsendwt_arg*)a; - - LOG(("MessageSendWatchThread started.")); - - str = SkypeRcvMsg(arg->szId, SkypeTime(NULL) - 1, arg->hContact, db_get_dw(NULL, "SRMsg", "MessageTimeout", TIMEOUT_MSGSEND)); - InterlockedDecrement(&sendwatchers); - if (str) - { - if (!db_get_b(arg->hContact, SKYPE_PROTONAME, "ChatRoom", 0)) { - if (err = GetSkypeErrorMsg(str)) { - ProtoBroadcastAck(SKYPE_PROTONAME, arg->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)1, (LPARAM)Translate(err)); - free(err); - free(str); - free(arg); - LOG(("MessageSendWatchThread terminated.")); - return; - } - ProtoBroadcastAck(SKYPE_PROTONAME, arg->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)1, 0); - } - free(str); - LOG(("MessageSendWatchThread terminated gracefully.")); - } - free(arg); -} - -INT_PTR SkypeSendMessage(WPARAM wParam, LPARAM lParam) { - CCSDATA *ccs = (CCSDATA *)lParam; - DBVARIANT dbv; - BOOL sendok = TRUE; - char *msg = (char *)ccs->lParam, *utfmsg = NULL, *mymsgcmd = cmdMessage, szId[16] = { 0 }; - static DWORD dwMsgNum = 0; - BYTE bIsChatroom = 0 != db_get_b(ccs->hContact, SKYPE_PROTONAME, "ChatRoom", 0); - - UNREFERENCED_PARAMETER(wParam); - - if (bIsChatroom) - { - if (db_get_s(ccs->hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv)) - return 0; - mymsgcmd = "CHATMESSAGE"; - } - else - { - if (db_get_s(ccs->hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) - return 0; - mymsgcmd = "MESSAGE"; - } - - if (ccs->wParam & PREF_UTF) { - utfmsg = msg; - } - else if (ccs->wParam & PREF_UNICODE) { - utfmsg = (char*)make_utf8_string((WCHAR*)(msg + strlen(msg) + 1)); - } - else { - if (utf8_encode(msg, &utfmsg) == -1) utfmsg = NULL; - } - if (protocol >= 4) { - InterlockedIncrement((LONG*)&dwMsgNum); - sprintf(szId, "#M%d ", dwMsgNum++); - } - InterlockedIncrement(&sendwatchers); - if (!utfmsg || SkypeSend("%s%s %s %s", szId, mymsgcmd, dbv.pszVal, utfmsg)) sendok = FALSE; - if (utfmsg && utfmsg != msg) free(utfmsg); - db_free(&dbv); - - if (sendok) { - msgsendwt_arg *psendarg = (msgsendwt_arg*)calloc(1, sizeof(msgsendwt_arg)); - - if (psendarg) { - psendarg->hContact = ccs->hContact; - strcpy(psendarg->szId, szId); - pthread_create(MessageSendWatchThread, psendarg); - } - else InterlockedDecrement(&sendwatchers); - return 1; - } - else InterlockedDecrement(&sendwatchers); - if (!bIsChatroom) - ProtoBroadcastAck(SKYPE_PROTONAME, ccs->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)1, (LPARAM)Translate("Connection to Skype lost")); - return 0; -} - -INT_PTR SkypeRecvMessage(WPARAM wParam, LPARAM lParam) -{ - DBEVENTINFO dbei = { 0 }; - CCSDATA *ccs = (CCSDATA *)lParam; - PROTORECVEVENT *pre = (PROTORECVEVENT *)ccs->lParam; - - UNREFERENCED_PARAMETER(wParam); - - db_unset(ccs->hContact, "CList", "Hidden"); - dbei.cbSize = sizeof(dbei); - dbei.szModule = SKYPE_PROTONAME; - dbei.timestamp = pre->timestamp; - if (pre->flags & PREF_CREATEREAD) dbei.flags |= DBEF_READ; - if (pre->flags & PREF_UTF) dbei.flags |= DBEF_UTF; - dbei.eventType = EVENTTYPE_MESSAGE; - dbei.cbBlob = strlen(pre->szMessage) + 1; - if (pre->flags & PREF_UNICODE) - dbei.cbBlob += sizeof(wchar_t)*((DWORD)wcslen((wchar_t*)&pre->szMessage[dbei.cbBlob]) + 1); - dbei.pBlob = (PBYTE)pre->szMessage; - MsgList_Add(pre->lParam, db_event_add(ccs->hContact, &dbei)); - return 0; -} - -INT_PTR SkypeUserIsTyping(WPARAM wParam, LPARAM lParam) { - DBVARIANT dbv = { 0 }; - MCONTACT hContact = (MCONTACT)wParam; - - if (protocol < 5 && !bIsImoproxy) return 0; - if (db_get_s(hContact, SKYPE_PROTONAME, "Typing_Stream", &dbv)) { - if (db_get_s(hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv) == 0) { - char szCmd[256]; - _snprintf(szCmd, sizeof(szCmd), - "ALTER APPLICATION libpurple_typing CONNECT %s", dbv.pszVal); - SkypeSend(szCmd); - db_free(&dbv); - testfor(szCmd, 2000); - // TODO: We should somehow cache the typing notify result and send it - // after we got a connection, but in the meantime this notification won't - // get sent on first run - } - return 0; - } - - SkypeSend("ALTER APPLICATION libpurple_typing DATAGRAM %s %s", dbv.pszVal, - (lParam == PROTOTYPE_SELFTYPING_ON ? "PURPLE_TYPING" : "PURPLE_NOT_TYPING")); - db_free(&dbv); - return 0; -} - - -INT_PTR SkypeSendAuthRequest(WPARAM wParam, LPARAM lParam) { - CCSDATA* ccs = (CCSDATA*)lParam; - DBVARIANT dbv; - int retval; - - UNREFERENCED_PARAMETER(wParam); - - if (!ccs->lParam || db_get_s(ccs->hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) - return 1; - retval = SkypeSend("SET USER %s BUDDYSTATUS 2 %s", dbv.pszVal, (char *)ccs->lParam); - db_free(&dbv); - if (retval) return 1; else return 0; -} - -INT_PTR SkypeRecvAuth(WPARAM wParam, LPARAM lParam) { - DBEVENTINFO dbei = { 0 }; - CCSDATA* ccs = (CCSDATA*)lParam; - PROTORECVEVENT* pre = (PROTORECVEVENT*)ccs->lParam; - - UNREFERENCED_PARAMETER(wParam); - - db_unset(ccs->hContact, "CList", "Hidden"); - - dbei.cbSize = sizeof(dbei); - dbei.szModule = SKYPE_PROTONAME; - dbei.timestamp = pre->timestamp; - dbei.flags = ((pre->flags & PREF_CREATEREAD) ? DBEF_READ : 0); - dbei.eventType = EVENTTYPE_AUTHREQUEST; - dbei.cbBlob = pre->lParam; - dbei.pBlob = (PBYTE)pre->szMessage; - - db_event_add(NULL, &dbei); - return 0; -} - -char *__skypeauth(WPARAM wParam) { - DBEVENTINFO dbei = { 0 }; - - if (!SkypeInitialized) return NULL; - - dbei.cbSize = sizeof(dbei); - if ((dbei.cbBlob = db_event_getBlobSize((HANDLE)wParam) == -1 || - !(dbei.pBlob = (unsigned char*)malloc(dbei.cbBlob)))) - { - return NULL; - } - - if (db_event_get((HANDLE)wParam, &dbei) || - dbei.eventType != EVENTTYPE_AUTHREQUEST || - strcmp(dbei.szModule, SKYPE_PROTONAME)) - { - free(dbei.pBlob); - return NULL; - } - return (char *)dbei.pBlob; -} - -INT_PTR SkypeAuthAllow(WPARAM wParam, LPARAM lParam) { - char *pBlob; - - UNREFERENCED_PARAMETER(lParam); - - if (pBlob = __skypeauth(wParam)) - { - int retval = SkypeSend("SET USER %s ISAUTHORIZED TRUE", pBlob + sizeof(DWORD) + sizeof(HANDLE)); - free(pBlob); - if (!retval) return 0; - } - return 1; -} - -INT_PTR SkypeAuthDeny(WPARAM wParam, LPARAM lParam) { - char *pBlob; - - UNREFERENCED_PARAMETER(lParam); - - if (pBlob = __skypeauth(wParam)) - { - int retval = SkypeSend("SET USER %s ISAUTHORIZED FALSE", pBlob + sizeof(DWORD) + sizeof(HANDLE)); - free(pBlob); - if (!retval) return 0; - } - return 1; -} - - -INT_PTR SkypeAddToListByEvent(WPARAM wParam, LPARAM lParam) { - char *pBlob; - - UNREFERENCED_PARAMETER(lParam); - - if (pBlob = __skypeauth(wParam)) - { - MCONTACT hContact = add_contact(pBlob + sizeof(DWORD) + sizeof(HANDLE), LOWORD(wParam)); - free(pBlob); - if (hContact) return (int)hContact; - } - return 0; -} - -INT_PTR SkypeRegisterProxy(WPARAM wParam, LPARAM lParam) { - UNREFERENCED_PARAMETER(wParam); - - if (!lParam) { - free(pszProxyCallout); - pszProxyCallout = NULL; - } - pszProxyCallout = _strdup((char*)lParam); - bIsImoproxy = TRUE; - return 0; -} - - -void CleanupNicknames(char *dummy) { - MCONTACT hContact; - char *szProto; - DBVARIANT dbv, dbv2; - - UNREFERENCED_PARAMETER(dummy); - - LOG(("CleanupNicknames Cleaning up...")); - for (hContact = db_find_first(SKYPE_PROTONAME); hContact != NULL; hContact = db_find_next(hContact)) { - szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); - if (szProto != NULL && !strcmp(szProto, SKYPE_PROTONAME) && - db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0) == 0) - { - if (db_get_s(hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) continue; - if (db_get_s(hContact, SKYPE_PROTONAME, "Nick", &dbv2)) { - db_free(&dbv); - continue; - } - db_unset(hContact, SKYPE_PROTONAME, "Nick"); - GetInfoThread((void*)hContact); - db_free(&dbv); - db_free(&dbv2); - } - } - OUTPUT(_T("Cleanup finished.")); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// EnterBitmapFileName - enters a bitmap filename - -int __stdcall EnterBitmapFileName(char* szDest) -{ - char szFilter[512]; - OPENFILENAMEA ofn = { 0 }; - *szDest = 0; - - CallService(MS_UTILS_GETBITMAPFILTERSTRINGS, sizeof szFilter, (LPARAM)szFilter); - ofn.lStructSize = sizeof(OPENFILENAME); - ofn.lpstrFilter = szFilter; - ofn.lpstrFile = szDest; - ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; - ofn.nMaxFile = MAX_PATH; - ofn.nMaxFileTitle = MAX_PATH; - ofn.lpstrDefExt = "bmp"; - if (!GetOpenFileNameA(&ofn)) - return 1; - - return ERROR_SUCCESS; -} - -int MirandaExit(WPARAM wParam, LPARAM lParam) { - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(lParam); - - MirandaShuttingDown = TRUE; - return 0; -} - -int OkToExit(WPARAM wParam, LPARAM lParam) { - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(lParam); - - // logoff_contacts(); - MirandaShuttingDown = TRUE; - - // Trigger all semaphores and events just to be sure that there is no deadlock - ReleaseSemaphore(SkypeMsgReceived, receivers, NULL); - SetEvent(SkypeReady); - SetEvent(MessagePumpReady); -#ifdef SKYPEBUG_OFFLN - SetEvent(GotUserstatus); -#endif - SetEvent(hBuddyAdded); - - SkypeFlush(); - PostMessage(g_hWnd, WM_CLOSE, 0, 0); - return 0; -} - - -struct PLUGINDI { - char **szSettings; - int dwCount; -}; - -// Taken from pluginopts.c and modified -int EnumOldPluginName(const char *szSetting, LPARAM lParam) -{ - struct PLUGINDI *pdi = (struct PLUGINDI*)lParam; - if (pdi && lParam) { - pdi->szSettings = (char**)realloc(pdi->szSettings, (pdi->dwCount + 1)*sizeof(char*)); - pdi->szSettings[pdi->dwCount++] = _strdup(szSetting); - } - return 0; -} - -// Are there any Skype users on list? -// 1 --> Yes -// 0 --> No -int AnySkypeusers(void) -{ - MCONTACT hContact; - DBVARIANT dbv; - int tCompareResult; - - // already on list? - for (hContact = db_find_first(); - hContact != NULL; - hContact = db_find_next(hContact)) - { - // GETCONTACTBASEPROTO doesn't work on not loaded protocol, therefore get - // protocol from DB - if (db_get_s(hContact, "Protocol", "p", &dbv)) continue; - tCompareResult = !strcmp(dbv.pszVal, SKYPE_PROTONAME); - db_free(&dbv); - if (tCompareResult) return 1; - } - return 0; -} - - -/*void UpgradeName(char *OldName) -{ -DBCONTACTENUMSETTINGS cns; -DBCONTACTWRITESETTING cws; -DBVARIANT dbv; -MCONTACT hContact=NULL; -struct PLUGINDI pdi; - -LOG(("Updating old database settings if there are any...")); -cns.pfnEnumProc=EnumOldPluginName; -cns.lParam=(LPARAM)&pdi; -cns.szModule=OldName; -cns.ofsSettings=0; - -hContact = db_find_first(SKYPE_PROTONAME); - -for ( ;; ) { -memset(&pdi,0,sizeof(pdi)); -CallService(MS_DB_CONTACT_ENUMSETTINGS,hContact,(LPARAM)&cns); -// Upgrade Protocol settings to new string -if (pdi.szSettings) { -int i; - -LOG(("We're currently upgrading...")); -for (i=0;i 0 && !Miranda_Terminated()) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - UnregisterClass(WndClass.lpszClassName, hInst); - LOG(("Messagepump stopped.")); -} - -// DLL Stuff // - -#ifdef IS_MIRANDAIM -EXPORT PLUGININFO* MirandaPluginInfo(DWORD mirVersion) -{ - mirandaVersion = mirVersion; - - pluginInfo.cbSize = sizeof(PLUGININFO); - return (PLUGININFO*) &pluginInfo; -} -#endif - -EXPORT PLUGININFOEX* MirandaPluginInfoEx(DWORD mirVersion) -{ - mirandaVersion = mirVersion; - - return &pluginInfo; -} - -static const MUUID interfaces[] = {MUUID_SKYPE_CALL, MIID_LAST}; -EXPORT const MUUID * MirandaPluginInterfaces(void) -{ - return interfaces; -} - - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - UNREFERENCED_PARAMETER(fdwReason); - UNREFERENCED_PARAMETER(lpvReserved); - - hInst = hinstDLL; - return TRUE; -} - - -int PreShutdown(WPARAM wParam, LPARAM lParam) { - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(lParam); - - PostThreadMessage(msgPumpThreadId, WM_QUIT, 0, 0); - return 0; -} - -#ifdef IS_MIRANDAIM -EXPORT int Load(PLUGINLINK *link) -#else -EXPORT int Load(void) -#endif -{ - PROTOCOLDESCRIPTOR pd = { 0 }; - DWORD Buffsize; - HKEY MyKey; - BOOL SkypeInstalled; - BOOL UseCustomCommand; - WSADATA wsaData; - char path[MAX_PATH]; - -#ifdef IS_MIRANDAIM - pluginLink = link; - mir_getMMI( &mmi ); - - // Used to enable Copy DLL hack in older Miranda versions for muliple accounts - GetModuleFileNameA( hInst, path, sizeof( path )); - _splitpath (path, NULL, NULL, SKYPE_PROTONAME, NULL); - CharUpperA( SKYPE_PROTONAME ); - -#else - mir_getLP(&pluginInfo); -#endif - - InitializeCriticalSection(&RingAndEndcallMutex); - InitializeCriticalSection(&QueryThreadMutex); - InitializeCriticalSection(&TimeMutex); - - -#ifdef _DEBUG - init_debug(); -#endif - - LOG(("Load: Skype Plugin loading...")); - - // We need to upgrade SKYPE_PROTOCOL internal name to Skype if not already done - /* if (!db_get_b(NULL, SKYPE_PROTONAME, "UpgradeDone", 0)) - UpgradeName("SKYPE_PROTOCOL");*/ - - // Initialisation of Skype MsgQueue must be done because of Cleanup in end and - // Mutex is also initialized here. - LOG(("SkypeMsgInit initializing Skype MSG-queue")); - if (SkypeMsgInit() == -1) { - OUTPUT(_T("Memory allocation error on startup.")); - return 0; - } - - // On first run on new profile, ask user, if he wants to enable the plugin in - // this profile - // --> Fixing Issue #0000006 from bugtracker. - if (!db_get_b(NULL, SKYPE_PROTONAME, "FirstRun", 0)) { - db_set_b(NULL, SKYPE_PROTONAME, "FirstRun", 1); - if (AnySkypeusers() == 0) // First run, it seems :) - if (MessageBox(NULL, TranslateT("This seems to be the first time that you're running the Skype protocol plugin. Do you want to enable the protocol for this Miranda profile? If you chose NO, you can always enable it in the plugin options later."), _T("Welcome!"), MB_ICONQUESTION | MB_YESNO) == IDNO) { - char path[MAX_PATH], *filename; - GetModuleFileNameA(hInst, path, sizeof(path)); - if (filename = strrchr(path, '\\') + 1) - db_set_b(NULL, "PluginDisable", filename, 1); - return 0; - } - } - - - // Check if Skype is installed - SkypeInstalled = TRUE; - UseCustomCommand = (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "UseCustomCommand", 0); - UseSockets = (BOOL)db_get_b(NULL, SKYPE_PROTONAME, "UseSkype2Socket", 0); - - if (!UseSockets && !UseCustomCommand) - { - if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\Skype\\Phone"), 0, KEY_READ, &MyKey) != ERROR_SUCCESS) - { - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\Skype\\Phone"), 0, KEY_READ, &MyKey) != ERROR_SUCCESS) - { - SkypeInstalled = FALSE; - } - } - - Buffsize = sizeof(skype_path); - - if (SkypeInstalled == FALSE || RegQueryValueExA(MyKey, "SkypePath", NULL, NULL, (unsigned char *)skype_path, &Buffsize) != ERROR_SUCCESS) - { - //OUTPUT("Skype was not found installed :( \nMaybe you are using portable Skype."); - RegCloseKey(MyKey); - skype_path[0] = 0; - //return 0; - } - RegCloseKey(MyKey); - } - WSAStartup(MAKEWORD(2, 2), &wsaData); - - // Start Skype connection - if (!(ControlAPIAttach = RegisterWindowMessage(_T("SkypeControlAPIAttach"))) || !(ControlAPIDiscover = RegisterWindowMessage(_T("SkypeControlAPIDiscover")))) - { - OUTPUT(_T("Cannot register Window message.")); - return 0; - } - - SkypeMsgReceived = CreateSemaphore(NULL, 0, MAX_MSGS, NULL); - if (!(SkypeReady = CreateEvent(NULL, TRUE, FALSE, NULL)) || - !(MessagePumpReady = CreateEvent(NULL, FALSE, FALSE, NULL)) || -#ifdef SKYPEBUG_OFFLN - !(GotUserstatus = CreateEvent(NULL, TRUE, FALSE, NULL)) || -#endif - !(hBuddyAdded = CreateEvent(NULL, FALSE, FALSE, NULL)) || - !(FetchMessageEvent = CreateEvent(NULL, FALSE, TRUE, NULL))) { - OUTPUT(_T("Unable to create Mutex!")); - return 0; - } - - /* Register the module */ - pd.cbSize = PROTOCOLDESCRIPTOR_V3_SIZE; - pd.szName = SKYPE_PROTONAME; - pd.type = PROTOTYPE_PROTOCOL; - CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd); - - VoiceServiceInit(); - - CreateServices(); - HookEvents(); - InitVSApi(); - MsgList_Init(); - - HookEvent(ME_SYSTEM_PRESHUTDOWN, PreShutdown); - - // Startup Message-pump - pthread_create((pThreadFunc)MsgPump, NULL); - WaitForSingleObject(MessagePumpReady, INFINITE); - return 0; -} - - - -EXPORT int Unload(void) -{ - BOOL UseCustomCommand = db_get_b(NULL, SKYPE_PROTONAME, "UseCustomCommand", 0); - BOOL Shutdown = db_get_b(NULL, SKYPE_PROTONAME, "Shutdown", 0); - - LOG(("Unload started")); - - if (Shutdown && ((skype_path && skype_path[0]) || UseCustomCommand)) { - - if (UseCustomCommand) - { - DBVARIANT dbv; - if (!db_get_s(NULL, SKYPE_PROTONAME, "CommandLine", &dbv)) - { - char szAbsolutePath[MAX_PATH]; - - TranslateMirandaRelativePathToAbsolute(dbv.pszVal, szAbsolutePath, FALSE); - _spawnl(_P_NOWAIT, szAbsolutePath, szAbsolutePath, "/SHUTDOWN", NULL); - LOG(("Unload Sent /shutdown to %s", szAbsolutePath)); - db_free(&dbv); - } - } - else - { - _spawnl(_P_NOWAIT, skype_path, skype_path, "/SHUTDOWN", NULL); - LOG(("Unload Sent /shutdown to %s", skype_path)); - } - - } - SkypeMsgCleanup(); - //WSACleanup(); - FreeVSApi(); - UnhookEvents(); - UnhookEvent(hChatEvent); - UnhookEvent(hChatMenu); - UnhookEvent(hEvInitChat); - DestroyHookableEvent(hInitChat); - VoiceServiceExit(); - GCExit(); - MsgList_Exit(); - - CloseHandle(SkypeReady); - CloseHandle(SkypeMsgReceived); -#ifdef SKYPEBUG_OFFLN - CloseHandle(GotUserstatus); -#endif - CloseHandle(MessagePumpReady); - CloseHandle(hBuddyAdded); - CloseHandle(FetchMessageEvent); - - DeleteCriticalSection(&RingAndEndcallMutex); - DeleteCriticalSection(&QueryThreadMutex); - - SkypeRegisterProxy(0, 0); - LOG(("Unload: Shutdown complete")); -#ifdef _DEBUG - end_debug(); -#endif - DeleteCriticalSection(&TimeMutex); - return 0; -} - diff --git a/protocols/SkypeClassic/src/skype.cpp b/protocols/SkypeClassic/src/skype.cpp new file mode 100644 index 0000000000..6f155010aa --- /dev/null +++ b/protocols/SkypeClassic/src/skype.cpp @@ -0,0 +1,3433 @@ +/* + +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 "skype.h" +#include "debug.h" +#include "skypeapi.h" +#include "skypesvc.h" +#include "contacts.h" +#include "utf8.h" +#include "pthread.h" +#include "gchat.h" +#include "m_toptoolbar.h" + +inline BOOL HasVoiceService() { return FALSE; } + +#include "msglist.h" +#include "memlist.h" +#include +#ifndef INVALID_FILE_ATTRIBUTES +#define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF +#endif +#ifdef _WIN64 +#if (_MSC_VER < 1500) +#pragma comment (lib, "bufferoverflowU.lib") +#endif +#endif + +#pragma warning (disable: 4706) // assignment within conditional expression + +POPUPDATAT MessagePopup; + +// Exported Globals +HWND hSkypeWnd = NULL, g_hWnd = NULL, hSkypeWndSecondary = NULL, hForbiddenSkypeWnd = NULL; +HANDLE SkypeReady, SkypeMsgReceived, hInitChat = NULL, httbButton = NULL, FetchMessageEvent = NULL; +BOOL SkypeInitialized = FALSE, MirandaShuttingDown = FALSE, PopupServiceExists = FALSE; +BOOL UseSockets = FALSE, bSkypeOut = FALSE, bProtocolSet = FALSE, bIsImoproxy = FALSE; +char skype_path[MAX_PATH], protocol = 2, *pszProxyCallout = NULL, g_szProtoName[_MAX_FNAME] = "SkypeClassic"; +int SkypeStatus = ID_STATUS_OFFLINE, hSearchThread = -1, receivers = 1; +long sendwatchers = 0, rcvwatchers = 0; +UINT ControlAPIAttach, ControlAPIDiscover; +LONG AttachStatus = -1; +HINSTANCE hInst; +HANDLE hProtocolAvatarsFolder; +char DefaultAvatarsFolder[MAX_PATH + 1]; +DWORD mirandaVersion; +int hLangpack = 0; + +CRITICAL_SECTION RingAndEndcallMutex, QueryThreadMutex, TimeMutex; + +// Module Internal Globals +HANDLE MessagePumpReady; +HANDLE hChatEvent = NULL, hChatMenu = NULL; +HANDLE hEvInitChat = NULL, hBuddyAdded = NULL; +HANDLE hMenuAddSkypeContact = NULL; + +DWORD msgPumpThreadId = 0; +#ifdef SKYPEBUG_OFFLN +HANDLE GotUserstatus; +#endif + +BOOL bModulesLoaded = FALSE; +char *RequestedStatus = NULL; // To fix Skype-API Statusmode-bug +char cmdMessage[12] = "MESSAGE", cmdPartner[8] = "PARTNER"; // Compatibility commands + + + +// Direct assignment of user properties to a DB-Setting +static const settings_map m_settings[] = { + { "LANGUAGE", "Language1" }, + { "PROVINCE", "State" }, + { "CITY", "City" }, + { "PHONE_HOME", "Phone" }, + { "PHONE_OFFICE", "CompanyPhone" }, + { "PHONE_MOBILE", "Cellular" }, + { "HOMEPAGE", "Homepage" }, + { "ABOUT", "About" } +}; + +// Imported Globals +extern status_map status_codes[]; + +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 + +typedef struct { + char msgnum[16]; + BOOL getstatus; + BOOL bIsRead; + BOOL bDontMarkSeen; + BOOL QueryMsgDirection; + TYP_MSGLENTRY *pMsgEntry; +} fetchmsg_arg; + +typedef struct { + MCONTACT hContact; + char szId[16]; +} msgsendwt_arg; + +/* + * 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; +} + +// Plugin Info +PLUGININFOEX pluginInfo = { + sizeof(PLUGININFOEX), + __PLUGIN_NAME, + PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), + __DESCRIPTION, + __AUTHOR, + __AUTHOREMAIL, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + // {A71F8335-7B87-4432-B8A3-81479431C6F5} + { 0xa71f8335, 0x7b87, 0x4432, { 0xb8, 0xa3, 0x81, 0x47, 0x94, 0x31, 0xc6, 0xf5 } } +}; + +#define MAPDND 1 // Map Occupied to DND status and say that you support it +//#define MAPNA 1 // Map NA status to Away and say that you support it + +/* P R O G R A M */ + +void RegisterToDbeditorpp(void) +{ + // known modules list + if (ServiceExists("DBEditorpp/RegisterSingleModule")) + CallService("DBEditorpp/RegisterSingleModule", (WPARAM)SKYPE_PROTONAME, 0); +} + +/* + * ShowMessage + * + * Shows a popup, if the popup plugin is enabled. + * mustShow: 1 -> If Popup-Plugin is not available/disabled, show Message + * in a Messagewindow + * If the Popup-Plugin is enabled, let the message stay on + * screen until someone clicks it away. + * 0 -> If Popup-Plugin is not available/disabled, skip message + * Returns 0 on success, -1 on failure + * + */ +int ShowMessage(int iconID, TCHAR *lpzText, int mustShow) { + + + + if (db_get_b(NULL, SKYPE_PROTONAME, "SuppressErrors", 0)) return -1; + lpzText = TranslateTS(lpzText); + + if (bModulesLoaded && PopupServiceExists && ServiceExists(MS_POPUP_ADDPOPUPT) && db_get_b(NULL, SKYPE_PROTONAME, "UsePopup", 0) && !MirandaShuttingDown) { + BOOL showPopup, popupWindowColor; + unsigned int popupBackColor, popupTextColor; + int popupTimeSec; + + popupTimeSec = db_get_dw(NULL, SKYPE_PROTONAME, "popupTimeSecErr", 4); + popupTextColor = db_get_dw(NULL, SKYPE_PROTONAME, "popupTextColorErr", GetSysColor(COLOR_WINDOWTEXT)); + popupBackColor = db_get_dw(NULL, SKYPE_PROTONAME, "popupBackColorErr", GetSysColor(COLOR_BTNFACE)); + popupWindowColor = (0 != db_get_b(NULL, SKYPE_PROTONAME, "popupWindowColorErr", TRUE)); + showPopup = (0 != db_get_b(NULL, SKYPE_PROTONAME, "showPopupErr", TRUE)); + + MessagePopup.lchContact = NULL; + MessagePopup.lchIcon = LoadIcon(hInst, MAKEINTRESOURCE(iconID)); + MessagePopup.colorBack = !popupWindowColor ? popupBackColor : GetSysColor(COLOR_BTNFACE); + MessagePopup.colorText = !popupWindowColor ? popupTextColor : GetSysColor(COLOR_WINDOWTEXT); + MessagePopup.iSeconds = popupTimeSec; + MessagePopup.PluginData = (void *)1; + + lstrcpy(MessagePopup.lptzText, lpzText); + +#ifdef _UNICODE + mbstowcs(MessagePopup.lptzContactName, SKYPE_PROTONAME, strlen(SKYPE_PROTONAME) + 1); +#else + lstrcpy(MessagePopup.lptzContactName, SKYPE_PROTONAME); +#endif + + if (showPopup) + CallService(MS_POPUP_ADDPOPUPT, (WPARAM)&MessagePopup, 0); + + return 0; + } + else { + + if (mustShow == 1) MessageBox(NULL, lpzText, _T("Skype Protocol"), MB_OK | MB_ICONWARNING); + return 0; + } +} +#ifdef _UNICODE +int ShowMessageA(int iconID, char *lpzText, int mustShow) { + WCHAR *lpwText; + int iRet; + size_t len = mbstowcs(NULL, lpzText, strlen(lpzText)); + if (len == -1 || !(lpwText = (WCHAR*)calloc(len + 1, sizeof(WCHAR)))) return -1; + mbstowcs(lpwText, lpzText, strlen(lpzText)); + iRet = ShowMessage(iconID, lpwText, mustShow); + free(lpwText); + return iRet; +} +#endif + +// processing Hooks + +int HookContactAdded(WPARAM wParam, LPARAM lParam) { + char *szProto; + + UNREFERENCED_PARAMETER(lParam); + + szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); + if (szProto != NULL && !strcmp(szProto, SKYPE_PROTONAME)) + add_contextmenu((MCONTACT)wParam); + return 0; +} + +int HookContactDeleted(WPARAM wParam, LPARAM lParam) { + char *szProto; + + UNREFERENCED_PARAMETER(lParam); + + szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); + if (szProto != NULL && !strcmp(szProto, SKYPE_PROTONAME)) { + DBVARIANT dbv; + int retval; + + if (db_get_s((MCONTACT)wParam, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) return 1; + retval = SkypeSend("SET USER %s BUDDYSTATUS 1", dbv.pszVal); + db_free(&dbv); + if (retval) return 1; + } + return 0; +} + +void GetInfoThread(void *hContact) +{ + DBVARIANT dbv; + int i; + char *ptr; + BOOL bSetNick = FALSE; + // All properties are already handled in the WndProc, so we just consume the + // messages here to do proper ERROR handling + // If you add something here, be sure to handle it in WndProc, but let it + // fall through there so that message gets added to the queue in order to be + // consumed by SkypeGet + char *pszProps[] = { + "BIRTHDAY", "COUNTRY", "SEX", "MOOD_TEXT", "TIMEZONE", "IS_VIDEO_CAPABLE" }; + + LOG(("GetInfoThread started.")); + EnterCriticalSection(&QueryThreadMutex); + if (db_get_s((MCONTACT)hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) + { + LOG(("GetInfoThread terminated, cannot find Skype Name for contact %08X.", hContact)); + LeaveCriticalSection(&QueryThreadMutex); + return; + } + + if (ptr = SkypeGet("USER", dbv.pszVal, "DISPLAYNAME")) { + // WndProc sets Nick accordingly + if (*ptr) bSetNick = TRUE; + free(ptr); + } + + if (ptr = SkypeGet("USER", dbv.pszVal, "FULLNAME")) { + if (*ptr && !bSetNick && db_get_b(NULL, SKYPE_PROTONAME, "ShowFullname", 1)) { + // No Displayname and FULLNAME requested + db_set_utf((MCONTACT)hContact, SKYPE_PROTONAME, "Nick", ptr); + bSetNick = TRUE; + } + free(ptr); + } + + if (!bSetNick) { + // Still no nick set, so use SKYPE Nickname + db_set_s((MCONTACT)hContact, SKYPE_PROTONAME, "Nick", dbv.pszVal); + } + + + if (!bIsImoproxy) + { + for (i = 0; i < sizeof(pszProps) / sizeof(pszProps[0]); i++) + if (ptr = SkypeGet("USER", dbv.pszVal, pszProps[i])) free(ptr); + } + else { + if (ptr = SkypeGet("USER", dbv.pszVal, "MOOD_TEXT")) free(ptr); + } + + if (protocol >= 7 || bIsImoproxy) { + // Notify about the possibility of an avatar + ACKDATA ack = { 0 }; + ack.cbSize = sizeof(ACKDATA); + ack.szModule = SKYPE_PROTONAME; + ack.hContact = (MCONTACT)hContact; + ack.type = ACKTYPE_AVATAR; + ack.result = ACKRESULT_STATUS; + + CallService(MS_PROTO_BROADCASTACK, 0, (LPARAM)&ack); + //if (ptr=SkypeGet ("USER", dbv.pszVal, "RICH_MOOD_TEXT")) free (ptr); + } + + if (!bIsImoproxy) + { + for (i = 0; i < sizeof(m_settings) / sizeof(m_settings[0]); i++) + if (ptr = SkypeGet("USER", dbv.pszVal, m_settings[i].SkypeSetting)) free(ptr); + } + + ProtoBroadcastAck(SKYPE_PROTONAME, (MCONTACT)hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE)1, 0); + LeaveCriticalSection(&QueryThreadMutex); + db_free(&dbv); + LOG(("GetInfoThread terminated gracefully.")); +} + +time_t SkypeTime(time_t *timer) +{ + struct _timeb tb; + + EnterCriticalSection(&TimeMutex); + _ftime(&tb); + if (timer) *timer = tb.time; + LeaveCriticalSection(&TimeMutex); + return tb.time; +} + + +void BasicSearchThread(char *nick) { + PROTOSEARCHRESULT psr = { 0 }; + char *cmd = NULL, *token = NULL, *ptr = NULL, *nextoken; + time_t st; + + LOG(("BasicSearchThread started.")); + EnterCriticalSection(&QueryThreadMutex); + SkypeTime(&st); + if (SkypeSend("SEARCH USERS %s", nick) == 0 && (cmd = SkypeRcvTime("USERS", st, INFINITE))) { + if (strncmp(cmd, "ERROR", 5)) { + psr.cbSize = sizeof(psr); + for (token = strtok_r(cmd + 5, ", ", &nextoken); token; token = strtok_r(NULL, ", ", &nextoken)) { + psr.nick = psr.id = _A2T(token); + psr.lastName = NULL; + psr.firstName = NULL; + psr.email = NULL; + if (ptr = SkypeGet("USER", token, "FULLNAME")) { + // We cannot use strtok() to seperate first & last name here, + // because we already use it for parsing the user list + // So we use our own function + if (psr.lastName = _A2T(strchr(ptr, ' '))) { + *psr.lastName = 0; + psr.lastName++; + LOG(("BasicSearchThread: lastName=%s", psr.lastName)); + } + psr.firstName = _A2T(ptr); + LOG(("BasicSearchThread: firstName=%s", psr.firstName)); + } + ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)hSearchThread, (LPARAM)(PROTOSEARCHRESULT*)&psr); + if (ptr) free(ptr); + } + } + else { + OUT(cmd); + } + free(cmd); + } + ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)hSearchThread, 0); + free(nick); + LeaveCriticalSection(&QueryThreadMutex); + LOG(("BasicSearchThread terminated gracefully.")); + return; +} + +// added by TioDuke +void GetDisplaynameThread(char *dummy) { + DBVARIANT dbv; + char *ptr; + + UNREFERENCED_PARAMETER(dummy); + + LOG(("GetDisplaynameThread started.")); + if (db_get_s(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) { + LOG(("GetDisplaynameThread terminated.")); + return; + } + EnterCriticalSection(&QueryThreadMutex); + if ((ptr = SkypeGet("USER", dbv.pszVal, "FULLNAME"))) { + if (*ptr) db_set_utf(NULL, SKYPE_PROTONAME, "Nick", ptr); + free(ptr); + } + db_free(&dbv); + LeaveCriticalSection(&QueryThreadMutex); + LOG(("GetDisplaynameThread terminated gracefully.")); +} + + +// Starts importing history from Skype +INT_PTR ImportHistory(WPARAM wParam, LPARAM lParam) { + DBVARIANT dbv; + + UNREFERENCED_PARAMETER(lParam); + + if (db_get_b((MCONTACT)wParam, SKYPE_PROTONAME, "ChatRoom", 0)) { + if (db_get_s((MCONTACT)wParam, SKYPE_PROTONAME, "ChatRoomID", &dbv)) return 0; + SkypeSend("GET CHAT %s CHATMESSAGES", dbv.pszVal); + } + else { + if (db_get_s((MCONTACT)wParam, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) return 0; + SkypeSend("SEARCH %sS %s", cmdMessage, dbv.pszVal); + } + db_free(&dbv); + return 0; +} + +int SearchFriends(void) { + char *ptr, *token, *pStat, *nextoken; + int iRet = 0; + time_t st; + + SkypeTime(&st); + if (SkypeSend("SEARCH FRIENDS") != -1 && (ptr = SkypeRcvTime("USERS", st, INFINITE))) + { + if (strncmp(ptr, "ERROR", 5)) { + if (ptr + 5) { + for (token = strtok_r(ptr + 5, ", ", &nextoken); token; token = strtok_r(NULL, ", ", &nextoken)) { + if (!(pStat = SkypeGet("USER", token, "ONLINESTATUS"))) + { + iRet = -1; + break; + } + free(pStat); + } + } + } + else iRet = -1; + free(ptr); + } + else iRet = -1; + return iRet; +} + +static void QueryUserWaitingAuthorization(char *pszNick, char *pszAuthRq) +{ + CCSDATA ccs={0}; + PROTORECVEVENT pre={0}; + MCONTACT hContact; + char *firstname=NULL, *lastname=NULL, *pCurBlob, *authmsg=NULL; + + LOG(("Awaiting auth: %s", pszNick)); + ccs.szProtoService=PSR_AUTH; + ccs.hContact = hContact = add_contact(pszNick, PALF_TEMPORARY); + ccs.wParam = 0; + ccs.lParam = (LPARAM)⪯ + pre.flags = 0; + pre.timestamp = (DWORD)SkypeTime(NULL); + + /* blob is: */ + //DWORD protocolSpecific HANDLE hContact + //ASCIIZ nick, firstName, lastName, e-mail, requestReason + if (firstname=SkypeGet("USER", pszNick, "FULLNAME")) { + if (mirandaVersion < 0x070000) { + char *tmp; + + if (utf8_decode(firstname, &tmp)!=-1) { + free (firstname); + firstname = tmp; + } + } + if (lastname=strchr(firstname, ' ')) { + *lastname=0; + lastname++; + } + } + + pre.lParam = sizeof(DWORD) + sizeof(HANDLE) + strlen(pszNick) + 5; + if (firstname) pre.lParam += strlen(firstname); + if (lastname) pre.lParam += strlen(lastname); + if (pszAuthRq) authmsg = strdup(pszAuthRq); + if (authmsg || ((protocol>=4 || bIsImoproxy) && (authmsg=SkypeGetID("USER", pszNick, "RECEIVEDAUTHREQUEST")))) + pre.lParam+=strlen(authmsg); + if (pre.szMessage = pCurBlob = (char *)calloc(1, pre.lParam)) { + pCurBlob+=sizeof(DWORD); // Not used + memcpy(pCurBlob, &hContact, sizeof(HANDLE)); pCurBlob += sizeof(HANDLE); + + if (mirandaVersion >= 0x070000) // 0.7.0+ supports PREF_UTF flag, no need to decode UTF8 + pre.flags |= PREF_UTF; + else { + char *tmp; + + if (authmsg && utf8_decode(authmsg, &tmp)!=-1) { + free (authmsg); + authmsg = tmp; + } + } + + sprintf (pCurBlob, "%s%c%s%c%s%c%c%s", pszNick, 0, firstname?firstname:"", 0, lastname?lastname:"", 0, 0, authmsg?authmsg:""); + + CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs); + free(pre.szMessage); + } + if (firstname) free(firstname); + if (authmsg) free (authmsg); + return; +} + + +void __cdecl ProcessAuthRq(void *pPmsg) { + char *nick, *auth; + + strtok ((char*)pPmsg, " "); + nick = strtok (NULL, " "); + strtok (NULL, " "); + auth = strtok (NULL, ""); + QueryUserWaitingAuthorization(nick, auth); + free (pPmsg); +} + +void __cdecl SearchUsersWaitingMyAuthorization(void *dummy) { + char *cmd, *token, *nextoken; + + UNREFERENCED_PARAMETER(dummy); + + if (SkypeSend("#UWA SEARCH USERSWAITINGMYAUTHORIZATION")) return; + if (!(cmd = SkypeRcv("#UWA USERS", INFINITE))) return; + if (!strncmp(cmd, "ERROR", 5)) { + free(cmd); + return; + } + + token = strtok_r(cmd + 10, ", ", &nextoken); + while (token) { + QueryUserWaitingAuthorization (token, NULL); + token=strtok_r(NULL, ", ", &nextoken); + } + free(cmd); + return; +} + +void SearchFriendsThread(char *dummy) { + UNREFERENCED_PARAMETER(dummy); + + if (!SkypeInitialized) return; + LOG(("SearchFriendsThread started.")); + EnterCriticalSection(&QueryThreadMutex); + SkypeInitialized = FALSE; + SearchFriends(); + SkypeInitialized = TRUE; + LeaveCriticalSection(&QueryThreadMutex); + LOG(("SearchFriendsThread terminated gracefully.")); +} + +void __cdecl SearchRecentChats(void *dummy) { + char *cmd, *token, *nextoken; + + UNREFERENCED_PARAMETER(dummy); + + if (SkypeSend("#RCH SEARCH RECENTCHATS")) return; + if (!(cmd = SkypeRcv("#RCH CHATS", INFINITE))) return; + if (!strncmp(cmd, "ERROR", 5)) { + free(cmd); + return; + } + + for (token = strtok_r(cmd + 10, ", ", &nextoken); token; token = strtok_r(NULL, ", ", &nextoken)) { + char *pszStatus = SkypeGet("CHAT", token, "STATUS"); + + if (pszStatus) { + if (!strcmp(pszStatus, "MULTI_SUBSCRIBED")) { + // Add chatrooms for active multisubscribed chats + /*if (!find_chatA(token)) */{ + char *pszTopic; + + EnterCriticalSection(&QueryThreadMutex); + ChatStart(token, TRUE); + if (pszTopic = SkypeGet("CHAT", token, "TOPIC")) { + TCHAR *psztChatName, *psztTopic; + + if (!*pszTopic) { + free(pszTopic); + pszTopic = SkypeGet("CHAT", token, "FRIENDLYNAME"); + } + psztChatName = make_nonutf_tchar_string((const unsigned char*)token); + psztTopic = make_tchar_string((const unsigned char*)pszTopic); + SetChatTopic(psztChatName, psztTopic, FALSE); + free_nonutf_tchar_string(psztChatName); + free(psztTopic); + free(pszTopic); + } + LeaveCriticalSection(&QueryThreadMutex); + } + } + free(pszStatus); + } + } + free(cmd); + return; +} + + +void __cdecl SkypeSystemInit(char *dummy) { + static BOOL Initializing = FALSE; + DBVARIANT dbv = { 0 }; + + UNREFERENCED_PARAMETER(dummy); + + LOG(("SkypeSystemInit thread started.")); + if (SkypeInitialized || Initializing) + { + LOG(("SkypeSystemInit terminated, nothing to do.")); + return; + } + Initializing = TRUE; + // Do initial Skype-Tasks + logoff_contacts(FALSE); + // Add friends + + // Clear currentuserhandle entries from queue + while (testfor("CURRENTUSERHANDLE", 0)); + if (SkypeSend(SKYPE_PROTO) == -1 || !testfor("PROTOCOL", INFINITE) || + SkypeSend("GET CURRENTUSERHANDLE") == -1 || + SkypeSend("GET PRIVILEGE SKYPEOUT") == -1) { + Initializing = FALSE; + LOG(("SkypeSystemInit thread stopped with failure.")); + return; + } + + if (db_get_s(NULL, SKYPE_PROTONAME, "LoginUserName", &dbv) == 0) + { + if (*dbv.pszVal) + { + char *pszUser; + + // Username is set in Plugin, therefore we need to match it + // against CURRENTUSERHANDLE + if (pszUser = SkypeRcv("CURRENTUSERHANDLE", INFINITE)) + { + memmove(pszUser, pszUser + 18, strlen(pszUser + 17)); + if (_stricmp(dbv.pszVal, pszUser)) + { + char szError[256]; + + // Doesn't match, maybe we have a second Skype instance we have to take + // care of? If in doubt, let's wait a while for it to report its hWnd to us. + LOG(("Userhandle %s doesn't match username %s from settings", pszUser, dbv.pszVal)); + if (!hSkypeWndSecondary) Sleep(3000); + if (hSkypeWndSecondary) + { + hSkypeWnd = hSkypeWndSecondary; + hSkypeWndSecondary = NULL; + Initializing = FALSE; + while (testfor("CURRENTUSERHANDLE", 0)); + LOG(("Trying to init secondary Skype instance")); + SkypeSystemInit(dummy); + } + else + { + hForbiddenSkypeWnd = hSkypeWnd; + + // If we need to start Skype as secondary instance, we should do it now + if (db_get_b(NULL, SKYPE_PROTONAME, "StartSkype", 1) && + db_get_b(NULL, SKYPE_PROTONAME, "secondary", 0)) + { + int oldstatus; + + hSkypeWnd = NULL; + AttachStatus = -1; + if (g_hWnd) KillTimer(g_hWnd, 1); + oldstatus = SkypeStatus; + InterlockedExchange((long *)&SkypeStatus, ID_STATUS_CONNECTING); + ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldstatus, SkypeStatus); + ConnectToSkypeAPI(skype_path, 1); + } + if (hForbiddenSkypeWnd == hSkypeWnd && !hSkypeWndSecondary) + { + int oldstatus; + + sprintf(szError, "Username '%s' provided by Skype API doesn't match username '%s' in " + "your settings. Please either remove username setting in you configuration or correct " + "it. Will not connect!", pszUser, dbv.pszVal); + OUTPUTA(szError); + Initializing = FALSE; + AttachStatus = -1; + logoff_contacts(FALSE); + if (g_hWnd) KillTimer(g_hWnd, 1); + hSkypeWnd = NULL; + oldstatus = SkypeStatus; + InterlockedExchange((long *)&SkypeStatus, ID_STATUS_OFFLINE); + ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldstatus, SkypeStatus); + } + } + } + free(pszUser); + } + } + db_free(&dbv); + if (!Initializing) return; + } + +#ifdef SKYPEBUG_OFFLN + if (!ResetEvent(GotUserstatus) || SkypeSend("GET USERSTATUS") == -1 || + WaitForSingleObject(GotUserstatus, INFINITE) == WAIT_FAILED) + { + LOG(("SkypeSystemInit thread stopped with failure.")); + Initializing = FALSE; + return; + } + if (SkypeStatus != ID_STATUS_OFFLINE) +#endif + if (SearchFriends() == -1) { + LOG(("SkypeSystemInit thread stopped with failure.")); + Initializing = FALSE; + return; + } + if (protocol >= 5 || bIsImoproxy) { + SkypeSend("CREATE APPLICATION libpurple_typing"); + testfor("CREATE APPLICATION libpurple_typing", 2000); + } + if (protocol>=5) { + SearchUsersWaitingMyAuthorization(NULL); + if (db_get_b(NULL, SKYPE_PROTONAME, "UseGroupchat", 0)) + SearchRecentChats(NULL); + } + SkypeSend("SEARCH MISSED%sS", cmdMessage); + + +#ifndef SKYPEBUG_OFFLN + if (SkypeSend("GET USERSTATUS")==-1) + { + LOG (("SkypeSystemInit thread stopped with failure.")); + Initializing=FALSE; + return; + } +#endif + SetTimer(g_hWnd, 1, PING_INTERVAL, NULL); + SkypeInitialized = TRUE; + Initializing = FALSE; + LOG(("SkypeSystemInit thread terminated gracefully.")); + return; +} + +void FirstLaunch(char *dummy) { + int counter = 0; + + UNREFERENCED_PARAMETER(dummy); + + LOG(("FirstLaunch thread started.")); + if (!db_get_b(NULL, SKYPE_PROTONAME, "StartSkype", 1) || ConnectToSkypeAPI(skype_path, FALSE) == -1) + { + int oldstatus = SkypeStatus; + + LOG(("OnModulesLoaded starting offline..")); + InterlockedExchange((long *)&SkypeStatus, ID_STATUS_OFFLINE); + ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldstatus, SkypeStatus); + } + if (AttachStatus == -1 || AttachStatus == SKYPECONTROLAPI_ATTACH_REFUSED || AttachStatus == SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE) { + LOG(("FirstLaunch thread stopped because of invalid Attachstatus.")); + return; + } + + // When you launch Skype and Attach is Successfull, it still takes some time + // until it becomes available for receiving messages. + // Let's probe this with PINGing + LOG(("CheckIfApiIsResponding Entering test loop")); + for (;;) { + LOG(("Test #%d", counter)); + if (SkypeSend("PING") == -1) counter++; else break; + if (counter >= 20) { + OUTPUT(_T("Cannot reach Skype API, plugin disfunct.")); + LOG(("FirstLaunch thread stopped: cannot reach Skype API.")); + return; + } + Sleep(500); + } + LOG(("CheckIfApiIsResponding: Testing for PONG")); + testfor("PONG", 2000); // Flush PONG from MsgQueue + + pthread_create((pThreadFunc)SkypeSystemInit, NULL); + LOG(("FirstLaunch thread terminated gracefully.")); +} + +int CreateTopToolbarButton(WPARAM wParam, LPARAM lParam) { + TTBButton ttb = { 0 }; + + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + + ttb.cbSize = sizeof(ttb); + ttb.dwFlags = TTBBF_VISIBLE | TTBBF_SHOWTOOLTIP; + ttb.name = Translate("Do a SkypeOut-call"); +#ifdef TTB_WINDOW_HANDLE + /* New Top toolbar */ + ttb.hIconHandleDn = ttb.hIconHandleUp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_CALL)); + ttb.pszService = SKYPEOUT_CALL; + if ((int)(TopToolbar_AddButton(&ttb)) == -1) httbButton = 0; +#else + /* Old Top toolbar */ + ttb.dwFlags |= TTBBF_DRAWBORDER; + ttb.hbBitmapDown = ttb.hbBitmapUp = LoadBitmap(hInst,MAKEINTRESOURCE(IDB_CALL)); + ttb.pszServiceDown = ttb.pszServiceUp = SKYPEOUT_CALL; + if ((int)(httbButton=(HANDLE)CallService(MS_TTB_ADDBUTTON, (WPARAM)&ttb, 0))==-1) httbButton=0; +#endif + return 0; +} + + +int OnModulesLoaded(WPARAM wParam, LPARAM lParam) { + bModulesLoaded = TRUE; + + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + + PopupServiceExists = ServiceExists(MS_POPUP_ADDPOPUPT); + + logoff_contacts(FALSE); + + HookEventsLoaded(); + RegisterToDbeditorpp(); + + GCInit(); + + add_contextmenu(NULL); + if (ServiceExists(MS_GC_REGISTER)) + { + GCREGISTER gcr = {0}; + static COLORREF crCols[1] = {0}; + char szEvent[MAXMODULELABELLENGTH]; + + + gcr.cbSize = sizeof( GCREGISTER ); + gcr.dwFlags = GC_CHANMGR; // |GC_ACKMSG; // TODO: Not implemented yet + gcr.dwFlags |= GC_TCHAR; + gcr.ptszDispName = _T("Skype protocol"); + gcr.pszModule = SKYPE_PROTONAME; + if (CallService(MS_GC_REGISTER, 0, (LPARAM)&gcr)) + OUTPUT(_T("Unable to register with Groupchat module!")); + + _snprintf(szEvent, sizeof(szEvent), "%s\\ChatInit", SKYPE_PROTONAME); + hInitChat = CreateHookableEvent(szEvent); + hEvInitChat = HookEvent(szEvent, ChatInit); + + hChatEvent = HookEvent(ME_GC_EVENT, GCEventHook); + hChatMenu = HookEvent(ME_GC_BUILDMENU, GCMenuHook); + CreateServiceFunction(SKYPE_CHATNEW, SkypeChatCreate); + CreateProtoService(PS_LEAVECHAT, GCOnLeaveChat); + CreateProtoService(PS_JOINCHAT, GCOnJoinChat); + } + // Try folder service first + hProtocolAvatarsFolder = NULL; + if (ServiceExists(MS_FOLDERS_REGISTER_PATH)) + { + char *tmpPath; + + if (!ServiceExists(MS_UTILS_REPLACEVARS) || !(tmpPath = Utils_ReplaceVars("%miranda_avatarcache%"))) + tmpPath = PROFILE_PATH; + mir_snprintf(DefaultAvatarsFolder, sizeof(DefaultAvatarsFolder), "%s\\%s", tmpPath, SKYPE_PROTONAME); + hProtocolAvatarsFolder = (HANDLE)FoldersRegisterCustomPath(SKYPE_PROTONAME, "Avatars Cache", DefaultAvatarsFolder); + } + + if (hProtocolAvatarsFolder == NULL) + { + // Use defaults + CallService(MS_DB_GETPROFILEPATH, (WPARAM)MAX_PATH, (LPARAM)DefaultAvatarsFolder); + mir_snprintf(DefaultAvatarsFolder, sizeof(DefaultAvatarsFolder), "%s\\%s", DefaultAvatarsFolder, SKYPE_PROTONAME); + CreateDirectoryA(DefaultAvatarsFolder, NULL); + } + + pthread_create((pThreadFunc)FirstLaunch, NULL); + return 0; +} + +void FetchMessageThread(fetchmsg_arg *pargs) { + char *who = NULL, *type = NULL, *chat = NULL, *users = NULL, *msg = NULL, *status = NULL; + char *ptr, *msgptr, szPartnerHandle[32], szBuf[128]; + int direction = 0, msglen = 0; + DWORD timestamp = 0, lwr = 0; + CCSDATA ccs = { 0 }; + PROTORECVEVENT pre = { 0 }; + MCONTACT hContact = NULL, hChat = NULL; + HANDLE hDbEvent; + DBEVENTINFO dbei = { 0 }; + DBVARIANT dbv = { 0 }; + fetchmsg_arg args; + BOOL bEmoted = FALSE, isGroupChat = FALSE, bHasPartList = FALSE; + BOOL bUseGroupChat = db_get_b(NULL, SKYPE_PROTONAME, "UseGroupchat", 0); + + if (!pargs) return; + args = *pargs; + free(pargs); + + sprintf(szPartnerHandle, "%s_HANDLE", cmdPartner); + pre.lParam = strtoul(args.msgnum, NULL, 10); + if (args.bIsRead) pre.flags |= PREF_CREATEREAD; + //pEvent = MsgList_FindMessage(pre.lParam); + + // Get Timestamp + if (!args.pMsgEntry || !args.pMsgEntry->tEdited) { + if (!(ptr=SkypeGet (cmdMessage, args.msgnum, "TIMESTAMP"))) return; + if (strncmp(ptr, "ERROR", 5)) { + timestamp=atol(ptr); + // Ensure time correction on clock skew... + if (timestamp>(DWORD)SkypeTime(NULL)) timestamp=(DWORD)SkypeTime(NULL); + } + else timestamp=(DWORD)SkypeTime(NULL); + free(ptr); + } + else timestamp = (DWORD)(args.pMsgEntry->tEdited); + + __try { + // Get Chatname (also to determine if we need to relay this to a groupchat) + if (!(chat = SkypeGetErr(cmdMessage, args.msgnum, "CHATNAME"))) __leave; + if (hChat = find_chatA(chat)) isGroupChat = TRUE; + + // Get chat status + if ((status = SkypeGetErr("CHAT", chat, "STATUS")) && + !strcmp(status, "MULTI_SUBSCRIBED")) isGroupChat = TRUE; + + // Get chat type + if (!(type = SkypeGetErr(cmdMessage, args.msgnum, "TYPE"))) __leave; + bEmoted = strcmp(type, "EMOTED") == 0; + if (strcmp(type, "MULTI_SUBSCRIBED") == 0) isGroupChat = TRUE; + + // Group chat handling + if (isGroupChat && strcmp(type, "TEXT") && strcmp(type, "SAID") && strcmp(type, "UNKNOWN") && !bEmoted) { + if (bUseGroupChat) { + BOOL bAddedMembers = FALSE; + + if (!strcmp(type, "SAWMEMBERS") || !strcmp(type, "CREATEDCHATWITH")) + { + // We have a new Groupchat + LOG(("FetchMessageThread CHAT SAWMEMBERS")); + if (!hChat) ChatStart(chat, FALSE); + __leave; + } + if (!strcmp(type, "KICKED")) + { + GCDEST gcd = {0}; + GCEVENT gce = {0}; + CONTACTINFO ci = {0}; + + if (!hChat) __leave; + gcd.pszModule = SKYPE_PROTONAME; + gcd.ptszID = make_nonutf_tchar_string((const unsigned char*)chat); + gcd.iType = GC_EVENT_KICK; + gce.cbSize = sizeof(GCEVENT); + gce.pDest = &gcd; + gce.dwFlags = GCEF_ADDTOLOG | GC_TCHAR; + gce.time = timestamp; + + if (users = SkypeGetErr(cmdMessage, args.msgnum, "USERS")) { + + ci.hContact = find_contact(users); + gce.ptszUID = make_nonutf_tchar_string((const unsigned char*)users); + if (who = SkypeGetErr(cmdMessage, args.msgnum, szPartnerHandle)) { + gce.ptszStatus = make_nonutf_tchar_string((const unsigned char*)who); + ci.cbSize = sizeof(ci); + ci.szProto = SKYPE_PROTONAME; + ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; + if (ci.hContact && !CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci)) gce.ptszNick = ci.pszVal; + else gce.ptszNick = gce.ptszUID; + + CallService(MS_GC_EVENT, 0, (LPARAM)&gce); + RemChatContact(GetChat(gcd.ptszID), gce.ptszUID); + free_nonutf_tchar_string((void*)gce.ptszStatus); + if (ci.pszVal) mir_free(ci.pszVal); + } + free_nonutf_tchar_string((void*)gce.ptszUID); + } + free_nonutf_tchar_string((void*)gcd.ptszID); + __leave; + } + if (!strcmp(type, "SETROLE")) + { + GCDEST gcd = {0}; + GCEVENT gce = {0}; + CONTACTINFO ci = {0}; + gchat_contact *gcContact; + char *pszRole; + + // FROM_HANDLE - Wer hats gesetzt + // USERS - Wessen Rolle wurde gesetzt + // ROLE - Die neue Rolle + if (!hChat) __leave; + gcd.pszModule = SKYPE_PROTONAME; + gcd.ptszID = make_nonutf_tchar_string((const unsigned char*)chat); + gcd.iType = GC_EVENT_REMOVESTATUS; + gce.cbSize = sizeof(GCEVENT); + gce.pDest = &gcd; + gce.dwFlags = GCEF_ADDTOLOG | GC_TCHAR; + gce.time = timestamp; + + if (users = SkypeGetErr(cmdMessage, args.msgnum, "USERS")) { + gce.ptszUID = make_nonutf_tchar_string((const unsigned char*)users); + if (who = SkypeGetErr(cmdMessage, args.msgnum, szPartnerHandle)) { + + ci.cbSize = sizeof(ci); + ci.szProto = SKYPE_PROTONAME; + ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; + ci.hContact = find_contact(who); + if (ci.hContact && !CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci)) { + gce.ptszText = _tcsdup(ci.pszVal); + mir_free(ci.pszVal); + ci.pszVal = NULL; + } + else gce.ptszText = make_tchar_string((const unsigned char*)who); + + ci.hContact = find_contact(users); + if (ci.hContact && !CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci)) gce.ptszNick = ci.pszVal; + else gce.ptszNick = gce.ptszUID; + + if (gcContact = GetChatContact(GetChat(gcd.ptszID), gce.ptszUID)) + { + gce.ptszStatus = gcContact->szRole; + CallService(MS_GC_EVENT, 0, (LPARAM)&gce); + } + if (pszRole = SkypeGetErr(cmdMessage, args.msgnum, "ROLE")) { + gce.ptszStatus = make_nonutf_tchar_string((const unsigned char*)pszRole); + gcd.iType = GC_EVENT_ADDSTATUS; + CallService(MS_GC_EVENT, 0, (LPARAM)&gce); + free_nonutf_tchar_string((void*)gce.ptszStatus); + free(pszRole); + } + free((void*)gce.ptszText); + if (ci.pszVal) mir_free(ci.pszVal); + } + free_nonutf_tchar_string((void*)gce.ptszUID); + } + free_nonutf_tchar_string((void*)gcd.ptszID); + __leave; + } + if (!strcmp(type, "SETTOPIC")) + { + GCDEST gcd = {0}; + GCEVENT gce = {0}; + CONTACTINFO ci = {0}; + + LOG(("FetchMessageThread CHAT SETTOPIC")); + gcd.pszModule = SKYPE_PROTONAME; + gcd.ptszID = make_nonutf_tchar_string((const unsigned char*)chat); + gcd.iType = GC_EVENT_TOPIC; + gce.cbSize = sizeof(GCEVENT); + gce.pDest = &gcd; + gce.dwFlags = GCEF_ADDTOLOG | GC_TCHAR; + gce.time = timestamp; + if (who = SkypeGetErr(cmdMessage, args.msgnum, szPartnerHandle)) { + + ci.hContact = find_contact(who); + gce.ptszUID = make_nonutf_tchar_string((const unsigned char*)who); + ci.cbSize = sizeof(ci); + ci.szProto = SKYPE_PROTONAME; + ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; + if (ci.hContact && !CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci)) gce.ptszNick = ci.pszVal; + else gce.ptszNick = gce.ptszUID; + + if (ptr = SkypeGetErr(cmdMessage, args.msgnum, "BODY")) { + gce.ptszText = make_tchar_string((const unsigned char*)ptr); + CallService(MS_GC_EVENT, 0, (LPARAM)&gce); + free((void*)gce.ptszText); + free(ptr); + } + free_nonutf_tchar_string((void*)gce.ptszUID); + if (ci.pszVal) mir_free(ci.pszVal); + } + free_nonutf_tchar_string((void*)gcd.ptszID); + if (!args.bDontMarkSeen) + { + MsgList_Add(pre.lParam, INVALID_HANDLE_VALUE); + SkypeSend("SET %s %s SEEN", cmdMessage, args.msgnum); + } + __leave; + } + if (!strcmp(type, "LEFT") || (bAddedMembers = strcmp(type, "ADDEDMEMBERS") == 0)) + { + GCDEST gcd = {0}; + GCEVENT gce = {0}; + CONTACTINFO ci = {0}; + char *pszInvited = Translate("invited"); + + LOG(("FetchMessageThread CHAT LEFT or ADDEDMEMBERS")); + if (bAddedMembers) { + gcd.pszModule = SKYPE_PROTONAME; + gcd.ptszID = make_nonutf_tchar_string((const unsigned char*)chat); + gcd.iType = GC_EVENT_ACTION; + gce.cbSize = sizeof(GCEVENT); + gce.pDest = &gcd; + gce.dwFlags = GCEF_ADDTOLOG | GC_TCHAR; + gce.time = timestamp; + if (users = SkypeGetErr(cmdMessage, args.msgnum, "USERS")) { + // We assume that users buffer has enough room for "invited" string + memmove (users+strlen(pszInvited), users, strlen(users)+1); + memcpy (users, pszInvited, strlen(pszInvited)); + gce.ptszText = make_tchar_string((const unsigned char*)users); + if (who = SkypeGetErr(cmdMessage, args.msgnum, szPartnerHandle)) { + DBVARIANT dbv; + if (db_get_s(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv) == 0) { + gce.bIsMe = strcmp(who, dbv.pszVal) == 0; + db_free(&dbv); + } + gce.ptszUID = make_nonutf_tchar_string((const unsigned char*)who); + + ci.cbSize = sizeof(ci); + if (!gce.bIsMe) + ci.hContact = find_contact(who); + ci.szProto = SKYPE_PROTONAME; + ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; + if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci)) + gce.ptszNick = ci.pszVal; + else + gce.ptszNick = gce.ptszUID; + + CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce); + free_nonutf_tchar_string((void*)gce.ptszUID); + if (ci.pszVal) mir_free(ci.pszVal); + } + if (gce.ptszText) free((void*)gce.ptszText); + } + free_nonutf_tchar_string((void*)gcd.ptszID); + } + if (!args.QueryMsgDirection) SkypeSend("GET CHAT %s MEMBERS", chat); + __leave; + } + } + __leave; + } + + // Need to get the status? + if (args.getstatus) { + char *status; + + if (protocol < 4) InterlockedIncrement(&rcvwatchers); + status = SkypeGetID(cmdMessage, args.msgnum, "STATUS"); + if (protocol < 4) InterlockedDecrement(&rcvwatchers); + if (!status) __leave; + if (!strcmp(status, "SENT")) direction = DBEF_SENT; + free(status); + } + + // Who sent it? + if (!(who = SkypeGetErr(cmdMessage, args.msgnum, szPartnerHandle))) __leave; + + // Get contact handle + LOG(("FetchMessageThread Finding contact handle")); + db_get_s(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv); + if (dbv.pszVal && !strcmp(who, dbv.pszVal)) + { + char *pTok, *nextoken; + + // It's from me.. But to whom? + // CHATMESSAGE .. USERS doesn't return anything, so we have to query the CHAT-Object + if (!(ptr = SkypeGetErr("CHAT", chat, "ACTIVEMEMBERS"))) { + db_free(&dbv); + __leave; + } + + for (pTok = strtok_r(ptr, " ", &nextoken); pTok; pTok = strtok_r(NULL, " ", &nextoken)) { + if (strcmp(pTok, dbv.pszVal)) break; // Take the first dude in the list who is not me + } + + if (!pTok) { + free(ptr); + db_free(&dbv); + __leave; // We failed + } + free(who); + who = (char *)memmove(ptr, pTok, strlen(pTok) + 1); + direction = DBEF_SENT; + } + db_free(&dbv); + + if (!(hContact = find_contact(who))) { + // Permanent adding of user obsolete, we use the BUDDYSTATUS now (bug #0000005) + ResetEvent(hBuddyAdded); + SkypeSend("GET USER %s BUDDYSTATUS", who); + WaitForSingleObject(hBuddyAdded, INFINITE); + if (!(hContact = find_contact(who))) { + // Arrgh, the user has been deleted from contact list. + // In this case, we add him temp. to receive the msg at least. + hContact = add_contact(who, PALF_TEMPORARY); + } + } + // Text which was sent (on edited msg, BODY may already be in queue, check) + sprintf(szBuf, "GET %s %s BODY", cmdMessage, args.msgnum); + if (!args.pMsgEntry || !args.pMsgEntry->tEdited || !(ptr = SkypeRcv(szBuf + 4, 1000))) + { + if (SkypeSend(szBuf) == -1 || !(ptr = SkypeRcv(szBuf + 4, INFINITE))) + __leave; + } + if (strncmp(ptr, "ERROR", 5)) { + msgptr = ptr + strlen(szBuf + 4) + 1; + bHasPartList = strncmp(msgptr, "tEdited) { + // Mark the message as edited + if (!*msgptr && args.pMsgEntry->hEvent != INVALID_HANDLE_VALUE) { + // Empty message and edited -> Delete event + if ((int)(hContact = db_event_getContact(args.pMsgEntry->hEvent)) != -1) { + db_event_delete(hContact, args.pMsgEntry->hEvent); + free(ptr); + __leave; + } + } + else { + msgptr -= 9; + memcpy(msgptr, "[EDITED] ", 9); + } + } + if (bEmoted && !isGroupChat) { + CONTACTINFO ci = { 0 }; + int newlen; + char *pMsg, *pszUTFnick = NULL; + ci.cbSize = sizeof(ci); + ci.szProto = SKYPE_PROTONAME; + ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; + if (ci.hContact = hContact) { + CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci); + if (ci.pszVal) { +#ifdef _UNICODE + pszUTFnick = (char*)make_utf8_string(ci.pszVal); +#else + utf8_encode (ci.pszVal, &pszUTFnick); +#endif + mir_free(ci.pszVal); + } + } + newlen = strlen(msgptr) + (pszUTFnick ? strlen(pszUTFnick) : 0) + 9; + if (pMsg = (char *)malloc(newlen)) { + sprintf(pMsg, "** %s%s%s **", (pszUTFnick ? pszUTFnick : ""), (pszUTFnick ? " " : ""), (char*)msgptr); + free(ptr); + ptr = msgptr = pMsg; + } + if (pszUTFnick) free(pszUTFnick); + } + + if (mirandaVersion >= 0x070000 && // 0.7.0+ supports PREF_UTF flag, no need to decode UTF8 + !isGroupChat) { // I guess Groupchat doesn't support UTF8? + msg = ptr; + pre.flags |= PREF_UTF; + } + else { // Older version has to decode either UTF8->ANSI or UTF8->UNICODE + // This could be replaced by mir_getUTFI - functions for Miranda 0.5+ builds, but we stay + // 0.4 compatible for backwards compatibility. Unfortunately this requires us to link with utf8.c +#ifdef _UNICODE + int wcLen; +#endif + + if (utf8_decode(msgptr, &msg) == -1) { + free(ptr); + __leave; + } +#ifdef _UNICODE + msglen = (int)strlen(msg) + 1; + msgptr = (char*)make_unicode_string((const unsigned char*)msgptr); + wcLen = (int)(_tcslen((TCHAR*)msgptr) + 1)*sizeof(TCHAR); + msg = (char*)realloc(msg, msglen + wcLen); + memcpy(msg + msglen, msgptr, wcLen); + free(msgptr); + pre.flags |= PREF_UNICODE; +#endif + msgptr = msg; + free(ptr); + } + msglen = (int)strlen(msgptr) + 1; + } + else { + free(ptr); + __leave; + } + // skype sends some xml statics after a call has finished. Check if thats the case and suppress it if necessary... + if ((db_get_b(NULL, SKYPE_PROTONAME, "SuppressCallSummaryMessage", 1) && + bHasPartList) || msgptr[0] == 0) __leave; + + if (isGroupChat && bUseGroupChat) { + + GCDEST gcd = { 0 }; + GCEVENT gce = { sizeof(gce), &gcd }; + DBVARIANT dbv = { 0 }; + CONTACTINFO ci = { 0 }; + + LOG(("FetchMessageThread This is a group chat message")); + if (!hChat) ChatStart(chat, FALSE); + gcd.pszModule = SKYPE_PROTONAME; + gcd.ptszID = make_nonutf_tchar_string((const unsigned char*)chat); + gcd.iType = bEmoted?GC_EVENT_ACTION:GC_EVENT_MESSAGE; + if ((gce.bIsMe = (direction&DBEF_SENT) ? TRUE : FALSE) && db_get_s(NULL, SKYPE_PROTONAME, SKYPE_NAME, &dbv) == 0) + { + free(who); + who = _strdup(dbv.pszVal); + db_free(&dbv); + } + gce.ptszUID = make_nonutf_tchar_string((const unsigned char*)who); + gce.ptszNick = gce.ptszUID; + + ci.cbSize = sizeof(ci); + ci.szProto = SKYPE_PROTONAME; + ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; + ci.hContact = !gce.bIsMe ? hContact : NULL; + if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci)) + gce.ptszNick = ci.pszVal; + gce.time = timestamp > 0 ? timestamp : (DWORD)SkypeTime(NULL); + gce.ptszText = (TCHAR*)(msgptr + msglen); + gce.dwFlags = GCEF_ADDTOLOG | GC_TCHAR; + CallService(MS_GC_EVENT, 0, (LPARAM)&gce); + MsgList_Add(pre.lParam, INVALID_HANDLE_VALUE); // Mark as groupchat + if (ci.pszVal) mir_free(ci.pszVal); + free_nonutf_tchar_string((void*)gce.ptszUID); + free_nonutf_tchar_string((void*)gcd.ptszID); + + // Yes, we have successfully read the msg + if (!args.bDontMarkSeen) + SkypeSend("SET %s %s SEEN", cmdMessage, args.msgnum); + __leave; + } + + if (args.QueryMsgDirection || (direction&DBEF_SENT)) { + // Check if the timestamp is valid + dbei.cbSize = sizeof(dbei); + dbei.cbBlob = 0; + if (hDbEvent = db_event_first(hContact)) { + db_event_get(hDbEvent, &dbei); + lwr = dbei.timestamp; + } + dbei.cbSize = sizeof(dbei); + dbei.cbBlob = 0; + dbei.timestamp = 0; + if (hDbEvent = db_event_last(hContact)) + db_event_get(hDbEvent, &dbei); + LOG(("FetchMessageThread timestamp %ld between %ld and %ld", timestamp, lwr, dbei.timestamp)); + if (timestamp < lwr || (direction&DBEF_SENT)) { + TYP_MSGLENTRY *pme; + + LOG(("FetchMessageThread Adding event")); + if (!(dbei.szModule = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0))) + dbei.szModule = SKYPE_PROTONAME; + dbei.cbBlob = msglen; + if (pre.flags & PREF_UNICODE) + dbei.cbBlob += sizeof(WCHAR)*((DWORD)wcslen((WCHAR*)&msgptr[dbei.cbBlob]) + 1); + dbei.pBlob = (PBYTE)msgptr; + dbei.timestamp = timestamp > 0 ? timestamp : (DWORD)SkypeTime(NULL); + dbei.flags = direction; + if (pre.flags & PREF_CREATEREAD) dbei.flags |= DBEF_READ; + if (pre.flags & PREF_UTF) dbei.flags |= DBEF_UTF; + dbei.eventType = EVENTTYPE_MESSAGE; + pme = MsgList_Add(pre.lParam, db_event_add(hContact, &dbei)); + + // We could call MS_PROTO_CHAINSEND if we want to have MetaContact adding the history for us, + // however we all know that CCSDATA doesn't contain timestamp-information which is + // really bad on importing history for example, as all messages would be added with current + // timestamp. This would cause unreliable jumbled timestamps in metacontact, so we better do this + // ourself. + if (db_mc_isSub(hContact)) { + DWORD dwMetaLink = db_get_dw(hContact, "MetaContacts", "MetaLink", MAXDWORD); + MCONTACT hMetaContact; + + if (dwMetaLink != MAXDWORD && (hMetaContact = GetMetaHandle(dwMetaLink))) { + dbei.szModule = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hMetaContact, 0); + pme->hMetaEvent = db_event_add(hMetaContact, &dbei); + } + } + + if (!args.QueryMsgDirection && !args.bDontMarkSeen) + SkypeSend("SET %s %s SEEN", cmdMessage, args.msgnum); + } + } + + + if (!(direction&DBEF_SENT) && (!args.QueryMsgDirection || (args.QueryMsgDirection && timestamp > dbei.timestamp))) { + LOG(("FetchMessageThread Normal message add...")); + // Normal message received, process it + ccs.szProtoService = PSR_MESSAGE; + ccs.hContact = hContact; + ccs.wParam = 0; + ccs.lParam = (LPARAM)⪯ + pre.flags |= direction; + if (isGroupChat && db_get_b(NULL, SKYPE_PROTONAME, "MarkGroupchatRead", 0)) + pre.flags |= PREF_CREATEREAD; + pre.timestamp = timestamp > 0 ? timestamp : (DWORD)SkypeTime(NULL); + pre.szMessage = msgptr; + CallServiceSync(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs); + + // Yes, we have successfully read the msg + if (!args.bDontMarkSeen) SkypeSend("SET %s %s SEEN", cmdMessage, args.msgnum); + } + } + __finally { + if (status) free(status); + if (msg) free(msg); + if (users) free(users); + if (chat) free(chat); + if (type) free(type); + if (who) free(who); + } + +} + +void FetchMessageThreadSync(fetchmsg_arg *pargs) { + // Secure this thread with a mutex. + // This is needed to ensure that we get called after an old msg in the queue has + // been added so that MsgList_FindEntry will find it. + WaitForSingleObject(FetchMessageEvent, 30000); // Wait max. 30 sec. for previous message fetch to complete + if ((pargs->pMsgEntry = MsgList_FindMessage(strtoul(pargs->msgnum, NULL, 10))) && !pargs->pMsgEntry->tEdited) { + // Better don't do this, as we set the msg as read and with this code, we would + // mark messages not opened by user as read which isn't that good + /* + if (pargs->bIsRead && pMsgEvent->hEvent != INVALID_HANDLE_VALUE) + { + MCONTACT hContact; + if ((int)(hContact = (MCONTACT)CallService (MS_DB_EVENT_GETCONTACT, (WPARAM)pMsgEntry->hEvent, 0)) != -1) + CallService (MS_DB_EVENT_MARKREAD, hContact, (LPARAM)hDBEvent); + } + */ + free(pargs); + } + else FetchMessageThread(pargs); + SetEvent(FetchMessageEvent); +} + +static int MsglCmpProc(const void *pstPElement, const void *pstPToFind) +{ + return strcmp((char*)((fetchmsg_arg*)pstPElement)->pMsgEntry, (char*)((fetchmsg_arg*)pstPToFind)->pMsgEntry); +} + +void MessageListProcessingThread(char *str) { + char *token, *nextoken, *chat = NULL; + fetchmsg_arg *args; + TYP_LIST *hListMsgs = List_Init(32); + int i, nCount; + + // Frst we need to sort the message timestamps + for ((token = strtok_r(str, ", ", &nextoken)); token; token = strtok_r(NULL, ", ", &nextoken)) { + if (args = (fetchmsg_arg*)calloc(1, sizeof(fetchmsg_arg) + sizeof(DWORD))) { + strncpy(args->msgnum, token, sizeof(args->msgnum)); + args->getstatus = TRUE; + args->bIsRead = TRUE; + args->bDontMarkSeen = TRUE; + args->QueryMsgDirection = TRUE; + args->pMsgEntry = (TYP_MSGLENTRY*)SkypeGet("CHATMESSAGE", token, "TIMESTAMP"); + if (!chat) chat = SkypeGet("CHATMESSAGE", token, "CHATNAME"); + if (args->pMsgEntry) List_InsertSort(hListMsgs, MsglCmpProc, args); + else free(args); + } + } + for (i = 0, nCount = List_Count(hListMsgs); i < nCount; i++) { + args = (fetchmsg_arg*)List_ElementAt(hListMsgs, i); + free(args->pMsgEntry); + args->pMsgEntry = NULL; + FetchMessageThreadSync(args); + } + if (chat) { + SkypeSend("GET CHAT %s MEMBERS", chat); + free(chat); + } + List_Exit(hListMsgs); + free(str); +} + +char *GetCallerHandle(char *szSkypeMsg) { + return SkypeGet(szSkypeMsg, "PARTNER_HANDLE", ""); +} + + +MCONTACT GetCallerContact(char *szSkypeMsg) +{ + char *szHandle; + MCONTACT hContact = NULL; + + if (!(szHandle = GetCallerHandle(szSkypeMsg))) return NULL; + if (!(hContact = find_contact(szHandle))) { + // If it's a SkypeOut-contact, PARTNER_HANDLE = SkypeOUT number + DBVARIANT dbv; + int tCompareResult; + + for (hContact = db_find_first(); hContact != NULL; hContact = db_find_next(hContact)) { + if (db_get_s(hContact, SKYPE_PROTONAME, "SkypeOutNr", &dbv)) continue; + tCompareResult = strcmp(dbv.pszVal, szHandle); + db_free(&dbv); + if (tCompareResult) continue; else break; + } + } + free(szHandle); + if (!hContact) { LOG(("GetCallerContact Not found!")); } + return hContact; +} + +MCONTACT GetMetaHandle(DWORD dwId) +{ + MCONTACT hContact; + + for (hContact = db_find_first(); hContact != NULL; hContact = db_find_next(hContact)) { + char *szProto = GetContactProto(hContact); + if (szProto != NULL && !strcmp(szProto, "MetaContacts") && + db_get_dw(hContact, "MetaContacts", "MetaID", MAXDWORD) == dwId) + return hContact; + } + return 0; +} + +LRESULT CALLBACK InCallPopUpProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_COMMAND: + break; + + case WM_CONTEXTMENU: + SendMessage(hwnd, UM_DESTROYPOPUP, 0, 0); + break; + case UM_FREEPLUGINDATA: + //Here we'd free our own data, if we had it. + return FALSE; + case UM_INITPOPUP: + break; + case UM_DESTROYPOPUP: + break; + case WM_NOTIFY: + default: + break; + } + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +void RingThread(char *szSkypeMsg) { + MCONTACT hContact; + DBEVENTINFO dbei = { 0 }; + DBVARIANT dbv; + char *ptr = NULL; + + // We use a single critical section for the RingThread- and the EndCallThread-functions + // so that only one function is running at the same time. This is needed, because when + // a initated and unaccepted call (which is still ringing) is hangup/canceled, skype + // sends two messages. First "CALL xxx STATUS RINGING" .. second "CALL xx STATUS CANCELED". + // This starts two independend threads (first: RingThread; second: EndCallThread). Now + // the two message are processed in reverse order sometimes. This causes the EndCallThread to + // delete the contacts "CallId" property and after that the RingThread saves the contacts + // "CallId" again. After that its not possible to call this contact, because the plugin + // thinks that there is already a call going and the hangup-function isnt working, because + // skype doesnt accept status-changes for finished calls. The CriticalSection syncronizes + // the threads and the messages are processed in correct order. + // Not the best solution, but it works. + EnterCriticalSection(&RingAndEndcallMutex); + + LOG(("RingThread started.")); + if (protocol >= 5) SkypeSend("MINIMIZE"); + if (hContact = GetCallerContact(szSkypeMsg)) { + // Make sure that an answering thread is not already in progress so that we don't get + // the 'Incoming call' event twice + if (!db_get_s(hContact, SKYPE_PROTONAME, "CallId", &dbv)) { + db_free(&dbv); + LOG(("RingThread terminated.")); + goto l_exitRT; + } + db_set_s(hContact, SKYPE_PROTONAME, "CallId", szSkypeMsg); + } + + if (!(ptr = SkypeGet(szSkypeMsg, "TYPE", ""))) { + LOG(("RingThread terminated.")); + goto l_exitRT;; + } + + if (!strncmp(ptr, "INCOMING", 8)) { + if (!hContact) { + char *szHandle; + + if (szHandle = GetCallerHandle(szSkypeMsg)) { + if (!(hContact = add_contact(szHandle, PALF_TEMPORARY))) { + free(szHandle); + goto l_exitRT; + } + db_unset(hContact, "CList", "Hidden"); + db_set_w(hContact, SKYPE_PROTONAME, "Status", (WORD)SkypeStatusToMiranda("SKYPEOUT")); + db_set_s(hContact, SKYPE_PROTONAME, "SkypeOutNr", szHandle); + free(szHandle); + } + else goto l_exitRT; + } + } + + if (HasVoiceService()) { + // Voice service will handle it + goto l_exitRT; + } + + dbei.cbSize = sizeof(dbei); + dbei.eventType = EVENTTYPE_CALL; + dbei.szModule = SKYPE_PROTONAME; + dbei.timestamp = (DWORD)SkypeTime(NULL); + dbei.pBlob = (unsigned char*)Translate("Phone call"); + dbei.cbBlob = strlen((const char*)dbei.pBlob) + 1; + if (!strncmp(ptr, "INCOMING", 8)) + { + CLISTEVENT cle = { 0 }; + char toolTip[256]; + + if (PopupServiceExists) + { + BOOL showPopup, popupWindowColor; + unsigned int popupBackColor, popupTextColor; + int popupTimeSec; + POPUPDATAT InCallPopup; + TCHAR * lpzContactName = (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR); + + popupTimeSec = db_get_dw(NULL, SKYPE_PROTONAME, "popupTimeSec", 4); + popupTextColor = db_get_dw(NULL, SKYPE_PROTONAME, "popupTextColor", GetSysColor(COLOR_WINDOWTEXT)); + popupBackColor = db_get_dw(NULL, SKYPE_PROTONAME, "popupBackColor", GetSysColor(COLOR_BTNFACE)); + popupWindowColor = (0 != db_get_b(NULL, SKYPE_PROTONAME, "popupWindowColor", TRUE)); + showPopup = (0 != db_get_b(NULL, SKYPE_PROTONAME, "showPopup", TRUE)); + + InCallPopup.lchContact = hContact; + InCallPopup.lchIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_CALL)); + InCallPopup.colorBack = !popupWindowColor ? popupBackColor : GetSysColor(COLOR_BTNFACE); + InCallPopup.colorText = !popupWindowColor ? popupTextColor : GetSysColor(COLOR_WINDOWTEXT); + InCallPopup.iSeconds = popupTimeSec; + InCallPopup.PluginWindowProc = (WNDPROC)InCallPopUpProc; + InCallPopup.PluginData = (void *)1; + + lstrcpy(InCallPopup.lptzText, TranslateT("Incoming Skype Call")); + + lstrcpy(InCallPopup.lptzContactName, lpzContactName); + + if (showPopup) + CallService(MS_POPUP_ADDPOPUPT, (WPARAM)&InCallPopup, 0); + + } + cle.cbSize = sizeof(cle); + cle.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_CALL)); + cle.pszService = SKYPE_ANSWERCALL; + dbei.flags = DBEF_READ; + cle.hContact = hContact; + cle.hDbEvent = db_event_add(hContact, &dbei); + _snprintf(toolTip, sizeof(toolTip), Translate("Incoming call from %s"), (char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0)); + cle.pszTooltip = toolTip; + CallServiceSync(MS_CLIST_ADDEVENT, 0, (LPARAM)&cle); + } + else + { + dbei.flags = DBEF_SENT; + db_event_add(hContact, &dbei); + } + +l_exitRT: + if (ptr) free(ptr); + free(szSkypeMsg); + LeaveCriticalSection(&RingAndEndcallMutex); +} + +void EndCallThread(char *szSkypeMsg) { + MCONTACT hContact = NULL; + HANDLE hDbEvent; + DBEVENTINFO dbei = { 0 }; + DBVARIANT dbv; + int tCompareResult; + + // We use a single critical section for the RingThread- and the EndCallThread-functions + // so that only one function is running at the same time. This is needed, because when + // a initated and unaccepted call (which is still ringing) is hangup/canceled, skype + // sends two messages. First "CALL xxx STATUS RINGING" .. second "CALL xx STATUS CANCELED". + // This starts two independend threads (first: RingThread; second: EndCallThread). Now + // the two message are processed in reverse order sometimes. This causes the EndCallThread to + // delete the contacts "CallId" property and after that the RingThread saves the contacts + // "CallId" again. After that its not possible to call this contact, because the plugin + // thinks that there is already a call going and the hangup-function isnt working, because + // skype doesnt accept status-changes for finished calls. The CriticalSection syncronizes + // the threads and the messages are processed in correct order. + // Not the best solution, but it works. + EnterCriticalSection(&RingAndEndcallMutex); + + LOG(("EndCallThread started.")); + if (szSkypeMsg) { + for (hContact = db_find_first(); hContact != NULL; hContact = db_find_next(hContact)) { + if (db_get_s(hContact, SKYPE_PROTONAME, "CallId", &dbv)) continue; + tCompareResult = strcmp(dbv.pszVal, szSkypeMsg); + db_free(&dbv); + if (tCompareResult) continue; else break; + } + } + if (hContact) + { + db_unset(hContact, SKYPE_PROTONAME, "CallId"); + + if (!HasVoiceService()) { + dbei.cbSize = sizeof(dbei); + hDbEvent = db_event_firstUnread(hContact); + while (hDbEvent) { + dbei.cbBlob = 0; + db_event_get(hDbEvent, &dbei); + if (!(dbei.flags&(DBEF_SENT | DBEF_READ)) && dbei.eventType == EVENTTYPE_CALL) { + db_event_markRead(hContact, hDbEvent); + CallService(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)hDbEvent); + } + if (dbei.pBlob) free(dbei.pBlob); + hDbEvent = db_event_next(hContact, hDbEvent); + } + } + + if (!db_get_s(hContact, SKYPE_PROTONAME, "SkypeOutNr", &dbv)) { + db_free(&dbv); + if (!strcmp((char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0), SKYPE_PROTONAME) && + db_get_b(hContact, "CList", "NotOnList", 0) + ) + CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0); + } + } + free(szSkypeMsg); + LeaveCriticalSection(&RingAndEndcallMutex); +} + +void HoldCallThread(char *szSkypeMsg) { + MCONTACT hContact; + + LOG(("HoldCallThread started")); + if (!szSkypeMsg) { + LOG(("HoldCallThread terminated.")); + return; + } + if (hContact = GetCallerContact(szSkypeMsg)) { + db_set_b(hContact, SKYPE_PROTONAME, "OnHold", 1); + } + free(szSkypeMsg); + LOG(("HoldCallThread terminated gracefully")); +} + +void ResumeCallThread(char *szSkypeMsg) { + MCONTACT hContact; + + LOG(("ResumeCallThread started")); + if (!szSkypeMsg) { + LOG(("ResumeCallThread terminated.")); + return; + } + if (hContact = GetCallerContact(szSkypeMsg)) { + db_unset(hContact, SKYPE_PROTONAME, "OnHold"); + } + free(szSkypeMsg); + LOG(("ResumeCallThread terminated gracefully.")); +} + +int SetUserStatus(void) { + if (RequestedStatus && AttachStatus != -1) { + if (SkypeSend("SET USERSTATUS %s", RequestedStatus) == -1) return 1; + } + return 0; +} + +void LaunchSkypeAndSetStatusThread(void *newStatus) { + + /* if (!db_get_b(NULL, SKYPE_PROTONAME, "UnloadOnOffline", 0)) { + logoff_contacts(); + return 1; + } + */ + int oldStatus = SkypeStatus; + static BOOL bLaunching = FALSE; + + UNREFERENCED_PARAMETER(newStatus); + + if (bLaunching) return; + bLaunching = TRUE; + LOG(("LaunchSkypeAndSetStatusThread started.")); + InterlockedExchange((long *)&SkypeStatus, (int)ID_STATUS_CONNECTING); + ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, SkypeStatus); + + if (ConnectToSkypeAPI(skype_path, 1) != -1) { + pthread_create((pThreadFunc)SkypeSystemInit, NULL); + //InterlockedExchange((long *)&SkypeStatus, (int)newStatus); + //ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, SkypeStatus); + SetUserStatus(); + } + + LOG(("LaunchSkypeAndSetStatusThread terminated gracefully.")); + bLaunching = FALSE; +} + +LONG APIENTRY WndProc(HWND hWndDlg, UINT message, UINT wParam, LONG lParam) +{ + PCOPYDATASTRUCT CopyData; + char *ptr, *szSkypeMsg = NULL, *nick, *buf; + static char *onlinestatus = NULL; + static BOOL RestoreUserStatus = FALSE; + int sstat, oldstatus, flag; + MCONTACT hContact; + fetchmsg_arg *args; + static int iReentranceCnt = 0; + + iReentranceCnt++; + switch (message) + { + case WM_COPYDATA: + LOG(("WM_COPYDATA start")); + if (hSkypeWnd == (HWND)wParam) { + char *pData; + CopyData = (PCOPYDATASTRUCT)lParam; + pData = (char*)CopyData->lpData; + while (*pData == ' ') pData++; + szSkypeMsg = _strdup((char*)pData); + ReplyMessage(1); + LOG(("< %s", szSkypeMsg)); + + if (!strncmp(szSkypeMsg, "CONNSTATUS", 10)) { + if (!strncmp(szSkypeMsg + 11, "LOGGEDOUT", 9)) { + SkypeInitialized = FALSE; + ResetEvent(SkypeReady); + AttachStatus = -1; + sstat = ID_STATUS_OFFLINE; + if (g_hWnd) KillTimer(g_hWnd, 1); + logoff_contacts(TRUE); + } + else + sstat = SkypeStatusToMiranda(szSkypeMsg + 11); + + if (sstat) { + oldstatus = SkypeStatus; + InterlockedExchange((long*)&SkypeStatus, sstat); + ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldstatus, SkypeStatus); + if (sstat != ID_STATUS_OFFLINE) { + if (sstat != ID_STATUS_CONNECTING && (oldstatus == ID_STATUS_OFFLINE || oldstatus == ID_STATUS_CONNECTING)) { + + SkypeInitialized = FALSE; + pthread_create((pThreadFunc)SkypeSystemInit, NULL); + } + if (db_get_b(NULL, SKYPE_PROTONAME, "KeepState", 0)) RestoreUserStatus = TRUE; + } + + // if (SkypeStatus==ID_STATUS_ONLINE) SkypeSend("SEARCH MISSEDMESSAGES"); + } + // break; + } + if (!strncmp(szSkypeMsg, "USERSTATUS", 10)) { + // if ((sstat=SkypeStatusToMiranda(szSkypeMsg+11)) && SkypeStatus!=ID_STATUS_CONNECTING) { + if ((sstat = SkypeStatusToMiranda(szSkypeMsg + 11))) { + if (RestoreUserStatus && RequestedStatus) { + RestoreUserStatus = FALSE; + SkypeSend("SET USERSTATUS %s", RequestedStatus); + } + oldstatus = SkypeStatus; + InterlockedExchange((long*)&SkypeStatus, sstat); + ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldstatus, sstat); +#ifdef SKYPEBUG_OFFLN + if ((oldstatus == ID_STATUS_OFFLINE || oldstatus == ID_STATUS_CONNECTING) && + SkypeStatus != ID_STATUS_CONNECTING && SkypeStatus != ID_STATUS_OFFLINE) + pthread_create((pThreadFunc)SearchFriendsThread, NULL); +#endif + } +#ifdef SKYPEBUG_OFFLN + SetEvent(GotUserstatus); +#endif + break; + } + if (!strncmp(szSkypeMsg, "APPLICATION libpurple_typing", 28)) { + char *nextoken, *p; + + if (p = strtok_r(szSkypeMsg + 29, " ", &nextoken)) + { + if (!strcmp(p, "STREAMS")) { + char *pStr; + + while (p = strtok_r(NULL, " ", &nextoken)) { + if (pStr = strchr(p, ':')) { + *pStr = 0; + if (hContact = find_contact(p)) { + *pStr = ':'; + db_set_s(hContact, SKYPE_PROTONAME, "Typing_Stream", p); + } + } + } + } + else if (!strcmp(p, "DATAGRAM")) { + if (p = strtok_r(NULL, " ", &nextoken)) { + char *pStr; + + if (pStr = strchr(p, ':')) { + *pStr = 0; + if (hContact = find_contact(p)) { + *pStr = ':'; + db_set_s(hContact, SKYPE_PROTONAME, "Typing_Stream", p); + + if (p = strtok_r(NULL, " ", &nextoken)) { + LPARAM lTyping = PROTOTYPE_CONTACTTYPING_OFF; + + if (!strcmp(p, "PURPLE_TYPING")) lTyping = PROTOTYPE_CONTACTTYPING_INFINITE; + CallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hContact, lTyping); + break; + } + } + } + } + } + } + } + if (!strncmp(szSkypeMsg, "USER ", 5)) { + char *nextoken; + + buf = _strdup(szSkypeMsg + 5); + nick = strtok_r(buf, " ", &nextoken); + ptr = strtok_r(NULL, " ", &nextoken); + + if (strcmp(ptr, "BUDDYSTATUS")) { + if (!strcmp(ptr, "RECEIVEDAUTHREQUEST")) { + pthread_create((pThreadFunc)SearchUsersWaitingMyAuthorization, NULL); + free(buf); + break; + } + + if (!(hContact = find_contact(nick)) && strcmp(ptr, "FULLNAME")) { + SkypeSend("GET USER %s BUDDYSTATUS", nick); + free(buf); + break; + } + + if (!strcmp(ptr, "ONLINESTATUS")) { + if (SkypeStatus != ID_STATUS_OFFLINE) + { + db_set_w(hContact, SKYPE_PROTONAME, "Status", (WORD)SkypeStatusToMiranda(ptr + 13)); + if ((WORD)SkypeStatusToMiranda(ptr + 13) != ID_STATUS_OFFLINE) + { + LOG(("WndProc Status is not offline so get user info")); + pthread_create(GetInfoThread, (void*)hContact); + } + } + } + + + /* We handle the following properties right here in the wndProc, in case that + * Skype protocol broadcasts them to us. + * + * However, we still let them be added to the Message queue im memory, as they + * may get consumed by GetInfoThread. + * This is necessary to have a proper error handling in case the property is + * not supported (i.e. imo2sproxy). + * + * If one of the property GETs returns an error, the error-message has to be + * removed from the message queue, as the error is the answer to the query. + * If we don't remove the ERRORs from the list, another consumer may see the ERROR + * as a reply to his query and process it. + * In case the SKYPE Protocol really broadcasts one of these messages without being + * requested by GetInfoThread (i.e. MOOD_TEXT), the garbage collector will take + * care of them and remove them after some time. + * This may not be the most efficient way, but ensures that we finally do proper + * error handling. + */ + if (!strcmp(ptr, "FULLNAME")) { + char *nm; + + if (nm = strtok_r(NULL, " ", &nextoken)) + { + db_set_utf(hContact, SKYPE_PROTONAME, "FirstName", nm); + if (!(nm = strtok_r(NULL, "", &nextoken))) {db_unset(hContact, SKYPE_PROTONAME, "LastName");} + else + db_set_utf(hContact, SKYPE_PROTONAME, "LastName", nm); + } + } + else + if (!strcmp(ptr, "BIRTHDAY")) { + unsigned int y, m, d; + if (sscanf(ptr + 9, "%04d%02d%02d", &y, &m, &d) == 3) { + db_set_w(hContact, SKYPE_PROTONAME, "BirthYear", (WORD)y); + db_set_b(hContact, SKYPE_PROTONAME, "BirthMonth", (BYTE)m); + db_set_b(hContact, SKYPE_PROTONAME, "BirthDay", (BYTE)d); + } + else { + db_unset(hContact, SKYPE_PROTONAME, "BirthYear"); + db_unset(hContact, SKYPE_PROTONAME, "BirthMonth"); + db_unset(hContact, SKYPE_PROTONAME, "BirthDay"); + } + } + else + if (!strcmp(ptr, "COUNTRY")) { + if (ptr[8]) { + struct CountryListEntry *countries; + int countryCount, i; + + CallService(MS_UTILS_GETCOUNTRYLIST, (WPARAM)&countryCount, (LPARAM)&countries); + for (i = 0; i < countryCount; i++) { + if (countries[i].id == 0 || countries[i].id == 0xFFFF) continue; + if (!_stricmp(countries[i].szName, ptr + 8)) + { + db_set_w(hContact, SKYPE_PROTONAME, "Country", (BYTE)countries[i].id); + break; + } + } + } + else db_unset(hContact, SKYPE_PROTONAME, "Country"); + } + else + if (!strcmp(ptr, "SEX")) { + if (ptr[4]) { + BYTE sex = 0; + if (!_stricmp(ptr + 4, "MALE")) sex = 0x4D; + if (!_stricmp(ptr + 4, "FEMALE")) sex = 0x46; + if (sex) db_set_b(hContact, SKYPE_PROTONAME, "Gender", sex); + } + else db_unset(hContact, SKYPE_PROTONAME, "Gender"); + } + else + if (!strcmp(ptr, "MOOD_TEXT")){ + + LOG(("WndProc MOOD_TEXT")); + db_set_utf(hContact, "CList", "StatusMsg", ptr + 10); + } + else + if (!strcmp(ptr, "TIMEZONE")){ + time_t temp; + struct tm tms; + int value = atoi(ptr + 9), tz; + + LOG(("WndProc: TIMEZONE %s", nick)); + + if (value && !db_get_b(NULL, SKYPE_PROTONAME, "IgnoreTimeZones", 0)) { + temp = SkypeTime(NULL); + tms = *localtime(&temp); + //memcpy(&tms,localtime(&temp), sizeof(tm)); + //tms = localtime(&temp) + tz = (value >= 86400) ? (256 - ((2 * (atoi(ptr + 9) - 86400)) / 3600)) : ((-2 * (atoi(ptr + 9) - 86400)) / 3600); + if (tms.tm_isdst == 1 && db_get_b(NULL, SKYPE_PROTONAME, "UseTimeZonePatch", 0)) + { + LOG(("WndProc: Using the TimeZonePatch")); + db_set_b(hContact, "UserInfo", "Timezone", (BYTE)(tz + 2)); + } + else + { + LOG(("WndProc: Not using the TimeZonePatch")); + db_set_b(hContact, "UserInfo", "Timezone", (BYTE)(tz + 0)); + } + } + else { + LOG(("WndProc: Deleting the TimeZone in UserInfo Section")); + db_unset(hContact, "UserInfo", "Timezone"); + } + } + else + if (!strcmp(ptr, "IS_VIDEO_CAPABLE")){ + if (!_stricmp(ptr + 17, "True")) + db_set_s(hContact, SKYPE_PROTONAME, "MirVer", "Skype 2.0"); + else + db_set_s(hContact, SKYPE_PROTONAME, "MirVer", "Skype"); + } + else + if (!strcmp(ptr, "RICH_MOOD_TEXT")) { + db_set_s(hContact, SKYPE_PROTONAME, "MirVer", "Skype 3.0"); + } + else + if (!strcmp(ptr, "DISPLAYNAME")) { + // Skype Bug? -> If nickname isn't customised in the Skype-App, this won't return anything :-( + if (ptr[12]) + db_set_utf(hContact, SKYPE_PROTONAME, "Nick", ptr + 12); + } + else // Other proerties that can be directly assigned to a DB-Value + { + int i; + char *pszProp; + + for (i = 0; i < sizeof(m_settings) / sizeof(m_settings[0]); i++) { + if (!strcmp(ptr, m_settings[i].SkypeSetting)) { + pszProp = ptr + strlen(m_settings[i].SkypeSetting) + 1; + if (*pszProp) + db_set_utf(hContact, SKYPE_PROTONAME, m_settings[i].MirandaSetting, pszProp); + else + db_unset(hContact, SKYPE_PROTONAME, m_settings[i].MirandaSetting); + } + } + } + } + else { // BUDDYSTATUS: + flag = 0; + switch (atoi(ptr + 12)) { + case 1: if (hContact = find_contact(nick)) CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0); break; + case 0: break; + case 2: flag = PALF_TEMPORARY; + case 3: add_contact(nick, flag); + SkypeSend("GET USER %s ONLINESTATUS", nick); + break; + } + free(buf); + if (!SetEvent(hBuddyAdded)) TellError(GetLastError()); + break; + } + free(buf); + } + if (!strncmp(szSkypeMsg, "CURRENTUSERHANDLE", 17)) { // My username + DBVARIANT dbv = { 0 }; + + if (db_get_s(NULL, SKYPE_PROTONAME, "LoginUserName", &dbv) || + !*dbv.pszVal || _stricmp(szSkypeMsg + 18, dbv.pszVal) == 0) + { + db_set_s(NULL, SKYPE_PROTONAME, SKYPE_NAME, szSkypeMsg + 18); + db_set_s(NULL, SKYPE_PROTONAME, "Nick", szSkypeMsg + 18); + pthread_create((pThreadFunc)GetDisplaynameThread, NULL); + } + if (dbv.pszVal) db_free(&dbv); + } + if (strstr(szSkypeMsg, "AUTOAWAY") || !strncmp(szSkypeMsg, "OPEN ", 5) || + (SkypeInitialized && !strncmp(szSkypeMsg, "PONG", 4)) || + !strncmp(szSkypeMsg, "MINIMIZE", 8)) + { + // Currently we do not process these messages + break; + } + if (!strncmp(szSkypeMsg, "CHAT ", 5)) { + // Currently we only process these notifications + if (db_get_b(NULL, SKYPE_PROTONAME, "UseGroupchat", 0) && + (ptr = strchr(szSkypeMsg, ' ')) && (ptr = strchr(++ptr, ' '))) + { + if (strncmp(ptr, " MEMBERS", 8) == 0) { + LOG(("WndProc AddMembers")); + pthread_create((pThreadFunc)AddMembersThread, _strdup(szSkypeMsg)); + } + else + if (strncmp(ptr, " FRIENDLYNAME ", 14) == 0) { + // Chat session name + MCONTACT hContact; + + *ptr = 0; + if (hContact = find_chatA(szSkypeMsg + 5)) + { + GCDEST gcd = {0}; + GCEVENT gce = {0}; + if (db_get_w(hContact, SKYPE_PROTONAME, "Status", ID_STATUS_OFFLINE) != + ID_STATUS_OFFLINE) + { + gcd.pszModule = SKYPE_PROTONAME; + gcd.ptszID = make_nonutf_tchar_string((const unsigned char*)szSkypeMsg+5); + gcd.iType = GC_EVENT_CHANGESESSIONAME; + gce.cbSize = sizeof(GCEVENT); + gce.pDest = &gcd; + gce.ptszText = make_tchar_string((const unsigned char*)ptr+14); + gce.dwFlags = GC_TCHAR; + if (gce.ptszText) { + CallService(MS_GC_EVENT, 0, (LPARAM)&gce); + db_set_ts(hContact, SKYPE_PROTONAME, "Nick", gce.ptszText); + free((void*)gce.ptszText); + } + free_nonutf_tchar_string((void*)gcd.ptszID); + } + } + *ptr = ' '; + } + else + if (strncmp(ptr, " CHATMESSAGES ", 14) == 0) { + pthread_create((pThreadFunc)MessageListProcessingThread, _strdup(ptr + 14)); + break; + } + } + } + if (!strncmp(szSkypeMsg, "CALL ", 5)) { + // incoming calls are already processed by Skype, so no need for us + // to do this. + // However we can give a user the possibility to hang up a call via Miranda's + // context menu + if (ptr = strstr(szSkypeMsg, " STATUS ")) { + ptr[0] = 0; ptr += 8; + if (!strcmp(ptr, "RINGING") || !strcmp(ptr, "ROUTING")) pthread_create((pThreadFunc)RingThread, _strdup(szSkypeMsg)); + if (!strcmp(ptr, "FAILED") || !strcmp(ptr, "FINISHED") || + !strcmp(ptr, "MISSED") || !strcmp(ptr, "REFUSED") || + !strcmp(ptr, "BUSY") || !strcmp(ptr, "CANCELLED")) + pthread_create((pThreadFunc)EndCallThread, _strdup(szSkypeMsg)); + if (!strcmp(ptr, "ONHOLD") || !strcmp(ptr, "LOCALHOLD") || + !strcmp(ptr, "REMOTEHOLD")) pthread_create((pThreadFunc)HoldCallThread, _strdup(szSkypeMsg)); + if (!strcmp(ptr, "INPROGRESS")) pthread_create((pThreadFunc)ResumeCallThread, _strdup(szSkypeMsg)); + break; + } + else if ((!strstr(szSkypeMsg, "PARTNER_HANDLE") && !strstr(szSkypeMsg, "FROM_HANDLE")) + && !strstr(szSkypeMsg, "TYPE")) break; + } + if (!strncmp(szSkypeMsg, "PRIVILEGE SKYPEOUT", 18)) { + if (!strncmp(szSkypeMsg + 19, "TRUE", 4)) { + if (!bSkypeOut) { + CLISTMENUITEM mi = { 0 }; + + bSkypeOut = TRUE; + mi.cbSize = sizeof(mi); + mi.position = -2000005000; + mi.flags = 0; + mi.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_CALLSKYPEOUT)); + mi.pszContactOwner = SKYPE_PROTONAME; + mi.pszName = Translate("Do a SkypeOut-call"); + mi.pszService = SKYPEOUT_CALL; + Menu_AddMainMenuItem(&mi); + } + + } + else { + bSkypeOut = FALSE; + if (httbButton) { + CallService(MS_TTB_REMOVEBUTTON, (WPARAM)httbButton, 0); + httbButton = 0; + } + } + break; + } + if (!strncmp(szSkypeMsg, "MESSAGES", 8) || !strncmp(szSkypeMsg, "CHATMESSAGES", 12)) { + if (strlen(szSkypeMsg) <= (UINT)(strchr(szSkypeMsg, ' ') - szSkypeMsg + 1)) + { + LOG(("%s %d %s %d", szSkypeMsg, (UINT)(strchr(szSkypeMsg, ' ') - szSkypeMsg + 1), + strchr(szSkypeMsg, ' '), strlen(szSkypeMsg))); + break; + } + LOG(("MessageListProcessingThread launched")); + pthread_create((pThreadFunc)MessageListProcessingThread, _strdup(strchr(szSkypeMsg, ' ') + 1)); + break; + } + if (!strncmp(szSkypeMsg, "MESSAGE", 7) || !strncmp(szSkypeMsg, "CHATMESSAGE", 11)) + { + char *pMsgNum; + TYP_MSGLENTRY *pEntry; + + if ((pMsgNum = strchr(szSkypeMsg, ' ')) && (ptr = strchr(++pMsgNum, ' '))) + { + BOOL bFetchMsg = FALSE; + + if (strncmp(ptr, " EDITED_TIMESTAMP", 17) == 0) { + ptr[0] = 0; + if (pEntry = MsgList_FindMessage(strtoul(pMsgNum, NULL, 10))) { + pEntry->tEdited = atol(ptr + 18); + } + bFetchMsg = TRUE; + } + else bFetchMsg = (strncmp(ptr, " STATUS RE", 10) == 0 && !rcvwatchers) || + (strncmp(ptr, " STATUS SENT", 12) == 0 && !sendwatchers); + + if (bFetchMsg) { + // If new message is available, fetch it + ptr[0] = 0; + if (!(args = (fetchmsg_arg *)calloc(1, sizeof(*args)))) break; + strncpy(args->msgnum, pMsgNum, sizeof(args->msgnum)); + args->getstatus = FALSE; + //args->bIsRead = strncmp(ptr+8, "READ", 4) == 0; + pthread_create((pThreadFunc)FetchMessageThreadSync, args); + break; + } + } + } + if (!strncmp(szSkypeMsg, "ERROR 68", 8)) { + LOG(("We got a sync problem :( -> SendMessage() will try to recover...")); + break; + } + if (!strncmp(szSkypeMsg, "PROTOCOL ", 9)) { + if ((protocol = (char)atoi(szSkypeMsg + 9)) >= 3) { + strcpy(cmdMessage, "CHATMESSAGE"); + strcpy(cmdPartner, "FROM"); + } + bProtocolSet = TRUE; + + if (protocol < 5 && !hMenuAddSkypeContact && + db_get_b(NULL, SKYPE_PROTONAME, "EnableMenu", 1)) + { + hMenuAddSkypeContact = add_mainmenu(); + } + } + LOG(("SkypeMsgAdd launched")); + SkypeMsgAdd(szSkypeMsg); + ReleaseSemaphore(SkypeMsgReceived, receivers, NULL); + } + break; + + case WM_TIMER: + if (iReentranceCnt > 1) break; + if (!bIsImoproxy) SkypeSend("PING"); + SkypeMsgCollectGarbage(MAX_MSG_AGE); + MsgList_CollectGarbage(); + if (receivers > 1) + { + LOG(("Watchdog WARNING: there are still %d receivers waiting for MSGs", receivers)); + } + break; + + case WM_CLOSE: + PostQuitMessage(0); + break; + case WM_DESTROY: + KillTimer(hWndDlg, 1); + break; + case WM_COPYDATALOCAL: + --iReentranceCnt; + return WndProc(hWndDlg, WM_COPYDATA, wParam, lParam); + + default: + if (message == ControlAPIAttach) { + // Skype responds with Attach to the discover-message + if ((HWND)wParam == hForbiddenSkypeWnd) { + ResetEvent(SkypeReady); + break; + } + AttachStatus = lParam; + if (lParam == SKYPECONTROLAPI_ATTACH_SUCCESS) { + LOG(("AttachStatus success, got hWnd %08X", (HWND)wParam)); + + if (hSkypeWnd && (HWND)wParam != hSkypeWnd && IsWindow(hSkypeWnd)) + hSkypeWndSecondary = (HWND)wParam; + else { + hSkypeWnd = (HWND)wParam; // Skype gave us the communication window handle + hSkypeWndSecondary = NULL; + } + } + if (AttachStatus != SKYPECONTROLAPI_ATTACH_API_AVAILABLE && + AttachStatus != SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE) + { + LOG(("Attaching: SkypeReady fired, Attachstatus is %d", AttachStatus)); + SetEvent(SkypeReady); + } + AttachStatus = lParam; + break; + } + --iReentranceCnt; + return DefWindowProc(hWndDlg, message, wParam, lParam); + } + LOG(("WM_COPYDATA exit (%08X)", message)); + if (szSkypeMsg) free(szSkypeMsg); + --iReentranceCnt; + return 1; +} + +void TellError(DWORD err) { + LPVOID lpMsgBuf; + + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); + MessageBox(NULL, (TCHAR*)lpMsgBuf, _T("GetLastError"), MB_OK | MB_ICONINFORMATION); + LocalFree(lpMsgBuf); + return; +} + + +// SERVICES // +INT_PTR SkypeSetStatus(WPARAM wParam, LPARAM lParam) +{ + int oldStatus, iRet; + BOOL UseCustomCommand, UnloadOnOffline; + + UNREFERENCED_PARAMETER(lParam); + + if (MirandaShuttingDown) return 0; + LOG(("SkypeSetStatus enter")); + UseCustomCommand = db_get_b(NULL, SKYPE_PROTONAME, "UseCustomCommand", 0); + UnloadOnOffline = db_get_b(NULL, SKYPE_PROTONAME, "UnloadOnOffline", 0); + + //if (!SkypeInitialized && !db_get_b(NULL, SKYPE_PROTONAME, "UnloadOnOffline", 0)) return 0; + + // Workaround for Skype status-bug + if ((int)wParam == ID_STATUS_OFFLINE) logoff_contacts(TRUE); + if (SkypeStatus == (int)wParam) return 0; + oldStatus = SkypeStatus; + + if ((int)wParam == ID_STATUS_CONNECTING) return 0; +#ifdef MAPDND + if ((int)wParam == ID_STATUS_OCCUPIED || (int)wParam == ID_STATUS_ONTHEPHONE) wParam = ID_STATUS_DND; + if ((int)wParam == ID_STATUS_OUTTOLUNCH) wParam = ID_STATUS_NA; +#endif +#ifdef MAPNA + if ((int)wParam==ID_STATUS_NA) wParam = ID_STATUS_AWAY; +#endif + + RequestedStatus = MirandaStatusToSkype((int)wParam); + + /* + if (SkypeStatus != ID_STATUS_OFFLINE) + { + InterlockedExchange((long*)&SkypeStatus, (int)wParam); + ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, SkypeStatus); + } + */ + + if ((int)wParam == ID_STATUS_OFFLINE && UnloadOnOffline) + { + if (UseCustomCommand) + { + DBVARIANT dbv; + if (!db_get_s(NULL, SKYPE_PROTONAME, "CommandLine", &dbv)) + { + CloseSkypeAPI(dbv.pszVal); + db_free(&dbv); + } + } + else + { + CloseSkypeAPI(skype_path); + } + + } + else if (AttachStatus == -1) + { + pthread_create(LaunchSkypeAndSetStatusThread, (void *)wParam); + return 0; + } + + iRet = SetUserStatus(); + LOG(("SkypeSetStatus exit")); + return iRet; +} + +int __stdcall SendBroadcast(MCONTACT hContact, int type, int result, HANDLE hProcess, LPARAM lParam) +{ + ACKDATA ack = {0}; + ack.cbSize = sizeof( ACKDATA ); + ack.szModule = SKYPE_PROTONAME; + ack.hContact = hContact; + ack.type = type; + ack.result = result; + ack.hProcess = hProcess; + ack.lParam = lParam; + return CallService(MS_PROTO_BROADCASTACK, 0, (LPARAM)&ack); +} + +static void __cdecl SkypeGetAwayMessageThread(void *hContact) +{ + DBVARIANT dbv; + if (!db_get_ts((MCONTACT)hContact, "CList", "StatusMsg", &dbv)) { + SendBroadcast((MCONTACT)hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, (LPARAM)dbv.ptszVal); + db_free(&dbv); + } + else SendBroadcast((MCONTACT)hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, (LPARAM)0); +} + +INT_PTR SkypeGetAwayMessage(WPARAM wParam, LPARAM lParam) +{ + CCSDATA* ccs = (CCSDATA*)lParam; + + UNREFERENCED_PARAMETER(wParam); + + pthread_create(SkypeGetAwayMessageThread, (void*)ccs->hContact); + return 1; +} + +#define POLYNOMIAL (0x488781ED) /* This is the CRC Poly */ +#define TOPBIT (1 << (WIDTH - 1)) /* MSB */ +#define WIDTH 32 + +static int GetFileHash(char* filename) +{ + HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + int remainder = 0, byte, bit; + char data[1024]; + DWORD dwRead; + + if (hFile == INVALID_HANDLE_VALUE) return 0; + + do + { + // Read file chunk + dwRead = 0; + ReadFile(hFile, data, 1024, &dwRead, NULL); + + /* loop through each byte of data */ + for (byte = 0; byte < (int)dwRead; ++byte) { + /* store the next byte into the remainder */ + remainder ^= (data[byte] << (WIDTH - 8)); + /* calculate for all 8 bits in the byte */ + for (bit = 8; bit > 0; --bit) { + /* check if MSB of remainder is a one */ + if (remainder & TOPBIT) + remainder = (remainder << 1) ^ POLYNOMIAL; + else + remainder = (remainder << 1); + } + } + } while (dwRead == 1024); + + CloseHandle(hFile); + + return remainder; +} + +static int _GetFileSize(char* filename) +{ + HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + int size; + + if (hFile == INVALID_HANDLE_VALUE) + return 0; + size = GetFileSize(hFile, NULL); + CloseHandle(hFile); + return size; +} + +/* RetrieveUserAvatar + * + * Purpose: Get a user avatar from skype itself + * Params : param=(void *)(HANDLE)hContact + */ +void RetrieveUserAvatar(void *param) +{ + MCONTACT hContact = (MCONTACT)param; + HANDLE file; + PROTO_AVATAR_INFORMATION AI = { 0 }; + ACKDATA ack = { 0 }; + DBVARIANT dbv; + char AvatarFile[MAX_PATH + 1], AvatarTmpFile[MAX_PATH + 10], *ptr, *pszTempFile; + + if (hContact == NULL) + return; + + // Mount default ack + ack.cbSize = sizeof(ACKDATA); + ack.szModule = SKYPE_PROTONAME; + ack.hContact = hContact; + ack.type = ACKTYPE_AVATAR; + ack.result = ACKRESULT_FAILED; + + AI.cbSize = sizeof(AI); + AI.hContact = hContact; + + // Get skype name + if (db_get_s(hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv) == 0) + { + if (dbv.pszVal) + { + // Get filename + FoldersGetCustomPath(hProtocolAvatarsFolder, AvatarFile, sizeof(AvatarFile), DefaultAvatarsFolder); + if (!*AvatarFile) strcpy(AvatarFile, DefaultAvatarsFolder); + mir_snprintf(AvatarTmpFile, sizeof(AvatarTmpFile), "AVATAR 1 %s\\%s_tmp.jpg", AvatarFile, dbv.pszVal); + pszTempFile = AvatarTmpFile + 9; + mir_snprintf(AvatarFile, sizeof(AvatarFile), "%s\\%s.jpg", AvatarFile, dbv.pszVal); + + // Just to be sure + DeleteFileA(pszTempFile); + file = CreateFileA(pszTempFile, 0, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (file != INVALID_HANDLE_VALUE) + { + CloseHandle(file); + if (ptr = SkypeGet("USER", dbv.pszVal, AvatarTmpFile)) + { + if (strncmp(ptr, "ERROR", 5) && + GetFileAttributesA(pszTempFile) != INVALID_FILE_ATTRIBUTES) + { + ack.result = ACKRESULT_SUCCESS; + + // Is no avatar image? + if (!db_get_b(NULL, SKYPE_PROTONAME, "ShowDefaultSkypeAvatar", 0) + && GetFileHash(pszTempFile) == 0x8d34e05d && _GetFileSize(pszTempFile) == 3751) + { + // Has no avatar + AI.format = PA_FORMAT_UNKNOWN; + ack.hProcess = (HANDLE)&AI; + DeleteFileA(AvatarFile); + } + else + { + // Got it + MoveFileExA(pszTempFile, AvatarFile, MOVEFILE_REPLACE_EXISTING); + AI.format = PA_FORMAT_JPEG; + strcpy(AI.filename, AvatarFile); + ack.hProcess = (HANDLE)&AI; + } + + } + free(ptr); + } + DeleteFileA(pszTempFile); + } + + } + db_free(&dbv); + } + CallService(MS_PROTO_BROADCASTACK, 0, (LPARAM)&ack); +} + + +/* SkypeGetAvatarInfo + * + * Purpose: Set user avatar in profile + * Params : wParam=0 + * lParam=(LPARAM)(const char*)filename + * Returns: 0 - Success + * -1 - Failure + */ +INT_PTR SkypeGetAvatarInfo(WPARAM wParam, LPARAM lParam) +{ + + DBVARIANT dbv; + PROTO_AVATAR_INFORMATION* AI = (PROTO_AVATAR_INFORMATION*)lParam; + if (AI->hContact == NULL) // User + { + if (!db_get_s(NULL, SKYPE_PROTONAME, "AvatarFile", &dbv)) + { + lstrcpynA(AI->filename, dbv.pszVal, sizeof(AI->filename)); + db_free(&dbv); + return GAIR_SUCCESS; + } + else + return GAIR_NOAVATAR; + } + else // Contact + { + DBVARIANT dbv; + char AvatarFile[MAX_PATH + 1]; + + if (protocol < 7 && !bIsImoproxy) + return GAIR_NOAVATAR; + + if (wParam & GAIF_FORCE) + { + // Request anyway + pthread_create(RetrieveUserAvatar, (void *)AI->hContact); + return GAIR_WAITFOR; + } + + if (db_get_s(AI->hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) + // No skype name ?? + return GAIR_NOAVATAR; + + if (dbv.pszVal == NULL) + { + // No skype name ?? + db_free(&dbv); + return GAIR_NOAVATAR; + } + + // Get filename + FoldersGetCustomPath(hProtocolAvatarsFolder, AvatarFile, sizeof(AvatarFile), DefaultAvatarsFolder); + mir_snprintf(AvatarFile, sizeof(AvatarFile), "%s\\%s.jpg", AvatarFile, dbv.pszVal); + db_free(&dbv); + + // Check if the file exists + if (GetFileAttributesA(AvatarFile) == INVALID_FILE_ATTRIBUTES) + return GAIR_NOAVATAR; + + // Return the avatar + AI->format = PA_FORMAT_JPEG; + strcpy(AI->filename, AvatarFile); + return GAIR_SUCCESS; + } +} + + +/* SkypeGetAvatarCaps + * + * Purpose: Query avatar caps for a protocol + * Params : wParam=One of AF_* + * lParam=Depends on wParam + * Returns: Depends on wParam + */ +INT_PTR SkypeGetAvatarCaps(WPARAM wParam, LPARAM lParam) +{ + switch (wParam) + { + case AF_MAXSIZE: + { + POINT *p = (POINT *)lParam; + if (p == NULL) + return -1; + + p->x = 96; + p->y = 96; + return 0; + } + case AF_PROPORTION: + { + return PIP_NONE; + } + case AF_FORMATSUPPORTED: + { + if (lParam == PA_FORMAT_PNG || lParam == PA_FORMAT_JPEG) + return TRUE; + else + return FALSE; + } + case AF_ENABLED: + { + return TRUE; + } + case AF_DONTNEEDDELAYS: + { + return FALSE; + } + } + return -1; +} + + +INT_PTR SkypeGetStatus(WPARAM wParam, LPARAM lParam) { + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + + return SkypeStatus; +} + +INT_PTR SkypeGetInfo(WPARAM wParam, LPARAM lParam) { + CCSDATA *ccs = (CCSDATA *)lParam; + + UNREFERENCED_PARAMETER(wParam); + + pthread_create(GetInfoThread, (void*)ccs->hContact); + return 0; +} + +INT_PTR SkypeAddToList(WPARAM wParam, LPARAM lParam) { + PROTOSEARCHRESULT *psr = (PROTOSEARCHRESULT*)lParam; + + LOG(("SkypeAddToList Adding API function called")); + if (psr->cbSize != sizeof(PROTOSEARCHRESULT) || !psr->nick) return 0; + LOG(("SkypeAddToList OK")); + return (INT_PTR)add_contact(_T2A(psr->nick), wParam); +} + +INT_PTR SkypeBasicSearch(WPARAM wParam, LPARAM lParam) { + UNREFERENCED_PARAMETER(wParam); + + LOG(("SkypeBasicSearch %s", (char *)lParam)); + if (!SkypeInitialized) return 0; + return (hSearchThread = pthread_create((pThreadFunc)BasicSearchThread, _strdup((char *)lParam))); +} + +void MessageSendWatchThread(void *a) { + char *str, *err; + + msgsendwt_arg *arg = (msgsendwt_arg*)a; + + LOG(("MessageSendWatchThread started.")); + + str = SkypeRcvMsg(arg->szId, SkypeTime(NULL) - 1, arg->hContact, db_get_dw(NULL, "SRMsg", "MessageTimeout", TIMEOUT_MSGSEND)); + InterlockedDecrement(&sendwatchers); + if (str) + { + if (!db_get_b(arg->hContact, SKYPE_PROTONAME, "ChatRoom", 0)) { + if (err = GetSkypeErrorMsg(str)) { + ProtoBroadcastAck(SKYPE_PROTONAME, arg->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)1, (LPARAM)Translate(err)); + free(err); + free(str); + free(arg); + LOG(("MessageSendWatchThread terminated.")); + return; + } + ProtoBroadcastAck(SKYPE_PROTONAME, arg->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)1, 0); + } + free(str); + LOG(("MessageSendWatchThread terminated gracefully.")); + } + free(arg); +} + +INT_PTR SkypeSendMessage(WPARAM wParam, LPARAM lParam) { + CCSDATA *ccs = (CCSDATA *)lParam; + DBVARIANT dbv; + BOOL sendok = TRUE; + char *msg = (char *)ccs->lParam, *utfmsg = NULL, *mymsgcmd = cmdMessage, szId[16] = { 0 }; + static DWORD dwMsgNum = 0; + BYTE bIsChatroom = 0 != db_get_b(ccs->hContact, SKYPE_PROTONAME, "ChatRoom", 0); + + UNREFERENCED_PARAMETER(wParam); + + if (bIsChatroom) + { + if (db_get_s(ccs->hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv)) + return 0; + mymsgcmd = "CHATMESSAGE"; + } + else + { + if (db_get_s(ccs->hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) + return 0; + mymsgcmd = "MESSAGE"; + } + + if (ccs->wParam & PREF_UTF) { + utfmsg = msg; + } + else if (ccs->wParam & PREF_UNICODE) { + utfmsg = (char*)make_utf8_string((WCHAR*)(msg + strlen(msg) + 1)); + } + else { + if (utf8_encode(msg, &utfmsg) == -1) utfmsg = NULL; + } + if (protocol >= 4) { + InterlockedIncrement((LONG*)&dwMsgNum); + sprintf(szId, "#M%d ", dwMsgNum++); + } + InterlockedIncrement(&sendwatchers); + if (!utfmsg || SkypeSend("%s%s %s %s", szId, mymsgcmd, dbv.pszVal, utfmsg)) sendok = FALSE; + if (utfmsg && utfmsg != msg) free(utfmsg); + db_free(&dbv); + + if (sendok) { + msgsendwt_arg *psendarg = (msgsendwt_arg*)calloc(1, sizeof(msgsendwt_arg)); + + if (psendarg) { + psendarg->hContact = ccs->hContact; + strcpy(psendarg->szId, szId); + pthread_create(MessageSendWatchThread, psendarg); + } + else InterlockedDecrement(&sendwatchers); + return 1; + } + else InterlockedDecrement(&sendwatchers); + if (!bIsChatroom) + ProtoBroadcastAck(SKYPE_PROTONAME, ccs->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)1, (LPARAM)Translate("Connection to Skype lost")); + return 0; +} + +INT_PTR SkypeRecvMessage(WPARAM wParam, LPARAM lParam) +{ + DBEVENTINFO dbei = { 0 }; + CCSDATA *ccs = (CCSDATA *)lParam; + PROTORECVEVENT *pre = (PROTORECVEVENT *)ccs->lParam; + + UNREFERENCED_PARAMETER(wParam); + + db_unset(ccs->hContact, "CList", "Hidden"); + dbei.cbSize = sizeof(dbei); + dbei.szModule = SKYPE_PROTONAME; + dbei.timestamp = pre->timestamp; + if (pre->flags & PREF_CREATEREAD) dbei.flags |= DBEF_READ; + if (pre->flags & PREF_UTF) dbei.flags |= DBEF_UTF; + dbei.eventType = EVENTTYPE_MESSAGE; + dbei.cbBlob = strlen(pre->szMessage) + 1; + if (pre->flags & PREF_UNICODE) + dbei.cbBlob += sizeof(wchar_t)*((DWORD)wcslen((wchar_t*)&pre->szMessage[dbei.cbBlob]) + 1); + dbei.pBlob = (PBYTE)pre->szMessage; + MsgList_Add(pre->lParam, db_event_add(ccs->hContact, &dbei)); + return 0; +} + +INT_PTR SkypeUserIsTyping(WPARAM wParam, LPARAM lParam) { + DBVARIANT dbv = { 0 }; + MCONTACT hContact = (MCONTACT)wParam; + + if (protocol < 5 && !bIsImoproxy) return 0; + if (db_get_s(hContact, SKYPE_PROTONAME, "Typing_Stream", &dbv)) { + if (db_get_s(hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv) == 0) { + char szCmd[256]; + _snprintf(szCmd, sizeof(szCmd), + "ALTER APPLICATION libpurple_typing CONNECT %s", dbv.pszVal); + SkypeSend(szCmd); + db_free(&dbv); + testfor(szCmd, 2000); + // TODO: We should somehow cache the typing notify result and send it + // after we got a connection, but in the meantime this notification won't + // get sent on first run + } + return 0; + } + + SkypeSend("ALTER APPLICATION libpurple_typing DATAGRAM %s %s", dbv.pszVal, + (lParam == PROTOTYPE_SELFTYPING_ON ? "PURPLE_TYPING" : "PURPLE_NOT_TYPING")); + db_free(&dbv); + return 0; +} + + +INT_PTR SkypeSendAuthRequest(WPARAM wParam, LPARAM lParam) { + CCSDATA* ccs = (CCSDATA*)lParam; + DBVARIANT dbv; + int retval; + + UNREFERENCED_PARAMETER(wParam); + + if (!ccs->lParam || db_get_s(ccs->hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) + return 1; + retval = SkypeSend("SET USER %s BUDDYSTATUS 2 %s", dbv.pszVal, (char *)ccs->lParam); + db_free(&dbv); + if (retval) return 1; else return 0; +} + +INT_PTR SkypeRecvAuth(WPARAM wParam, LPARAM lParam) { + DBEVENTINFO dbei = { 0 }; + CCSDATA* ccs = (CCSDATA*)lParam; + PROTORECVEVENT* pre = (PROTORECVEVENT*)ccs->lParam; + + UNREFERENCED_PARAMETER(wParam); + + db_unset(ccs->hContact, "CList", "Hidden"); + + dbei.cbSize = sizeof(dbei); + dbei.szModule = SKYPE_PROTONAME; + dbei.timestamp = pre->timestamp; + dbei.flags = ((pre->flags & PREF_CREATEREAD) ? DBEF_READ : 0); + dbei.eventType = EVENTTYPE_AUTHREQUEST; + dbei.cbBlob = pre->lParam; + dbei.pBlob = (PBYTE)pre->szMessage; + + db_event_add(NULL, &dbei); + return 0; +} + +char *__skypeauth(WPARAM wParam) { + DBEVENTINFO dbei = { 0 }; + + if (!SkypeInitialized) return NULL; + + dbei.cbSize = sizeof(dbei); + if ((dbei.cbBlob = db_event_getBlobSize((HANDLE)wParam) == -1 || + !(dbei.pBlob = (unsigned char*)malloc(dbei.cbBlob)))) + { + return NULL; + } + + if (db_event_get((HANDLE)wParam, &dbei) || + dbei.eventType != EVENTTYPE_AUTHREQUEST || + strcmp(dbei.szModule, SKYPE_PROTONAME)) + { + free(dbei.pBlob); + return NULL; + } + return (char *)dbei.pBlob; +} + +INT_PTR SkypeAuthAllow(WPARAM wParam, LPARAM lParam) { + char *pBlob; + + UNREFERENCED_PARAMETER(lParam); + + if (pBlob = __skypeauth(wParam)) + { + int retval = SkypeSend("SET USER %s ISAUTHORIZED TRUE", pBlob + sizeof(DWORD) + sizeof(HANDLE)); + free(pBlob); + if (!retval) return 0; + } + return 1; +} + +INT_PTR SkypeAuthDeny(WPARAM wParam, LPARAM lParam) { + char *pBlob; + + UNREFERENCED_PARAMETER(lParam); + + if (pBlob = __skypeauth(wParam)) + { + int retval = SkypeSend("SET USER %s ISAUTHORIZED FALSE", pBlob + sizeof(DWORD) + sizeof(HANDLE)); + free(pBlob); + if (!retval) return 0; + } + return 1; +} + + +INT_PTR SkypeAddToListByEvent(WPARAM wParam, LPARAM lParam) { + char *pBlob; + + UNREFERENCED_PARAMETER(lParam); + + if (pBlob = __skypeauth(wParam)) + { + MCONTACT hContact = add_contact(pBlob + sizeof(DWORD) + sizeof(HANDLE), LOWORD(wParam)); + free(pBlob); + if (hContact) return (int)hContact; + } + return 0; +} + +INT_PTR SkypeRegisterProxy(WPARAM wParam, LPARAM lParam) { + UNREFERENCED_PARAMETER(wParam); + + if (!lParam) { + free(pszProxyCallout); + pszProxyCallout = NULL; + } + pszProxyCallout = _strdup((char*)lParam); + bIsImoproxy = TRUE; + return 0; +} + + +void CleanupNicknames(char *dummy) { + MCONTACT hContact; + char *szProto; + DBVARIANT dbv, dbv2; + + UNREFERENCED_PARAMETER(dummy); + + LOG(("CleanupNicknames Cleaning up...")); + for (hContact = db_find_first(); hContact != NULL; hContact = db_find_next(hContact)) { + szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (szProto != NULL && !strcmp(szProto, SKYPE_PROTONAME) && + db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0) == 0) + { + if (db_get_s(hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) continue; + if (db_get_s(hContact, SKYPE_PROTONAME, "Nick", &dbv2)) { + db_free(&dbv); + continue; + } + db_unset(hContact, SKYPE_PROTONAME, "Nick"); + GetInfoThread((void*)hContact); + db_free(&dbv); + db_free(&dbv2); + } + } + OUTPUT(_T("Cleanup finished.")); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// EnterBitmapFileName - enters a bitmap filename + +int __stdcall EnterBitmapFileName(char* szDest) +{ + char szFilter[512]; + OPENFILENAMEA ofn = { 0 }; + *szDest = 0; + + CallService(MS_UTILS_GETBITMAPFILTERSTRINGS, sizeof szFilter, (LPARAM)szFilter); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.lpstrFilter = szFilter; + ofn.lpstrFile = szDest; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; + ofn.nMaxFile = MAX_PATH; + ofn.nMaxFileTitle = MAX_PATH; + ofn.lpstrDefExt = "bmp"; + if (!GetOpenFileNameA(&ofn)) + return 1; + + return ERROR_SUCCESS; +} + +int MirandaExit(WPARAM wParam, LPARAM lParam) { + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + + MirandaShuttingDown = TRUE; + return 0; +} + +int OkToExit(WPARAM wParam, LPARAM lParam) { + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + + // logoff_contacts(); + MirandaShuttingDown = TRUE; + + // Trigger all semaphores and events just to be sure that there is no deadlock + ReleaseSemaphore(SkypeMsgReceived, receivers, NULL); + SetEvent(SkypeReady); + SetEvent(MessagePumpReady); +#ifdef SKYPEBUG_OFFLN + SetEvent(GotUserstatus); +#endif + SetEvent(hBuddyAdded); + + SkypeFlush(); + PostMessage(g_hWnd, WM_CLOSE, 0, 0); + return 0; +} + + +struct PLUGINDI { + char **szSettings; + int dwCount; +}; + +// Taken from pluginopts.c and modified +int EnumOldPluginName(const char *szSetting, LPARAM lParam) +{ + struct PLUGINDI *pdi = (struct PLUGINDI*)lParam; + if (pdi && lParam) { + pdi->szSettings = (char**)realloc(pdi->szSettings, (pdi->dwCount + 1)*sizeof(char*)); + pdi->szSettings[pdi->dwCount++] = _strdup(szSetting); + } + return 0; +} + +// Are there any Skype users on list? +// 1 --> Yes +// 0 --> No +int AnySkypeusers(void) +{ + MCONTACT hContact; + DBVARIANT dbv; + int tCompareResult; + + // already on list? + for (hContact = db_find_first(); + hContact != NULL; + hContact = db_find_next(hContact)) + { + // GETCONTACTBASEPROTO doesn't work on not loaded protocol, therefore get + // protocol from DB + if (db_get_s(hContact, "Protocol", "p", &dbv)) continue; + tCompareResult = !strcmp(dbv.pszVal, SKYPE_PROTONAME); + db_free(&dbv); + if (tCompareResult) return 1; + } + return 0; +} + + +/*void UpgradeName(char *OldName) +{ +DBCONTACTENUMSETTINGS cns; +DBCONTACTWRITESETTING cws; +DBVARIANT dbv; +MCONTACT hContact=NULL; +struct PLUGINDI pdi; + +LOG(("Updating old database settings if there are any...")); +cns.pfnEnumProc=EnumOldPluginName; +cns.lParam=(LPARAM)&pdi; +cns.szModule=OldName; +cns.ofsSettings=0; + +hContact = db_find_first(); + +for ( ;; ) { +memset(&pdi,0,sizeof(pdi)); +CallService(MS_DB_CONTACT_ENUMSETTINGS,hContact,(LPARAM)&cns); +// Upgrade Protocol settings to new string +if (pdi.szSettings) { +int i; + +LOG(("We're currently upgrading...")); +for (i=0;i 0 && !Miranda_Terminated()) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + UnregisterClass(WndClass.lpszClassName, hInst); + LOG(("Messagepump stopped.")); +} + +// DLL Stuff // + +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirVersion) +{ + mirandaVersion = mirVersion; + + return &pluginInfo; +} + +extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MUUID_SKYPE_CALL, MIID_LAST }; + +extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + UNREFERENCED_PARAMETER(fdwReason); + UNREFERENCED_PARAMETER(lpvReserved); + + hInst = hinstDLL; + return TRUE; +} + + +int PreShutdown(WPARAM wParam, LPARAM lParam) { + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + + PostThreadMessage(msgPumpThreadId, WM_QUIT, 0, 0); + return 0; +} + +extern "C" int __declspec(dllexport) Load() +{ + DWORD Buffsize; + HKEY MyKey; + BOOL SkypeInstalled; + BOOL UseCustomCommand; + WSADATA wsaData; + char path[MAX_PATH]; + + mir_getLP(&pluginInfo); + + // Used to enable Copy DLL hack in older Miranda versions for muliple accounts + GetModuleFileNameA( hInst, path, sizeof( path )); + _splitpath (path, NULL, NULL, SKYPE_PROTONAME, NULL); + CharUpperA( SKYPE_PROTONAME ); + + InitializeCriticalSection(&RingAndEndcallMutex); + InitializeCriticalSection(&QueryThreadMutex); + InitializeCriticalSection(&TimeMutex); + +#ifdef _DEBUG + init_debug(); +#endif + + LOG(("Load: Skype Plugin loading...")); + + // We need to upgrade SKYPE_PROTOCOL internal name to Skype if not already done + /* if (!db_get_b(NULL, SKYPE_PROTONAME, "UpgradeDone", 0)) + UpgradeName("SKYPE_PROTOCOL");*/ + + // Initialisation of Skype MsgQueue must be done because of Cleanup in end and + // Mutex is also initialized here. + LOG(("SkypeMsgInit initializing Skype MSG-queue")); + if (SkypeMsgInit() == -1) { + OUTPUT(_T("Memory allocation error on startup.")); + return 0; + } + + // On first run on new profile, ask user, if he wants to enable the plugin in + // this profile + // --> Fixing Issue #0000006 from bugtracker. + if (!db_get_b(NULL, SKYPE_PROTONAME, "FirstRun", 0)) { + db_set_b(NULL, SKYPE_PROTONAME, "FirstRun", 1); + if (AnySkypeusers() == 0) // First run, it seems :) + if (MessageBox(NULL, TranslateT("This seems to be the first time that you're running the Skype protocol plugin. Do you want to enable the protocol for this Miranda profile? If you chose NO, you can always enable it in the plugin options later."), _T("Welcome!"), MB_ICONQUESTION | MB_YESNO) == IDNO) { + char path[MAX_PATH], *filename; + GetModuleFileNameA(hInst, path, sizeof(path)); + if (filename = strrchr(path, '\\') + 1) + db_set_b(NULL, "PluginDisable", filename, 1); + return 0; + } + } + + + // Check if Skype is installed + SkypeInstalled = TRUE; + UseCustomCommand = (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "UseCustomCommand", 0); + UseSockets = (BOOL)db_get_b(NULL, SKYPE_PROTONAME, "UseSkype2Socket", 0); + + if (!UseSockets && !UseCustomCommand) + { + if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\Skype\\Phone"), 0, KEY_READ, &MyKey) != ERROR_SUCCESS) + { + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\Skype\\Phone"), 0, KEY_READ, &MyKey) != ERROR_SUCCESS) + { + SkypeInstalled = FALSE; + } + } + + Buffsize = sizeof(skype_path); + + if (SkypeInstalled == FALSE || RegQueryValueExA(MyKey, "SkypePath", NULL, NULL, (unsigned char *)skype_path, &Buffsize) != ERROR_SUCCESS) + { + //OUTPUT("Skype was not found installed :( \nMaybe you are using portable Skype."); + RegCloseKey(MyKey); + skype_path[0] = 0; + //return 0; + } + RegCloseKey(MyKey); + } + WSAStartup(MAKEWORD(2, 2), &wsaData); + + // Start Skype connection + if (!(ControlAPIAttach = RegisterWindowMessage(_T("SkypeControlAPIAttach"))) || !(ControlAPIDiscover = RegisterWindowMessage(_T("SkypeControlAPIDiscover")))) + { + OUTPUT(_T("Cannot register Window message.")); + return 0; + } + + SkypeMsgReceived = CreateSemaphore(NULL, 0, MAX_MSGS, NULL); + if (!(SkypeReady = CreateEvent(NULL, TRUE, FALSE, NULL)) || + !(MessagePumpReady = CreateEvent(NULL, FALSE, FALSE, NULL)) || +#ifdef SKYPEBUG_OFFLN + !(GotUserstatus = CreateEvent(NULL, TRUE, FALSE, NULL)) || +#endif + !(hBuddyAdded = CreateEvent(NULL, FALSE, FALSE, NULL)) || + !(FetchMessageEvent = CreateEvent(NULL, FALSE, TRUE, NULL))) { + OUTPUT(_T("Unable to create Mutex!")); + return 0; + } + + /* Register the module */ + PROTOCOLDESCRIPTOR pd = { 0 }; + pd.cbSize = PROTOCOLDESCRIPTOR_V3_SIZE; + pd.szName = SKYPE_PROTONAME; + pd.type = PROTOTYPE_PROTOCOL; + CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd); + + CreateServices(); + HookEvents(); + InitVSApi(); + MsgList_Init(); + + HookEvent(ME_SYSTEM_PRESHUTDOWN, PreShutdown); + + // Startup Message-pump + pthread_create((pThreadFunc)MsgPump, NULL); + WaitForSingleObject(MessagePumpReady, INFINITE); + return 0; +} + + + +extern "C" int __declspec(dllexport) Unload(void) +{ + BOOL UseCustomCommand = db_get_b(NULL, SKYPE_PROTONAME, "UseCustomCommand", 0); + BOOL Shutdown = db_get_b(NULL, SKYPE_PROTONAME, "Shutdown", 0); + + LOG(("Unload started")); + + if (Shutdown && ((skype_path && skype_path[0]) || UseCustomCommand)) { + + if (UseCustomCommand) + { + DBVARIANT dbv; + if (!db_get_s(NULL, SKYPE_PROTONAME, "CommandLine", &dbv)) + { + char szAbsolutePath[MAX_PATH]; + + TranslateMirandaRelativePathToAbsolute(dbv.pszVal, szAbsolutePath, FALSE); + _spawnl(_P_NOWAIT, szAbsolutePath, szAbsolutePath, "/SHUTDOWN", NULL); + LOG(("Unload Sent /shutdown to %s", szAbsolutePath)); + db_free(&dbv); + } + } + else + { + _spawnl(_P_NOWAIT, skype_path, skype_path, "/SHUTDOWN", NULL); + LOG(("Unload Sent /shutdown to %s", skype_path)); + } + + } + SkypeMsgCleanup(); + //WSACleanup(); + FreeVSApi(); + UnhookEvents(); + UnhookEvent(hChatEvent); + UnhookEvent(hChatMenu); + UnhookEvent(hEvInitChat); + DestroyHookableEvent(hInitChat); + GCExit(); + MsgList_Exit(); + + CloseHandle(SkypeReady); + CloseHandle(SkypeMsgReceived); +#ifdef SKYPEBUG_OFFLN + CloseHandle(GotUserstatus); +#endif + CloseHandle(MessagePumpReady); + CloseHandle(hBuddyAdded); + CloseHandle(FetchMessageEvent); + + DeleteCriticalSection(&RingAndEndcallMutex); + DeleteCriticalSection(&QueryThreadMutex); + + SkypeRegisterProxy(0, 0); + LOG(("Unload: Shutdown complete")); +#ifdef _DEBUG + end_debug(); +#endif + DeleteCriticalSection(&TimeMutex); + return 0; +} + diff --git a/protocols/SkypeClassic/src/skype.h b/protocols/SkypeClassic/src/skype.h index e28be1051f..3772398ab9 100644 --- a/protocols/SkypeClassic/src/skype.h +++ b/protocols/SkypeClassic/src/skype.h @@ -44,11 +44,8 @@ #include #include #include -#ifdef IS_MIRANDAIM -#include -#else + #define MIRANDA_CUSTOM_LP -#endif #pragma warning (pop) diff --git a/protocols/SkypeClassic/src/skypeapi.c b/protocols/SkypeClassic/src/skypeapi.c deleted file mode 100644 index 0c76c33c34..0000000000 --- a/protocols/SkypeClassic/src/skypeapi.c +++ /dev/null @@ -1,1707 +0,0 @@ -/* - * SkypeAPI - All more or less important functions that deal with Skype - */ - -#include "skype.h" -#include "skypeapi.h" -#include "utf8.h" -#include "debug.h" -#include "contacts.h" -#include "skypeproxy.h" -#include "pthread.h" -#include "gchat.h" -#include "alogon.h" -#include "msgq.h" -#include -#pragma warning (push) -#pragma warning (disable: 4100) // unreferenced formal parameter -#include -#include -#pragma warning (push) -#include - -#pragma warning (disable: 4706) // assignment within conditional expression - -// Imported Globals -extern HWND hSkypeWnd, g_hWnd; -extern BOOL SkypeInitialized, UseSockets, MirandaShuttingDown, bIsImoproxy; -extern int SkypeStatus, receivers; -extern HANDLE SkypeReady, SkypeMsgReceived, httbButton; -extern UINT ControlAPIAttach, ControlAPIDiscover; -extern LONG AttachStatus; -extern HINSTANCE hInst; -extern PLUGININFOEX pluginInfo; -extern HANDLE hProtocolAvatarsFolder, hHookSkypeApiRcv; -extern char DefaultAvatarsFolder[MAX_PATH+1], *pszProxyCallout, protocol, g_szProtoName[]; - -// -> Skype Message Queue functions // - -static TYP_MSGQ SkypeMsgs, SkypeSendQueue; - -status_map status_codes[] = { - {ID_STATUS_AWAY, "AWAY"}, - {ID_STATUS_NA, "NA"}, - {ID_STATUS_DND, "DND"}, - {ID_STATUS_ONLINE, "ONLINE"}, - {ID_STATUS_FREECHAT, "SKYPEME"}, // Unfortunately Skype API tells us userstatus ONLINE, if we are free for chat - {ID_STATUS_OFFLINE, "OFFLINE"}, - {ID_STATUS_INVISIBLE, "INVISIBLE"}, - {ID_STATUS_CONNECTING, "CONNECTING"}, - {0, NULL} -}; - -//status_map - - -static CRITICAL_SECTION ConnectMutex; -static BOOL rcvThreadRunning=FALSE, isConnecting = FALSE; -static SOCKET ClientSocket=INVALID_SOCKET; -static HANDLE SkypeMsgToSend=NULL; - -static char *m_szSendBuf = NULL; -static DWORD m_iBufSize = 0; - - -static int _ConnectToSkypeAPI(char *path, BOOL bStart); - - -/* SkypeReceivedMessage - * - * Purpose: Hook to be called when a message is received, if some caller is - * using our internal I/O services. - * Params : wParam - Not used - * lParam - COPYDATASTRUCT like in WM_COPYDATA - * Returns: Result from SendMessage - */ -INT_PTR SkypeReceivedAPIMessage(WPARAM wParam, LPARAM lParam) { - return SendMessage(g_hWnd, WM_COPYDATALOCAL, (WPARAM)hSkypeWnd, lParam); -} - -/* - * Skype via Socket --> Skype2Socket connection - */ - -void rcvThread(char *dummy) { - unsigned int length; - char *buf; - COPYDATASTRUCT CopyData; - int rcv; - - if (!UseSockets) return; - rcvThreadRunning=TRUE; - for ( ;; ) { - if (ClientSocket==INVALID_SOCKET) { - rcvThreadRunning=FALSE; - return; - } - LOG(("rcvThread Receiving from socket..")); - if ((rcv=recv(ClientSocket, (char *)&length, sizeof(length), 0))==SOCKET_ERROR || rcv==0) { - rcvThreadRunning=FALSE; - if (rcv==SOCKET_ERROR) {LOG(("rcvThread Socket error"));} - else {LOG(("rcvThread lost connection, graceful shutdown"));} - return; - } - LOG(("rcvThread Received length, recieving message..")); - buf=(char *)calloc(1, length+1); - if ((rcv = recv(ClientSocket, buf, length, 0))==SOCKET_ERROR || rcv==0) { - rcvThreadRunning=FALSE; - if (rcv==SOCKET_ERROR) {LOG(("rcvThread Socket error"));} - else {LOG(("rcvThread lost connection, graceful shutdown"));} - free(buf); - return; - } - LOG(("Received message: %s", buf)); - - CopyData.dwData=0; - CopyData.lpData=buf; - CopyData.cbData=(DWORD)strlen(buf)+1; - if (!SendMessage(g_hWnd, WM_COPYDATALOCAL, (WPARAM)hSkypeWnd, (LPARAM)&CopyData)) - { - LOG(("SendMessage failed: %08X", GetLastError())); - } - free(buf); - } -} - -void sendThread(char *dummy) { - COPYDATASTRUCT CopyData; - LRESULT SendResult; - int oldstatus; - unsigned int length; - char *szMsg; - - while (SkypeMsgToSend) { - if (WaitForSingleObject(SkypeMsgToSend, INFINITE) != WAIT_OBJECT_0) return; - if (!(szMsg = MsgQ_Get(&SkypeSendQueue))) continue; - length=(unsigned int)strlen(szMsg); - - if (UseSockets) { - if (send(ClientSocket, (char *)&length, sizeof(length), 0) != SOCKET_ERROR && - send(ClientSocket, szMsg, length, 0) != SOCKET_ERROR) { - free (szMsg); - continue; - } - SendResult = 0; - } else { - CopyData.dwData=0; - CopyData.lpData=szMsg; - CopyData.cbData=length+1; - - // Internal comm channel - if (pszProxyCallout) { - CallService (pszProxyCallout, 0, (LPARAM)&CopyData); - free(szMsg); - continue; - } - - // If this didn't work, proceed with normal Skype API - if (!hSkypeWnd) - { - LOG(("SkypeSend: DAMN! No Skype window handle! :(")); - } - SendResult=SendMessage(hSkypeWnd, WM_COPYDATA, (WPARAM)g_hWnd, (LPARAM)&CopyData); - LOG(("SkypeSend: SendMessage returned %d", SendResult)); - free(szMsg); - } - if (!SendResult) { - SkypeInitialized=FALSE; - AttachStatus=-1; - ResetEvent(SkypeReady); - if (g_hWnd) KillTimer (g_hWnd, 1); - if (SkypeStatus!=ID_STATUS_OFFLINE) { - // Go offline - logoff_contacts(FALSE); - oldstatus=SkypeStatus; - InterlockedExchange((long *)&SkypeStatus, (int)ID_STATUS_OFFLINE); - ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldstatus, SkypeStatus); - } - // Reconnect to Skype - ResetEvent(SkypeReady); - pthread_create(LaunchSkypeAndSetStatusThread, (void *)ID_STATUS_ONLINE); - WaitForSingleObject (SkypeReady, 10000); - // SendMessageTimeout(HWND_BROADCAST, ControlAPIDiscover, (WPARAM)g_hWnd, 0, SMTO_ABORTIFHUNG, 3000, NULL); - } - } -} - - -/* - * Skype Messagequeue - Implemented as a linked list - */ - -/* SkypeMsgInit - * - * Purpose: Initializes the Skype Message queue and API - * Returns: 0 - Success - * -1 - Memory allocation failure - */ -int SkypeMsgInit(void) { - - MsgQ_Init(&SkypeMsgs); - MsgQ_Init(&SkypeSendQueue); - InitializeCriticalSection(&ConnectMutex); - if (SkypeMsgToSend=CreateSemaphore(NULL, 0, MAX_MSGS, NULL)) { - if (m_szSendBuf = (char*)malloc(m_iBufSize=512)) { - if (_beginthread(( pThreadFunc )sendThread, 0, NULL)!=-1) - return 0; - free(m_szSendBuf); - } - CloseHandle (SkypeMsgToSend); - } - return -1; -} - -/* SkypeMsgAdd - * - * Purpose: Add Message to linked list - * Params : msg - Message to add to queue - * Returns: 0 - Success - * -1 - Memory allocation failure - */ -int SkypeMsgAdd(char *msg) { - return MsgQ_Add(&SkypeMsgs, msg)?0:-1; -} - -/* SkypeMsgCleanup - * - * Purpose: Clean up the whole MESSagequeue - free() all - */ -void SkypeMsgCleanup(void) { - int i; - - LOG(("SkypeMsgCleanup Cleaning up message queue..")); - if (receivers>1) - { - LOG (("SkypeMsgCleanup Releasing %d receivers", receivers)); - for (i=0;i %s", szMsg)); - - // Fake PING-PONG, as PING-PONG is not supported by Skype2Socket - if ((UseSockets || bIsImoproxy) && !strcmp(szMsg, "PING")) { - CopyData.dwData=0; - CopyData.lpData="PONG"; - CopyData.cbData=5; - SendMessage(g_hWnd, WM_COPYDATALOCAL, (WPARAM)hSkypeWnd, (LPARAM)&CopyData); - return 0; - } - - if (UseSockets && ClientSocket==INVALID_SOCKET) return -1; - if (!MsgQ_Add(&SkypeSendQueue, szMsg) || !ReleaseSemaphore(SkypeMsgToSend, 1, NULL)) - return -1; - return 0; -} - -/* SkypeSend - * - * Purpose: Sends the specified message to the Skype API. - * If it fails, try to reconnect zu the Skype API - * Params: use like sprintf without first param (dest. buffer) - * Returns: 0 - Success - * -1 - Failure - */ -int SkypeSend(char *szFmt, ...) { - char *pNewBuf; - va_list ap; - size_t iLen; - - // 0.0.0.17+ - Build message-String from supplied parameter list - // so the user doesn't have to care about memory allocation any more. - // 0.0.0.47+ - No more restrictions apply to the format string. - // The temporary buffer remains allocated during the session and gets - // dynamically expanded when needed. This makes sense, as this function - // is used very often and therefore it is faster to not allocate - // memory on every send. - if (!m_szSendBuf && !(m_szSendBuf=(char*)malloc(m_iBufSize=512))) return -1; - do - { - va_start(ap, szFmt); - iLen = _vsnprintf(m_szSendBuf, m_iBufSize, szFmt, ap); - va_end(ap); - if (iLen == -1) - { - if (!(pNewBuf = (char*)realloc (m_szSendBuf, m_iBufSize*2))) - { - iLen = strlen (m_szSendBuf); - break; - } - m_szSendBuf = pNewBuf; - m_iBufSize*=2; - } - } while (iLen == -1); - - return __sendMsg(m_szSendBuf); -} - -/* SkypeRcvTime - * - * Purpose: Wait, until either the message "what" is received or maxwait-Time has passed - * or there was an error and return it - * Params : what - Wait for this string-part at the beginning of a received string - * If the first character of the string is NULL, the rest after the NULL - * character will be searched in the entire received message-string. - * You can tokenize the string by using NULL characters. - * You HAVE TO end the string with a extra \0, otherwise the tokenizer - * will run amok in memory! - * st - The message timestamp must be newer or equal to st. - * Set to 0, if you do not need this and want the first message of this - * kind in the queue. - * maxwait - Wait this time before returning, if nothing was received, - * can be INFINITE - * Returns: The received message containing "what" or a ERROR-Message or NULL if - * time is up and nothing was received - * Warning: Don't forget to free() return value! - */ -char *SkypeRcvTime(char *what, time_t st, DWORD maxwait) { - char *msg, *token=NULL; - struct MsgQueue *ptr; - int j; - DWORD dwWaitStat; - BOOL bChatMsg = FALSE, bIsChatMsg = FALSE; - - LOG (("SkypeRcv - Requesting answer: %s", what)); - if (what) bChatMsg = strncmp(what, "CHATMESSAGE", 11)==0; - do { - EnterCriticalSection(&SkypeMsgs.cs); - // First, search for the requested message. On second run, also accept an ERROR - for (j=0; j<2; j++) - { - for (ptr=SkypeMsgs.l.tqh_first; ptr; ptr=ptr->l.tqe_next) { - if (what && what[0]==0) { - // Tokenizer syntax active - token=what+1; - while (*token) { - if (!strstr (ptr->message, token)) { - token=NULL; - break; - } - token+=strlen(token)+1; - } - } - - //if (j==1) {LOG(("SkypeRcv compare %s (%lu) -- %s (%lu)", ptr->message, ptr->tReceived, what, st));} - if ((st == 0 || ptr->tReceived >= st) && - (what==NULL || token || (what[0] && !strncmp(ptr->message, what, strlen(what))) || - (bIsChatMsg = (j==1 && bChatMsg && !strncmp(ptr->message, what+4, strlen(what+4)))) || - (j==1 && !strncmp(ptr->message, "ERROR", 5)))) - { - msg=MsgQ_RemoveMsg(&SkypeMsgs, ptr); - LOG(("1) InterlockedDecrement ((long *)&receivers); // receivers--; - if (receivers>1) {LOG (("SkypeRcv: %d receivers still waiting", receivers));} - - } while(dwWaitStat == WAIT_OBJECT_0 && !MirandaShuttingDown); - InterlockedDecrement ((long *)&receivers); - LOG(("message, what)); - pCurMsg = ptr->message; - bIsError = FALSE; - if (*what && !strncmp(pCurMsg, what, iLenWhat)) { - // Now we received a MESSAGE with an identifier. So this one is definitely for us - // However the status can be SENDING instead of SENT and next message with this number - // isn't using the ID anymore, so we have to save the ID as new identifier for message recognition - pCurMsg+=iLenWhat; - if ((pMsg = strchr (pCurMsg, ' ')) && (pMsg=strchr (pMsg+1, ' '))) - strncpy (msgid, pCurMsg, pMsg-pCurMsg); - else if (strncmp (pCurMsg, "ERROR", 5) == 0) bIsError = TRUE; - } - - if ((*msgid && strncmp (pCurMsg, msgid, strlen(msgid)) == 0) || - (!*what && ptr->tReceived >= st && - (strncmp(pCurMsg, "MESSAGE", 7) == 0 || strncmp(pCurMsg, "CHATMESSAGE", 11) == 0 ) - ) || bIsError || - (ptr->tReceived >= st && ptr->tReceived <=st+1 && - (bIsError=(strncmp(pCurMsg, "ERROR 26", 8)==0 || strncmp(pCurMsg, "ERROR 43", 8)==0)) - ) ) - { - bProcess = bIsError; - if (!bIsError) { - if ((pMsg = strchr (pCurMsg, ' ')) && (pMsg=strchr (pMsg+1, ' '))) { - pMsg++; - if (strncmp (pMsg, "STATUS ", 7) == 0) { - pMsg+=7; - if (strcmp (pMsg, "SENDING") == 0) { - // Remove dat shit - struct MsgQueue *ptr_=ptr->l.tqe_next; - - free(MsgQ_RemoveMsg(&SkypeMsgs, ptr)); - ptr=ptr_; - continue; - } - bProcess = (strcmp (pMsg, "SENT") == 0 || strcmp (pMsg, "QUEUED") == 0 || - strcmp (pMsg, "FAILED") == 0 || strcmp (pMsg, "IGNORED") == 0 || - strcmp (pMsg, "SENDING") == 0); - } - } - } - if (bProcess) { - msg=MsgQ_RemoveMsg(&SkypeMsgs, ptr); - LOG(("l.tqe_next; - } - LeaveCriticalSection(&SkypeMsgs.cs); - InterlockedIncrement ((long *)&receivers); //receivers++; - dwWaitStat = WaitForSingleObject(SkypeMsgReceived, maxwait); - if (receivers>1) InterlockedDecrement ((long *)&receivers); // receivers--; - if (receivers>1) {LOG (("SkypeRcvMsg: %d receivers still waiting", receivers));} - - } while(dwWaitStat == WAIT_OBJECT_0 && !MirandaShuttingDown); - InterlockedDecrement ((long *)&receivers); - LOG((" Answer %s", str, ptr)); - return ptr; -} - -char *SkypeGetID(char *szWhat, char *szWho, char *szProperty) { - char szID[16]={0}; - static DWORD dwId = 0; - - if (protocol>=4 || bIsImoproxy) sprintf (szID, "#G%d ", dwId++); - return __SkypeGet (szID, szWhat, szWho, szProperty); -} - -char *SkypeGet(char *szWhat, char *szWho, char *szProperty) { - return __SkypeGet ("", szWhat, szWho, szProperty); -} - -#ifdef _UNICODE -WCHAR *SkypeGetW(char *szWhat, WCHAR *szWho, char *szProperty) { - char *ptszWho = (char*)make_utf8_string(szWho); - char *pRet = SkypeGet (szWhat, ptszWho, szProperty); - free (ptszWho); - if (pRet) { - WCHAR *ptr = make_unicode_string((const unsigned char*)pRet); - free (pRet); - return ptr; - } - return NULL; -} -#endif - -char *SkypeGetErr(char *szWhat, char *szWho, char *szProperty) { - char *ret = SkypeGet(szWhat, szWho, szProperty); - if (ret && !strncmp(ret, "ERROR", 5)) { - free (ret); - return NULL; - } - return ret; -} - -#ifdef _UNICODE -WCHAR *SkypeGetErrW(char *szWhat, TCHAR *szWho, char *szProperty) { - WCHAR *ret = SkypeGetW(szWhat, szWho, szProperty); - if (ret && !_tcsncmp(ret, _T("ERROR"), 5)) { - free (ret); - return NULL; - } - return ret; -} -#endif - - -/* SkypeGetProfile - * - * Issues a SET PROFILE szProperty szValue and waits until the answer is received - * Returns the answer or NULL on failure - * BEWARE: Don't forget to free() return value! - * - * For example: SkypeGetProfile("FULLNAME", "Tweety"); -*/ -char *SkypeGetProfile(char *szProperty) { - return SkypeGet ("PROFILE", "", szProperty); -} - -/* SkypeSetProfile - * - * -*/ -int SkypeSetProfile(char *szProperty, char *szValue) { - return SkypeSend("SET PROFILE %s %s", szProperty, szValue); -} - -/* SkypeMsgCollectGarbage - * - * Purpose: Runs the garbage collector on the Skype Message-Queue to throw out old - * messages which may unnecessarily eat up memory. - * Params : age - Time in seconds. Messages older than this value will be - * thrown out. - * Returns: 0 - No messages were thrown out - * >0 - n messages were thrown out - */ -int SkypeMsgCollectGarbage(time_t age) { - return MsgQ_CollectGarbage(&SkypeMsgs, age); -} - - -/* SkypeCall - * - * Purpose: Give a Skype call to the given User in wParam - * or hangs up existing call - * (hangUp is moved over to SkypeCallHangup) - * Params : wParam - Handle to the User to be called - * lParam - Can be NULL - * Returns: 0 - Success - * -1 - Failure - */ -INT_PTR SkypeCall(WPARAM wParam, LPARAM lParam) { - DBVARIANT dbv; - char *msg=0; - int res; - - if (!db_get_s((MCONTACT)wParam, SKYPE_PROTONAME, "CallId", &dbv)) { - res = -1; // no direct return, because dbv needs to be freed - } else { - if (db_get_s((MCONTACT)wParam, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) return -1; - msg=(char *)malloc(strlen(dbv.pszVal)+6); - strcpy(msg, "CALL "); - strcat(msg, dbv.pszVal); - res=SkypeSend(msg); - } - db_free(&dbv); - free(msg); - return res; -} - -/* SkypeCallHangup - * - * Prupose: Hangs up the existing call to the given User - * in wParam. - * - * Params : wParam - Handle to the User to be called - * lParam - Can be NULL - * - * Returns: 0 - Success - * -1 - Failure - * - */ -INT_PTR SkypeCallHangup(WPARAM wParam, LPARAM lParam) -{ - DBVARIANT dbv; - char *msg=0; - int res = -1; - - if (!db_get_s((MCONTACT)wParam, SKYPE_PROTONAME, "CallId", &dbv)) { - msg=(char *)malloc(strlen(dbv.pszVal)+21); - sprintf(msg, "SET %s STATUS FINISHED", dbv.pszVal); - //sprintf(msg, "ALTER CALL %s HANGUP", dbv.pszVal); - res=SkypeSend(msg); -#if _DEBUG - db_unset((MCONTACT)wParam, SKYPE_PROTONAME, "CallId"); -#endif - //} else { - // if (db_get((HANDLE)wParam, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) return -1; - // msg=(char *)malloc(strlen(dbv.pszVal)+6); - // strcpy(msg, "CALL "); - // strcat(msg, dbv.pszVal); - // res=SkypeSend(msg); - } - db_free(&dbv); - free(msg); - return res; -} - -/* FixNumber - * - * Purpose: Eliminates all non-numeric chars from the given phonenumber - * Params : p - Pointer to the buffer with the number - */ -static void FixNumber(char *p) { - unsigned int i; - - for (i=0;i<=strlen(p);i++) - if ((p[i]<'0' || p[i]>'9')) - if (p[i]) { - memmove(p+i, p+i+1, strlen(p+i)); - i--; - } else break; -} - - -/* DialDlgProc - * - * Purpose: Dialog procedure for the Dial-Dialog - */ -static INT_PTR CALLBACK DialDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - static MCONTACT hContact; - static unsigned int entries=0; - BOOL TempAdded=FALSE; - char number[64], *msg, *ptr=NULL; - - switch (uMsg){ - case WM_INITDIALOG: - hContact=(MCONTACT)lParam; - Utils_RestoreWindowPosition(hwndDlg, NULL, SKYPE_PROTONAME, "DIALdlg"); - TranslateDialogDefault(hwndDlg); - - if (lParam) { - DBVARIANT dbv; - BOOL bDialNow=TRUE; - - if (!db_get(hContact,"UserInfo","MyPhone1",&dbv)) { - int j; - char idstr[16]; - - // Multiple phone numbers, select one - bDialNow=FALSE; - db_free(&dbv); - for(j=0;;j++) { - sprintf(idstr,"MyPhone%d",j); - if(db_get_s(hContact,"UserInfo",idstr,&dbv)) break; - FixNumber(dbv.pszVal+1); // Leave + alone - SendDlgItemMessage(hwndDlg,IDC_NUMBER,CB_ADDSTRING,0,(LPARAM)dbv.pszVal); - db_free(&dbv); - } - } - if (db_get_s(hContact,SKYPE_PROTONAME,"SkypeOutNr",&dbv)) { - db_get_s(hContact,"UserInfo","MyPhone0",&dbv); - FixNumber(dbv.pszVal+1); - } - SetDlgItemTextA(hwndDlg, IDC_NUMBER, dbv.pszVal); - db_free(&dbv); - if (bDialNow) PostMessage(hwndDlg, WM_COMMAND, IDDIAL, 0); - } else { - DBVARIANT dbv; - char number[64]; - - for (entries=0;entriesMAX_ENTRIES) entries=MAX_ENTRIES; - for (i=entries;i>0;i--) { - sprintf(buf, "LastNumber%d", i-1); - if (!db_get_s(NULL, SKYPE_PROTONAME, buf, &dbv)) { - sprintf(buf, "LastNumber%d", i); - db_set_s(NULL, SKYPE_PROTONAME, buf, dbv.pszVal); - db_free(&dbv); - } else break; - } - db_set_s(NULL, SKYPE_PROTONAME, "LastNumber0", number); - } - TempAdded=TRUE; - } - if (!db_set_s(hContact, SKYPE_PROTONAME, "SkypeOutNr", number)) { - msg=(char *)malloc(strlen(number)+6); - strcpy(msg, "CALL "); - strcat(msg, number); - if (SkypeSend(msg) || (ptr=SkypeRcv("ERROR", 500))) { - db_unset(hContact, SKYPE_PROTONAME, "SkypeOutNr"); - if (ptr) { - OUTPUTA(ptr); - free(ptr); - } - if (TempAdded) CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0); - } - free(msg); - } - case IDCANCEL: - DestroyWindow(hwndDlg); - break; - } - break; - case WM_DESTROY: - Utils_SaveWindowPosition(hwndDlg, NULL, SKYPE_PROTONAME, "DIALdlg"); - if (httbButton) CallService(MS_TTB_SETBUTTONSTATE, (WPARAM)httbButton, TTBST_RELEASED); - break; - } - return FALSE; -} - -/* CallstatDlgProc - * - * Purpose: Dialog procedure for the CallStatus Dialog - */ -static INT_PTR CALLBACK CallstatDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - static int selected; - static DBVARIANT dbv, dbv2={0}; - - switch (uMsg){ - case WM_INITDIALOG: - { - MCONTACT hContact; - - if (!db_get_s((MCONTACT)lParam, SKYPE_PROTONAME, "CallId", &dbv)) { - - // Check, if another call is in progress - for (hContact=db_find_first(SKYPE_PROTONAME);hContact != NULL;hContact=db_find_next(hContact)) { - char *szProto = (char*)CallService( MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0 ); - if (szProto != NULL && !strcmp(szProto, SKYPE_PROTONAME) && hContact != (MCONTACT)lParam && - db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0) == 0 && - !db_get_s(hContact, SKYPE_PROTONAME, "CallId", &dbv2)) - { - if (db_get_b(hContact, SKYPE_PROTONAME, "OnHold", 0)) { - db_free(&dbv2); - continue; - } else break; - } - } - - if (dbv2.pszVal) - { - char buf[256], buf2[256]; - char *szOtherCaller=(char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact,0); - - Utils_RestoreWindowPosition(hwndDlg, NULL, SKYPE_PROTONAME, "CALLSTATdlg"); - TranslateDialogDefault(hwndDlg); - SendMessage(hwndDlg, WM_COMMAND, IDC_JOIN, 0); - - GetWindowTextA(hwndDlg, buf, sizeof(buf)); - _snprintf(buf2, sizeof(buf), buf, CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)lParam,0)); - SetWindowTextA(hwndDlg, buf2); - - GetDlgItemTextA(hwndDlg, IDC_JOIN, buf, sizeof(buf)); - _snprintf(buf2, sizeof(buf), buf, szOtherCaller); - SetDlgItemTextA(hwndDlg, IDC_JOIN, buf2); - - GetDlgItemTextA(hwndDlg, IDC_HOLD, buf, sizeof(buf)); - _snprintf(buf2, sizeof(buf), buf, szOtherCaller); - SetDlgItemTextA(hwndDlg, IDC_HOLD, buf2); - - return TRUE; - } - - // No other call in progress, no need for this Dlg., just answer the call - SkypeSend("SET %s STATUS INPROGRESS", dbv.pszVal); - testfor ("ERROR", 200); - db_free(&dbv); - } - DestroyWindow(hwndDlg); - break; - } - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDC_JOIN: - case IDC_HOLD: - case IDC_HANGUP: - CheckRadioButton(hwndDlg, IDC_JOIN, IDC_HANGUP, (selected=LOWORD(wParam))); - break; - case IDOK: - { - char *szIdCall2; - - switch (selected) { - case IDC_JOIN: - if (szIdCall2=strchr(dbv2.pszVal, ' ')) - SkypeSend("SET %s JOIN_CONFERENCE%s", dbv.pszVal, szIdCall2); - break; - case IDC_HOLD: - SkypeSend("SET %s STATUS ONHOLD", dbv2.pszVal); - SkypeSend("SET %s STATUS INPROGRESS", dbv.pszVal); - break; - case IDC_HANGUP: - SkypeSend("SET %s STATUS FINISHED", dbv.pszVal); - break; - } - - db_free(&dbv); - db_free(&dbv2); - DestroyWindow(hwndDlg); - break; - } - } - break; - case WM_DESTROY: - Utils_SaveWindowPosition(hwndDlg, NULL, SKYPE_PROTONAME, "CALLSTATdlg"); - break; - } - return FALSE; -} - - -/* SkypeOutCallErrorCheck - * - * Purpose: Checks, if an error has occured after call and - * if so, hangs up the call - * This procedure is a seperate thread to not block the core - * while waiting for "ERROR" - * Params : szCallId - ID of the call - */ -void SkypeOutCallErrorCheck(char *szCallId) { - if (testfor("ERROR", 500)) EndCallThread(szCallId); -} - -/* SkypeOutCall - * - * Purpose: Give a SkypeOut call to the given User in wParam - * or hangs up existing call - * The user's record is searched for Phone-number entries. - * If there is more than 1 entry, the Dial-Dialog is shown - * Params : wParam - Handle to the User to be called - * If NULL, the dial-dialog is shown - * Returns: 0 - Success - * -1 - Failure - */ -INT_PTR SkypeOutCall(WPARAM wParam, LPARAM lParam) { - DBVARIANT dbv; - int res = -1; - - if (wParam && !db_get_s((MCONTACT)wParam, SKYPE_PROTONAME, "CallId", &dbv)) { - res=SkypeSend("SET %s STATUS FINISHED", dbv.pszVal); - pthread_create(( pThreadFunc )SkypeOutCallErrorCheck, _strdup(dbv.pszVal)); - db_free(&dbv); - } else if (!CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_DIAL), NULL, DialDlgProc, (LPARAM)wParam)) return -1; - return res; -} - -/* SkypeHoldCall - * - * Purpose: Put the call to the User given in wParam on Hold or Resumes it - * Params : wParam - Handle to the User - * Returns: 0 - Success - * -1 - Failure - */ -INT_PTR SkypeHoldCall(WPARAM wParam, LPARAM lParam) { - DBVARIANT dbv; - int retval; - - LOG(("SkypeHoldCall started")); - if (!wParam || db_get_s((MCONTACT)wParam, SKYPE_PROTONAME, "CallId", &dbv)) - return -1; - retval = SkypeSend ("SET %s STATUS %s", dbv.pszVal, - db_get_b((MCONTACT)wParam, SKYPE_PROTONAME, "OnHold", 0)?"INPROGRESS":"ONHOLD"); - db_free(&dbv); - return retval; -} - -/* SkypeAnswerCall - * - * Purpose: Answer a Skype-call when a user double-clicks on - * The incoming-call-Symbol. Works for both, Skype and SkypeOut-calls - * Params : wParam - Not used - * lParam - CLISTEVENT* - * Returns: 0 - Success - * -1 - Failure - */ -INT_PTR SkypeAnswerCall(WPARAM wParam, LPARAM lParam) { - - LOG(("SkypeAnswerCall started")); - CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_CALLSTAT), NULL, CallstatDlgProc, (LPARAM)((CLISTEVENT*)lParam)->hContact); - return 0; -} -/* SkypeSetNick - * - * Purpose: Set Full Name in profile - * Params : wParam=0 - * lParam=(LPARAM)(const char*)Nick text - * Returns: 0 - Success - * -1 - Failure - */ -INT_PTR SkypeSetNick(WPARAM wParam, LPARAM lParam) { - int retval = -1; - char *Nick = NULL; - - if (wParam & SMNN_UNICODE) - { - db_set_ws(0, SKYPE_PROTONAME, "Nick", (WCHAR*)lParam); - if (AttachStatus == SKYPECONTROLAPI_ATTACH_SUCCESS && - !(Nick = (char*)make_utf8_string((WCHAR*)lParam))) return -1; - } - else - { - db_set_s(0, SKYPE_PROTONAME, "Nick", (char*)lParam); - if(AttachStatus == SKYPECONTROLAPI_ATTACH_SUCCESS && - utf8_encode((const char *)lParam, &Nick) == -1 ) return -1; - } - if(AttachStatus == SKYPECONTROLAPI_ATTACH_SUCCESS) - retval = SkypeSend("SET PROFILE FULLNAME %s", Nick); - if (Nick) free (Nick); - - return retval; - -} -/* SkypeSetAwayMessage - * - * Purpose: Set Mood message in profile - * Params : wParam=status mode - * lParam=(LPARAM)(const char*)message text - * Returns: 0 - Success - * -1 - Failure - */ -INT_PTR SkypeSetAwayMessage(WPARAM wParam, LPARAM lParam) { - int retval = -1; - char *Mood = NULL; - - if (!lParam) lParam=(LPARAM)""; - if(utf8_encode((const char *)lParam, &Mood) == -1 ) return -1; - db_set_s(NULL, SKYPE_PROTONAME, "MoodText", (const char *)lParam); - - if(AttachStatus == SKYPECONTROLAPI_ATTACH_SUCCESS) - retval = SkypeSend("SET PROFILE MOOD_TEXT %s", Mood); - free (Mood); - - return retval; -} -INT_PTR SkypeSetAwayMessageW(WPARAM wParam, LPARAM lParam) { - int retval = -1; - char *Mood = NULL; - - if (!lParam) lParam=(LPARAM)""; - if (!(Mood = (char*)make_utf8_string((WCHAR*)lParam))) return -1; - db_set_ws(NULL, SKYPE_PROTONAME, "MoodText", (WCHAR*)lParam); - - if(AttachStatus == SKYPECONTROLAPI_ATTACH_SUCCESS) - retval = SkypeSend("SET PROFILE MOOD_TEXT %s", Mood); - free (Mood); - - return retval; -} - -/* SkypeSetAvatar - * - * Purpose: Set user avatar in profile - * Params : wParam=0 - * lParam=(LPARAM)(const char*)filename - * Returns: 0 - Success - * -1 - Failure - */ -INT_PTR SkypeSetAvatar(WPARAM wParam, LPARAM lParam) { - char *filename = (char *) lParam, *ext; - char AvatarFile[MAX_PATH+1], OldAvatarFile[1024]; - char *ptr = NULL; - int ret; - char command[500]; - DBVARIANT dbv = {0}; - BOOL hasOldAvatar = (db_get_s(NULL, SKYPE_PROTONAME, "AvatarFile", &dbv) == 0 && dbv.type == DBVT_ASCIIZ); - size_t len; - - if (AttachStatus != SKYPECONTROLAPI_ATTACH_SUCCESS) - return -3; - - if (filename == NULL) - return -1; - len = strlen(filename); - if (len < 4) - return -1; - - ext = &filename[len-4]; - if (_stricmp(ext, ".jpg")==0 || _stricmp(ext-1, ".jpeg")==0) - ext = "jpg"; - else if (_stricmp(ext, ".png")==0) - ext = "png"; - else - return -2; - - FoldersGetCustomPath(hProtocolAvatarsFolder, AvatarFile, sizeof(AvatarFile), DefaultAvatarsFolder); - if (!*AvatarFile) strcpy (AvatarFile, DefaultAvatarsFolder); - mir_snprintf(AvatarFile, sizeof(AvatarFile), "%s\\%s avatar.%s", AvatarFile, SKYPE_PROTONAME, ext); - - // Backup old file - if (hasOldAvatar) - { - strncpy(OldAvatarFile, dbv.pszVal, sizeof(OldAvatarFile)-4); - OldAvatarFile[sizeof(OldAvatarFile)-5] = '\0'; - strcat(OldAvatarFile, "_old"); - DeleteFileA(OldAvatarFile); - if (!MoveFileA(dbv.pszVal, OldAvatarFile)) - { - db_free(&dbv); - return -3; - } - } - - // Copy new file - if (!CopyFileA(filename, AvatarFile, FALSE)) - { - if (hasOldAvatar) - { - MoveFileA(OldAvatarFile, dbv.pszVal); - db_free(&dbv); - } - return -3; - } - - // Try to set with skype - mir_snprintf(command, sizeof(command), "SET AVATAR 1 %s", AvatarFile); - if (SkypeSend(command) || (ptr = SkypeRcv(command+4, INFINITE)) == NULL || !strncmp(ptr, "ERROR", 5)) - { - DeleteFileA(AvatarFile); - - if (hasOldAvatar) - MoveFileA(OldAvatarFile, dbv.pszVal); - - ret = -4; - } - else - { - if (hasOldAvatar) - DeleteFileA(OldAvatarFile); - - db_set_s(NULL, SKYPE_PROTONAME, "AvatarFile", AvatarFile); - - ret = 0; - } - - if (ptr != NULL) - free(ptr); - - if (hasOldAvatar) - db_free(&dbv); - - return ret; -} - - -/* SkypeSendFile - * - * Purpose: Opens the Skype-dialog to send a file - * Params : wParam - Handle to the User - * lParam - Not used - * Returns: 0 - Success - * -1 - Failure - */ -INT_PTR SkypeSendFile(WPARAM wParam, LPARAM lParam) { - DBVARIANT dbv; - int retval; - - if (!wParam || db_get_s((MCONTACT)wParam, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) - return -1; - retval=SkypeSend("OPEN FILETRANSFER %s", dbv.pszVal); - db_free(&dbv); - return retval; -} - -/* SkypeChatCreate - * - * Purpose: Creates a groupchat with the user - * Params : wParam - Handle to the User - * lParam - Not used - * Returns: 0 - Success - * -1 - Failure - */ -INT_PTR SkypeChatCreate(WPARAM wParam, LPARAM lParam) { - DBVARIANT dbv; - MCONTACT hContact=(MCONTACT)wParam; - char *ptr, *ptr2; - - if (!hContact || db_get_s(hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) - return -1; - // Flush old messages - while (testfor("\0CHAT \0 STATUS \0", 0)); - if (SkypeSend("CHAT CREATE %s", dbv.pszVal) || !(ptr=SkypeRcv ("\0CHAT \0 STATUS \0", INFINITE))) - { - db_free(&dbv); - return -1; - } - db_free(&dbv); - if (ptr2=strstr (ptr, "STATUS")) { - *(ptr2-1)=0; - ChatStart (ptr+5, FALSE); - } - free(ptr); - return 0; -} - -/* SkypeAdduserDlg - * - * Purpose: Show Skype's Add user Dialog - */ -INT_PTR SkypeAdduserDlg(WPARAM wParam, LPARAM lParam) { - SkypeSend("OPEN ADDAFRIEND"); - return 0; -} - -/* SkypeFlush - * - * Purpose: Flush the Skype Message-List - */ -void SkypeFlush(void) { - char *ptr; - - while ((ptr=SkypeRcv(NULL, 0))!=NULL) free(ptr); -} - -/* SkypeStatusToMiranda - * - * Purpose: Converts the specified Skype-Status mode to the corresponding Miranda-Status mode - * Params : s - Skype Status - * Returns: The correct Status - * 0 - Nothing found - */ -int SkypeStatusToMiranda(char *s) { - int i; - if (!strcmp("SKYPEOUT", s)) return db_get_dw(NULL, SKYPE_PROTONAME, "SkypeOutStatusMode", ID_STATUS_ONTHEPHONE); - for(i=0; status_codes[i].szStat; i++) - if (!strcmp(status_codes[i].szStat, s)) - return status_codes[i].id; - return 0; -} - -/* MirandaStatusToSkype - * - * Purpose: Converts the specified Miranda-Status mode to the corresponding Skype-Status mode - * Params : id - Miranda Status - * Returns: The correct Status - * NULL - Nothing found - */ -char *MirandaStatusToSkype(int id) { - int i; - if (db_get_b(NULL, SKYPE_PROTONAME, "NoSkype3Stats", 0)) { - switch (id) - { - case ID_STATUS_NA: return "AWAY"; - case ID_STATUS_FREECHAT: return "ONLINE"; - } - } - for(i=0; status_codes[i].szStat; i++) - if (status_codes[i].id==id) - return status_codes[i].szStat; - return NULL; -} - -/* GetSkypeErrorMsg - * - * Purpose: Get a human-readable Error-Message for the supplied Skype Error-Message - * Params : str - Skype Error-Message string - * Returns: Human-readable Error Message or NULL, if nothing was found - * Warning: Don't forget to free() return value - */ -char *GetSkypeErrorMsg(char *str) { - char *pos, *reason, *msg; - - LOG (("GetSkypeErrorMsg received error: %s", str)); - if (!strncmp(str, "ERROR", 5)) { - reason=_strdup(str); - return reason; - } - if ((pos=strstr(str, "FAILURE")) ) { - switch(atoi(pos+14)) { - case MISC_ERROR: msg="Misc. Error"; break; - case USER_NOT_FOUND: msg="User does not exist, check username"; break; - case USER_NOT_ONLINE: msg="Trying to send IM to an user, who is not online"; break; - case USER_BLOCKED: msg="IM blocked by recipient"; break; - case TYPE_UNSUPPORTED: msg="Type unsupported"; break; - case SENDER_NOT_FRIEND: msg="Sending IM message to user, who has not added you to friendslist and has chosen 'only people in my friendslist can start IM'"; break; - case SENDER_NOT_AUTHORIZED: msg="Sending IM message to user, who has not authorized you and has chosen 'only people whom I have authorized can start IM'"; break; - default: msg="Unknown error"; - } - reason=(char *)malloc(strlen(pos)+strlen(msg)+3); - sprintf (reason, "%s: %s", pos, msg); - return reason; - } - return NULL; -} - -/* testfor - * - * Purpose: Wait, until the given Message-Fragment is received from Skype within - * the given amount of time - * Params : see SkypeRcv - * Returns: TRUE - Message was received within the given amount of time - * FALSE- nope, sorry - */ -BOOL testfor(char *what, DWORD maxwait) { - char *res; - - if ((res=SkypeRcv(what, maxwait))==NULL) return FALSE; - free(res); - return TRUE; -} - -char SendSkypeproxyCommand(char command) { - int length=0; - char reply=0; - BOOL res; - - res = send(ClientSocket, (char *)&length, sizeof(length), 0)==SOCKET_ERROR - || send(ClientSocket, (char *)&command, sizeof(command), 0)==SOCKET_ERROR - || recv(ClientSocket, (char *)&reply, sizeof(reply), 0)==SOCKET_ERROR; - if (res) - return -1; - else - return reply; -} - -/* ConnectToSkypeAPI - * - * Purpose: Establish a connection to the Skype API - * Params : path - Path to the Skype application - * iStart - Need to start skype for status change. - * 1 = Normal start if Skype not running - * 2 = Forced startp code execution no matter what - * Returns: 0 - Connecting succeeded - * -1 - Something went wrong - */ -int ConnectToSkypeAPI(char *path, int iStart) { - static int iRet = -1; // last request result - static volatile long newRequest = TRUE; - - InterlockedExchange(&newRequest, TRUE); // place new request - EnterCriticalSection(&ConnectMutex); // Prevent reentrance - if (iRet == -1 || newRequest) - { - iRet = _ConnectToSkypeAPI(path, iStart); - InterlockedExchange(&newRequest, FALSE); // every thread which is waiting for connect mutex will get our result as well.. but subsequent calls will set this value to true and call _Connect again - } - LeaveCriticalSection(&ConnectMutex); - return iRet; -} - -void TranslateMirandaRelativePathToAbsolute(LPCSTR cszPath, LPSTR szAbsolutePath, BOOL fQuoteSpaces) { - *szAbsolutePath = 0; - CallService (MS_UTILS_PATHTOABSOLUTE, (WPARAM)(*cszPath ? cszPath : ".\\"), (LPARAM)szAbsolutePath); - if(fQuoteSpaces && strchr((LPCSTR)szAbsolutePath, ' ')){ - memmove (szAbsolutePath+1, szAbsolutePath, strlen(szAbsolutePath)+1); - *szAbsolutePath='"'; - strcat (szAbsolutePath, "\""); - } - - TRACEA(szAbsolutePath); -} - -static int my_spawnv(const char *cmdname, const char *const *argv, PROCESS_INFORMATION *pi) -{ - int i, iLen=0; - char *CommandLine; - STARTUPINFOA si={0}; - BOOL bRet; - - memset (pi, 0, sizeof(PROCESS_INFORMATION)); - for (i=0; argv[i]; i++) - iLen += (int)strlen(argv[i])+1; - if (!(CommandLine = (char*)calloc(1, iLen))) return -1; - for (i=0; argv[i]; i++) { - if (i) strcat (CommandLine, " "); - strcat (CommandLine, argv[i]); - } - si.cb = sizeof(si); - - bRet = CreateProcessA( cmdname,CommandLine,NULL,NULL,FALSE,0,NULL,NULL,&si,pi); - free(CommandLine); - if (!bRet) return -1; - return (DWORD)pi->hProcess; -} - -static int _ConnectToSkypeAPI(char *path, int iStart) { - BOOL SkypeLaunched=FALSE; - BOOL UseCustomCommand = db_get_b(NULL, SKYPE_PROTONAME, "UseCustomCommand", 0); - int counter=0, i, j, maxattempts=db_get_w(NULL, SKYPE_PROTONAME, "ConnectionAttempts", 10); - char *args[16], *pFree = NULL; - char *SkypeOptions[]={"/notray", "/nosplash", "/minimized", "/removable", "/datapath:", "/secondary"}; - const int SkypeDefaults[]={0, 1, 1, 0, 0}; - - char szAbsolutePath[MAX_PATH]; - - LOG(("ConnectToSkypeAPI started.")); - if (UseSockets) - { - SOCKADDR_IN service; - DBVARIANT dbv; - long inet; - struct hostent *hp; - - LOG(("ConnectToSkypeAPI: Connecting to Skype2socket socket...")); - if ((ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))==INVALID_SOCKET) return -1; - - if (!db_get_s(NULL, SKYPE_PROTONAME, "Host", &dbv)) { - if ((inet=inet_addr(dbv.pszVal))==-1) { - if (hp=gethostbyname(dbv.pszVal)) - memcpy(&inet, hp->h_addr, sizeof(inet)); - else { - OUTPUT(_T("Cannot resolve host!")); - db_free(&dbv); - return -1; - } - } - db_free(&dbv); - } else { - OUTPUT(_T("Cannot find valid host to connect to.")); - return -1; - } - - service.sin_family = AF_INET; - service.sin_addr.s_addr = inet; - service.sin_port = htons((unsigned short)db_get_w(NULL, SKYPE_PROTONAME, "Port", 1401)); - - if ( connect( ClientSocket, (SOCKADDR*) &service, sizeof(service) ) == SOCKET_ERROR) return -1; - - if (db_get_b(NULL, SKYPE_PROTONAME, "RequiresPassword", 0) && !db_get_s(NULL, SKYPE_PROTONAME, "Password", &dbv)) - { - char reply=0; - - if ((reply=SendSkypeproxyCommand(AUTHENTICATE))==-1) { - db_free(&dbv); - return -1; - } - if (!reply) { - OUTPUT(_T("Authentication is not supported/needed for this Skype proxy server. It will be disabled.")); - db_set_b(NULL, SKYPE_PROTONAME, "RequiresPassword", 0); - } else { - unsigned int length=(unsigned int)strlen(dbv.pszVal); - BOOL res; - res = send(ClientSocket, (char *)&length, sizeof(length), 0)==SOCKET_ERROR - || send(ClientSocket, dbv.pszVal, length, 0)==SOCKET_ERROR - || recv(ClientSocket, (char *)&reply, sizeof(reply), 0)==SOCKET_ERROR; - if (res) - { - db_free(&dbv); - return -1; - } - if (!reply) - { - OUTPUT(_T("Authentication failed for this server, connection was not successful. Verify that your password is correct!")); - db_free(&dbv); - return -1; - } - } - db_free(&dbv); - } - else - { - char reply=0; - - if ((reply=SendSkypeproxyCommand(CAPABILITIES))==-1) return -1; - if (reply&USE_AUTHENTICATION) { - OUTPUT(_T("The server you specified requires authentication, but you have not supplied a password for it. Check the Skype plugin settings and try again.")); - return -1; - } - } - - - if (!rcvThreadRunning) - if(_beginthread(( pThreadFunc )rcvThread, 0, NULL)==-1) return -1; - - AttachStatus=SKYPECONTROLAPI_ATTACH_SUCCESS; - return 0; - } - - if (pszProxyCallout) - { - if (SkypeSend("SET USERSTATUS ONLINE")==-1) - { - AttachStatus=SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE; - return -1; - } - for ( ;; ) { - char *ptr = SkypeRcv ("CONNSTATUS", INFINITE); - if (!ptr) - { - AttachStatus=SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE; - return -1; - } - - if (strcmp (ptr+11, "CONNECTING")) - { - free (ptr); - break; - } - free (ptr); - } - - AttachStatus=SKYPECONTROLAPI_ATTACH_SUCCESS; - return 0; - } - - do - { - int retval; - /* To initiate communication, Client should broadcast windows message - ('SkypeControlAPIDiscover') to all windows in the system, specifying its own - window handle in wParam parameter. - */ - if (iStart != 2 || counter) - { - LOG(("ConnectToSkypeAPI sending discover message.. hWnd=%08X", (long)g_hWnd)); - retval = (int)SendMessageTimeout(HWND_BROADCAST, ControlAPIDiscover, (WPARAM)g_hWnd, 0, SMTO_ABORTIFHUNG, 3000, NULL); - LOG(("ConnectToSkypeAPI sent discover message returning %d", retval)); - } - - /* In response, Skype responds with - message 'SkypeControlAPIAttach' to the handle specified, and indicates - connection status - SkypeReady is set if there is an answer by Skype other than API_AVAILABLE. - If there is no answer after 3 seconds, launch Skype as it's propably - not running. - */ - if (iStart == 2 || (WaitForSingleObject(SkypeReady, 3000)==WAIT_TIMEOUT && AttachStatus!=SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION)) - { - if (iStart != 2 && g_hWnd==NULL) - { - LOG(("ConnectToSkypeAPI: hWnd of SkypeDispatchWindow not yet set..")); - continue; - } - if ((iStart == 2 || !SkypeLaunched) && (path || UseCustomCommand)) - { - static PROCESS_INFORMATION pi={0}; - DWORD dwExitStatus = 0; - - if ((!pi.hProcess || !GetExitCodeProcess(pi.hProcess, &dwExitStatus) || dwExitStatus != STILL_ACTIVE) && - (db_get_b(NULL, SKYPE_PROTONAME, "StartSkype", 1) || iStart)) - { - LOG(("ConnectToSkypeAPI Starting Skype, as it's not running")); - - j=1; - for (i=0; i < SIZEOF(SkypeOptions); i++) - if (db_get_b(NULL, SKYPE_PROTONAME, SkypeOptions[i]+1, SkypeDefaults[i])) { - DBVARIANT dbv; - - switch (i) - { - case 4: - if(!db_get_s(NULL,SKYPE_PROTONAME,"datapath",&dbv)) - { - int paramSize; - TranslateMirandaRelativePathToAbsolute(dbv.pszVal, szAbsolutePath, TRUE); - paramSize = (int)strlen(SkypeOptions[i]) + (int)strlen(szAbsolutePath); - pFree = args[j] = (char*)malloc(paramSize + 1); - sprintf(args[j],"%s%s",SkypeOptions[i],szAbsolutePath); - db_free(&dbv); - } - break; - case 2: - args[j++]="/legacylogin"; - default: - args[j]=SkypeOptions[i]; - break; - } - LOG(("Using Skype parameter: %s", args[j])); - //MessageBox(NULL,"Using Skype parameter: ",args[j],0); - j++; - } - args[j]=NULL; - - if(UseCustomCommand) - { - DBVARIANT dbv; - - if(!db_get_s(NULL,SKYPE_PROTONAME,"CommandLine",&dbv)) - { - TranslateMirandaRelativePathToAbsolute(dbv.pszVal, szAbsolutePath, FALSE); - args[0] = (LPSTR)szAbsolutePath; - LOG(("ConnectToSkypeAPI: Launch skype using command line")); - if (!*szAbsolutePath || my_spawnv(szAbsolutePath, args, &pi) == -1) { - LOG(("ConnectToSkypeAPI: Failed to launch skype!")); - } else { - WaitForInputIdle((HANDLE)pi.hProcess, 5000); - setUserNamePassword(pi.dwProcessId); - } - db_free(&dbv); - } - } - else - { - args[0]=path; - LOG(("ConnectToSkypeAPI: Launch skype")); - /*for(int i=0;i=maxattempts && AttachStatus==-1) - { - int oldstatus=SkypeStatus; - InterlockedExchange((long *)&SkypeStatus, (int)ID_STATUS_OFFLINE); - ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldstatus, SkypeStatus); - OUTPUT(_T("ERROR: Skype not running / too old / working!")); - return -1; - } - } - } - LOG(("Attachstatus %d", AttachStatus)); - } while (AttachStatus==SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE || AttachStatus==SKYPECONTROLAPI_ATTACH_API_AVAILABLE || AttachStatus==-1); - - while (AttachStatus==SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION) Sleep(1000); - LOG(("Attachstatus %d", AttachStatus)); - if (AttachStatus!=SKYPECONTROLAPI_ATTACH_SUCCESS) { - int oldstatus; - - switch(AttachStatus) { - case SKYPECONTROLAPI_ATTACH_REFUSED: - OUTPUT(_T("Skype refused the connection :(")); - break; - case SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE: - OUTPUT(_T("The Skype API is not available")); - break; - default: - LOG(("ERROR: AttachStatus: %d", AttachStatus)); - OUTPUT(_T("Wheee, Skype won't let me use the API. :(")); - } - oldstatus=SkypeStatus; - InterlockedExchange((long *)&SkypeStatus, (int)ID_STATUS_OFFLINE); - ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldstatus, SkypeStatus); - return -1; - } - - return 0; -} - -/* CloseSkypeAPI - * Purpose: Closes existing api connection - * Params: path - Path to the Skype application; could be NULL when using proxy - * Returns: always 0 - */ -int CloseSkypeAPI(char *skypePath) -{ - char szAbsolutePath[MAX_PATH]; - - logoff_contacts(TRUE); - if (UseSockets) - { - if (ClientSocket != INVALID_SOCKET) - { - closesocket(ClientSocket); - ClientSocket = INVALID_SOCKET; - } - } - else { - if (!pszProxyCallout) - { - if (AttachStatus!=-1) - { - // it was crashing when the skype-network-proxy is used (imo2sproxy for imo.im) and skype-path is empty - // now, with the "UseSockets" check and the skypePath[0] != 0 check its fixed - if (skypePath != NULL && skypePath[0] != 0) { - TranslateMirandaRelativePathToAbsolute(skypePath, szAbsolutePath, FALSE); - _spawnl(_P_NOWAIT, szAbsolutePath, szAbsolutePath, "/SHUTDOWN", NULL); - } - } - } - } - SkypeInitialized=FALSE; - ResetEvent(SkypeReady); - AttachStatus=-1; - if (g_hWnd) KillTimer (g_hWnd, 1); - return 0; -} -/* ConnectToSkypeAPI - * - * Purpose: Establish a connection to the Skype API - * Params : path - Path to the Skype application - * Returns: 0 - Connecting succeeded - * -1 - Something went wrong - */ -//int __connectAPI(char *path) { -// int retval; -// -// EnterCriticalSection(&ConnectMutex); -// if (AttachStatus!=-1) { -// LeaveCriticalSection(&ConnectMutex); -// return -1; -// } -// InterlockedExchange((long *)&SkypeStatus, ID_STATUS_CONNECTING); -// ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) ID_STATUS_OFFLINE, SkypeStatus); -// retval=__connectAPI(path); -// if (retval==-1) { -// logoff_contacts(); -// InterlockedExchange((long *)&SkypeStatus, ID_STATUS_OFFLINE); -// ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) ID_STATUS_CONNECTING, SkypeStatus); -// } -// LeaveCriticalSection(&ConnectMutex); -// return retval; -//} diff --git a/protocols/SkypeClassic/src/skypeapi.cpp b/protocols/SkypeClassic/src/skypeapi.cpp new file mode 100644 index 0000000000..1534a3530a --- /dev/null +++ b/protocols/SkypeClassic/src/skypeapi.cpp @@ -0,0 +1,1707 @@ +/* + * SkypeAPI - All more or less important functions that deal with Skype + */ + +#include "skype.h" +#include "skypeapi.h" +#include "utf8.h" +#include "debug.h" +#include "contacts.h" +#include "skypeproxy.h" +#include "pthread.h" +#include "gchat.h" +#include "alogon.h" +#include "msgq.h" +#include +#pragma warning (push) +#pragma warning (disable: 4100) // unreferenced formal parameter +#include +#include +#pragma warning (push) +#include + +#pragma warning (disable: 4706) // assignment within conditional expression + +// Imported Globals +extern HWND hSkypeWnd, g_hWnd; +extern BOOL SkypeInitialized, UseSockets, MirandaShuttingDown, bIsImoproxy; +extern int SkypeStatus, receivers; +extern HANDLE SkypeReady, SkypeMsgReceived, httbButton; +extern UINT ControlAPIAttach, ControlAPIDiscover; +extern LONG AttachStatus; +extern HINSTANCE hInst; +extern PLUGININFOEX pluginInfo; +extern HANDLE hProtocolAvatarsFolder, hHookSkypeApiRcv; +extern char DefaultAvatarsFolder[MAX_PATH+1], *pszProxyCallout, protocol, g_szProtoName[]; + +// -> Skype Message Queue functions // + +static TYP_MSGQ SkypeMsgs, SkypeSendQueue; + +status_map status_codes[] = { + {ID_STATUS_AWAY, "AWAY"}, + {ID_STATUS_NA, "NA"}, + {ID_STATUS_DND, "DND"}, + {ID_STATUS_ONLINE, "ONLINE"}, + {ID_STATUS_FREECHAT, "SKYPEME"}, // Unfortunately Skype API tells us userstatus ONLINE, if we are free for chat + {ID_STATUS_OFFLINE, "OFFLINE"}, + {ID_STATUS_INVISIBLE, "INVISIBLE"}, + {ID_STATUS_CONNECTING, "CONNECTING"}, + {0, NULL} +}; + +//status_map + + +static CRITICAL_SECTION ConnectMutex; +static BOOL rcvThreadRunning=FALSE, isConnecting = FALSE; +static SOCKET ClientSocket=INVALID_SOCKET; +static HANDLE SkypeMsgToSend=NULL; + +static char *m_szSendBuf = NULL; +static DWORD m_iBufSize = 0; + + +static int _ConnectToSkypeAPI(char *path, BOOL bStart); + + +/* SkypeReceivedMessage + * + * Purpose: Hook to be called when a message is received, if some caller is + * using our internal I/O services. + * Params : wParam - Not used + * lParam - COPYDATASTRUCT like in WM_COPYDATA + * Returns: Result from SendMessage + */ +INT_PTR SkypeReceivedAPIMessage(WPARAM wParam, LPARAM lParam) { + return SendMessage(g_hWnd, WM_COPYDATALOCAL, (WPARAM)hSkypeWnd, lParam); +} + +/* + * Skype via Socket --> Skype2Socket connection + */ + +void rcvThread(char *dummy) { + unsigned int length; + char *buf; + COPYDATASTRUCT CopyData; + int rcv; + + if (!UseSockets) return; + rcvThreadRunning=TRUE; + for ( ;; ) { + if (ClientSocket==INVALID_SOCKET) { + rcvThreadRunning=FALSE; + return; + } + LOG(("rcvThread Receiving from socket..")); + if ((rcv=recv(ClientSocket, (char *)&length, sizeof(length), 0))==SOCKET_ERROR || rcv==0) { + rcvThreadRunning=FALSE; + if (rcv==SOCKET_ERROR) {LOG(("rcvThread Socket error"));} + else {LOG(("rcvThread lost connection, graceful shutdown"));} + return; + } + LOG(("rcvThread Received length, recieving message..")); + buf=(char *)calloc(1, length+1); + if ((rcv = recv(ClientSocket, buf, length, 0))==SOCKET_ERROR || rcv==0) { + rcvThreadRunning=FALSE; + if (rcv==SOCKET_ERROR) {LOG(("rcvThread Socket error"));} + else {LOG(("rcvThread lost connection, graceful shutdown"));} + free(buf); + return; + } + LOG(("Received message: %s", buf)); + + CopyData.dwData=0; + CopyData.lpData=buf; + CopyData.cbData=(DWORD)strlen(buf)+1; + if (!SendMessage(g_hWnd, WM_COPYDATALOCAL, (WPARAM)hSkypeWnd, (LPARAM)&CopyData)) + { + LOG(("SendMessage failed: %08X", GetLastError())); + } + free(buf); + } +} + +void sendThread(char *dummy) { + COPYDATASTRUCT CopyData; + LRESULT SendResult; + int oldstatus; + unsigned int length; + char *szMsg; + + while (SkypeMsgToSend) { + if (WaitForSingleObject(SkypeMsgToSend, INFINITE) != WAIT_OBJECT_0) return; + if (!(szMsg = MsgQ_Get(&SkypeSendQueue))) continue; + length=(unsigned int)strlen(szMsg); + + if (UseSockets) { + if (send(ClientSocket, (char *)&length, sizeof(length), 0) != SOCKET_ERROR && + send(ClientSocket, szMsg, length, 0) != SOCKET_ERROR) { + free (szMsg); + continue; + } + SendResult = 0; + } else { + CopyData.dwData=0; + CopyData.lpData=szMsg; + CopyData.cbData=length+1; + + // Internal comm channel + if (pszProxyCallout) { + CallService (pszProxyCallout, 0, (LPARAM)&CopyData); + free(szMsg); + continue; + } + + // If this didn't work, proceed with normal Skype API + if (!hSkypeWnd) + { + LOG(("SkypeSend: DAMN! No Skype window handle! :(")); + } + SendResult=SendMessage(hSkypeWnd, WM_COPYDATA, (WPARAM)g_hWnd, (LPARAM)&CopyData); + LOG(("SkypeSend: SendMessage returned %d", SendResult)); + free(szMsg); + } + if (!SendResult) { + SkypeInitialized=FALSE; + AttachStatus=-1; + ResetEvent(SkypeReady); + if (g_hWnd) KillTimer (g_hWnd, 1); + if (SkypeStatus!=ID_STATUS_OFFLINE) { + // Go offline + logoff_contacts(FALSE); + oldstatus=SkypeStatus; + InterlockedExchange((long *)&SkypeStatus, (int)ID_STATUS_OFFLINE); + ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldstatus, SkypeStatus); + } + // Reconnect to Skype + ResetEvent(SkypeReady); + pthread_create(LaunchSkypeAndSetStatusThread, (void *)ID_STATUS_ONLINE); + WaitForSingleObject (SkypeReady, 10000); + // SendMessageTimeout(HWND_BROADCAST, ControlAPIDiscover, (WPARAM)g_hWnd, 0, SMTO_ABORTIFHUNG, 3000, NULL); + } + } +} + + +/* + * Skype Messagequeue - Implemented as a linked list + */ + +/* SkypeMsgInit + * + * Purpose: Initializes the Skype Message queue and API + * Returns: 0 - Success + * -1 - Memory allocation failure + */ +int SkypeMsgInit(void) { + + MsgQ_Init(&SkypeMsgs); + MsgQ_Init(&SkypeSendQueue); + InitializeCriticalSection(&ConnectMutex); + if (SkypeMsgToSend=CreateSemaphore(NULL, 0, MAX_MSGS, NULL)) { + if (m_szSendBuf = (char*)malloc(m_iBufSize=512)) { + if (_beginthread(( pThreadFunc )sendThread, 0, NULL)!=-1) + return 0; + free(m_szSendBuf); + } + CloseHandle (SkypeMsgToSend); + } + return -1; +} + +/* SkypeMsgAdd + * + * Purpose: Add Message to linked list + * Params : msg - Message to add to queue + * Returns: 0 - Success + * -1 - Memory allocation failure + */ +int SkypeMsgAdd(char *msg) { + return MsgQ_Add(&SkypeMsgs, msg)?0:-1; +} + +/* SkypeMsgCleanup + * + * Purpose: Clean up the whole MESSagequeue - free() all + */ +void SkypeMsgCleanup(void) { + int i; + + LOG(("SkypeMsgCleanup Cleaning up message queue..")); + if (receivers>1) + { + LOG (("SkypeMsgCleanup Releasing %d receivers", receivers)); + for (i=0;i %s", szMsg)); + + // Fake PING-PONG, as PING-PONG is not supported by Skype2Socket + if ((UseSockets || bIsImoproxy) && !strcmp(szMsg, "PING")) { + CopyData.dwData=0; + CopyData.lpData="PONG"; + CopyData.cbData=5; + SendMessage(g_hWnd, WM_COPYDATALOCAL, (WPARAM)hSkypeWnd, (LPARAM)&CopyData); + return 0; + } + + if (UseSockets && ClientSocket==INVALID_SOCKET) return -1; + if (!MsgQ_Add(&SkypeSendQueue, szMsg) || !ReleaseSemaphore(SkypeMsgToSend, 1, NULL)) + return -1; + return 0; +} + +/* SkypeSend + * + * Purpose: Sends the specified message to the Skype API. + * If it fails, try to reconnect zu the Skype API + * Params: use like sprintf without first param (dest. buffer) + * Returns: 0 - Success + * -1 - Failure + */ +int SkypeSend(char *szFmt, ...) { + char *pNewBuf; + va_list ap; + size_t iLen; + + // 0.0.0.17+ - Build message-String from supplied parameter list + // so the user doesn't have to care about memory allocation any more. + // 0.0.0.47+ - No more restrictions apply to the format string. + // The temporary buffer remains allocated during the session and gets + // dynamically expanded when needed. This makes sense, as this function + // is used very often and therefore it is faster to not allocate + // memory on every send. + if (!m_szSendBuf && !(m_szSendBuf=(char*)malloc(m_iBufSize=512))) return -1; + do + { + va_start(ap, szFmt); + iLen = _vsnprintf(m_szSendBuf, m_iBufSize, szFmt, ap); + va_end(ap); + if (iLen == -1) + { + if (!(pNewBuf = (char*)realloc (m_szSendBuf, m_iBufSize*2))) + { + iLen = strlen (m_szSendBuf); + break; + } + m_szSendBuf = pNewBuf; + m_iBufSize*=2; + } + } while (iLen == -1); + + return __sendMsg(m_szSendBuf); +} + +/* SkypeRcvTime + * + * Purpose: Wait, until either the message "what" is received or maxwait-Time has passed + * or there was an error and return it + * Params : what - Wait for this string-part at the beginning of a received string + * If the first character of the string is NULL, the rest after the NULL + * character will be searched in the entire received message-string. + * You can tokenize the string by using NULL characters. + * You HAVE TO end the string with a extra \0, otherwise the tokenizer + * will run amok in memory! + * st - The message timestamp must be newer or equal to st. + * Set to 0, if you do not need this and want the first message of this + * kind in the queue. + * maxwait - Wait this time before returning, if nothing was received, + * can be INFINITE + * Returns: The received message containing "what" or a ERROR-Message or NULL if + * time is up and nothing was received + * Warning: Don't forget to free() return value! + */ +char *SkypeRcvTime(char *what, time_t st, DWORD maxwait) { + char *msg, *token=NULL; + struct MsgQueue *ptr; + int j; + DWORD dwWaitStat; + BOOL bChatMsg = FALSE, bIsChatMsg = FALSE; + + LOG (("SkypeRcv - Requesting answer: %s", what)); + if (what) bChatMsg = strncmp(what, "CHATMESSAGE", 11)==0; + do { + EnterCriticalSection(&SkypeMsgs.cs); + // First, search for the requested message. On second run, also accept an ERROR + for (j=0; j<2; j++) + { + for (ptr=SkypeMsgs.l.tqh_first; ptr; ptr=ptr->l.tqe_next) { + if (what && what[0]==0) { + // Tokenizer syntax active + token=what+1; + while (*token) { + if (!strstr (ptr->message, token)) { + token=NULL; + break; + } + token+=strlen(token)+1; + } + } + + //if (j==1) {LOG(("SkypeRcv compare %s (%lu) -- %s (%lu)", ptr->message, ptr->tReceived, what, st));} + if ((st == 0 || ptr->tReceived >= st) && + (what==NULL || token || (what[0] && !strncmp(ptr->message, what, strlen(what))) || + (bIsChatMsg = (j==1 && bChatMsg && !strncmp(ptr->message, what+4, strlen(what+4)))) || + (j==1 && !strncmp(ptr->message, "ERROR", 5)))) + { + msg=MsgQ_RemoveMsg(&SkypeMsgs, ptr); + LOG(("1) InterlockedDecrement ((long *)&receivers); // receivers--; + if (receivers>1) {LOG (("SkypeRcv: %d receivers still waiting", receivers));} + + } while(dwWaitStat == WAIT_OBJECT_0 && !MirandaShuttingDown); + InterlockedDecrement ((long *)&receivers); + LOG(("message, what)); + pCurMsg = ptr->message; + bIsError = FALSE; + if (*what && !strncmp(pCurMsg, what, iLenWhat)) { + // Now we received a MESSAGE with an identifier. So this one is definitely for us + // However the status can be SENDING instead of SENT and next message with this number + // isn't using the ID anymore, so we have to save the ID as new identifier for message recognition + pCurMsg+=iLenWhat; + if ((pMsg = strchr (pCurMsg, ' ')) && (pMsg=strchr (pMsg+1, ' '))) + strncpy (msgid, pCurMsg, pMsg-pCurMsg); + else if (strncmp (pCurMsg, "ERROR", 5) == 0) bIsError = TRUE; + } + + if ((*msgid && strncmp (pCurMsg, msgid, strlen(msgid)) == 0) || + (!*what && ptr->tReceived >= st && + (strncmp(pCurMsg, "MESSAGE", 7) == 0 || strncmp(pCurMsg, "CHATMESSAGE", 11) == 0 ) + ) || bIsError || + (ptr->tReceived >= st && ptr->tReceived <=st+1 && + (bIsError=(strncmp(pCurMsg, "ERROR 26", 8)==0 || strncmp(pCurMsg, "ERROR 43", 8)==0)) + ) ) + { + bProcess = bIsError; + if (!bIsError) { + if ((pMsg = strchr (pCurMsg, ' ')) && (pMsg=strchr (pMsg+1, ' '))) { + pMsg++; + if (strncmp (pMsg, "STATUS ", 7) == 0) { + pMsg+=7; + if (strcmp (pMsg, "SENDING") == 0) { + // Remove dat shit + struct MsgQueue *ptr_=ptr->l.tqe_next; + + free(MsgQ_RemoveMsg(&SkypeMsgs, ptr)); + ptr=ptr_; + continue; + } + bProcess = (strcmp (pMsg, "SENT") == 0 || strcmp (pMsg, "QUEUED") == 0 || + strcmp (pMsg, "FAILED") == 0 || strcmp (pMsg, "IGNORED") == 0 || + strcmp (pMsg, "SENDING") == 0); + } + } + } + if (bProcess) { + msg=MsgQ_RemoveMsg(&SkypeMsgs, ptr); + LOG(("l.tqe_next; + } + LeaveCriticalSection(&SkypeMsgs.cs); + InterlockedIncrement ((long *)&receivers); //receivers++; + dwWaitStat = WaitForSingleObject(SkypeMsgReceived, maxwait); + if (receivers>1) InterlockedDecrement ((long *)&receivers); // receivers--; + if (receivers>1) {LOG (("SkypeRcvMsg: %d receivers still waiting", receivers));} + + } while(dwWaitStat == WAIT_OBJECT_0 && !MirandaShuttingDown); + InterlockedDecrement ((long *)&receivers); + LOG((" Answer %s", str, ptr)); + return ptr; +} + +char *SkypeGetID(char *szWhat, char *szWho, char *szProperty) { + char szID[16]={0}; + static DWORD dwId = 0; + + if (protocol>=4 || bIsImoproxy) sprintf (szID, "#G%d ", dwId++); + return __SkypeGet (szID, szWhat, szWho, szProperty); +} + +char *SkypeGet(char *szWhat, char *szWho, char *szProperty) { + return __SkypeGet ("", szWhat, szWho, szProperty); +} + +#ifdef _UNICODE +WCHAR *SkypeGetW(char *szWhat, WCHAR *szWho, char *szProperty) { + char *ptszWho = (char*)make_utf8_string(szWho); + char *pRet = SkypeGet (szWhat, ptszWho, szProperty); + free (ptszWho); + if (pRet) { + WCHAR *ptr = make_unicode_string((const unsigned char*)pRet); + free (pRet); + return ptr; + } + return NULL; +} +#endif + +char *SkypeGetErr(char *szWhat, char *szWho, char *szProperty) { + char *ret = SkypeGet(szWhat, szWho, szProperty); + if (ret && !strncmp(ret, "ERROR", 5)) { + free (ret); + return NULL; + } + return ret; +} + +#ifdef _UNICODE +WCHAR *SkypeGetErrW(char *szWhat, TCHAR *szWho, char *szProperty) { + WCHAR *ret = SkypeGetW(szWhat, szWho, szProperty); + if (ret && !_tcsncmp(ret, _T("ERROR"), 5)) { + free (ret); + return NULL; + } + return ret; +} +#endif + + +/* SkypeGetProfile + * + * Issues a SET PROFILE szProperty szValue and waits until the answer is received + * Returns the answer or NULL on failure + * BEWARE: Don't forget to free() return value! + * + * For example: SkypeGetProfile("FULLNAME", "Tweety"); +*/ +char *SkypeGetProfile(char *szProperty) { + return SkypeGet ("PROFILE", "", szProperty); +} + +/* SkypeSetProfile + * + * +*/ +int SkypeSetProfile(char *szProperty, char *szValue) { + return SkypeSend("SET PROFILE %s %s", szProperty, szValue); +} + +/* SkypeMsgCollectGarbage + * + * Purpose: Runs the garbage collector on the Skype Message-Queue to throw out old + * messages which may unnecessarily eat up memory. + * Params : age - Time in seconds. Messages older than this value will be + * thrown out. + * Returns: 0 - No messages were thrown out + * >0 - n messages were thrown out + */ +int SkypeMsgCollectGarbage(time_t age) { + return MsgQ_CollectGarbage(&SkypeMsgs, age); +} + + +/* SkypeCall + * + * Purpose: Give a Skype call to the given User in wParam + * or hangs up existing call + * (hangUp is moved over to SkypeCallHangup) + * Params : wParam - Handle to the User to be called + * lParam - Can be NULL + * Returns: 0 - Success + * -1 - Failure + */ +INT_PTR SkypeCall(WPARAM wParam, LPARAM lParam) { + DBVARIANT dbv; + char *msg=0; + int res; + + if (!db_get_s((MCONTACT)wParam, SKYPE_PROTONAME, "CallId", &dbv)) { + res = -1; // no direct return, because dbv needs to be freed + } else { + if (db_get_s((MCONTACT)wParam, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) return -1; + msg=(char *)malloc(strlen(dbv.pszVal)+6); + strcpy(msg, "CALL "); + strcat(msg, dbv.pszVal); + res=SkypeSend(msg); + } + db_free(&dbv); + free(msg); + return res; +} + +/* SkypeCallHangup + * + * Prupose: Hangs up the existing call to the given User + * in wParam. + * + * Params : wParam - Handle to the User to be called + * lParam - Can be NULL + * + * Returns: 0 - Success + * -1 - Failure + * + */ +INT_PTR SkypeCallHangup(WPARAM wParam, LPARAM lParam) +{ + DBVARIANT dbv; + char *msg=0; + int res = -1; + + if (!db_get_s((MCONTACT)wParam, SKYPE_PROTONAME, "CallId", &dbv)) { + msg=(char *)malloc(strlen(dbv.pszVal)+21); + sprintf(msg, "SET %s STATUS FINISHED", dbv.pszVal); + //sprintf(msg, "ALTER CALL %s HANGUP", dbv.pszVal); + res=SkypeSend(msg); +#if _DEBUG + db_unset((MCONTACT)wParam, SKYPE_PROTONAME, "CallId"); +#endif + //} else { + // if (db_get((HANDLE)wParam, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) return -1; + // msg=(char *)malloc(strlen(dbv.pszVal)+6); + // strcpy(msg, "CALL "); + // strcat(msg, dbv.pszVal); + // res=SkypeSend(msg); + } + db_free(&dbv); + free(msg); + return res; +} + +/* FixNumber + * + * Purpose: Eliminates all non-numeric chars from the given phonenumber + * Params : p - Pointer to the buffer with the number + */ +static void FixNumber(char *p) { + unsigned int i; + + for (i=0;i<=strlen(p);i++) + if ((p[i]<'0' || p[i]>'9')) + if (p[i]) { + memmove(p+i, p+i+1, strlen(p+i)); + i--; + } else break; +} + + +/* DialDlgProc + * + * Purpose: Dialog procedure for the Dial-Dialog + */ +static INT_PTR CALLBACK DialDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + static MCONTACT hContact; + static unsigned int entries=0; + BOOL TempAdded=FALSE; + char number[64], *msg, *ptr=NULL; + + switch (uMsg){ + case WM_INITDIALOG: + hContact=(MCONTACT)lParam; + Utils_RestoreWindowPosition(hwndDlg, NULL, SKYPE_PROTONAME, "DIALdlg"); + TranslateDialogDefault(hwndDlg); + + if (lParam) { + DBVARIANT dbv; + BOOL bDialNow=TRUE; + + if (!db_get(hContact,"UserInfo","MyPhone1",&dbv)) { + int j; + char idstr[16]; + + // Multiple phone numbers, select one + bDialNow=FALSE; + db_free(&dbv); + for(j=0;;j++) { + sprintf(idstr,"MyPhone%d",j); + if(db_get_s(hContact,"UserInfo",idstr,&dbv)) break; + FixNumber(dbv.pszVal+1); // Leave + alone + SendDlgItemMessage(hwndDlg,IDC_NUMBER,CB_ADDSTRING,0,(LPARAM)dbv.pszVal); + db_free(&dbv); + } + } + if (db_get_s(hContact,SKYPE_PROTONAME,"SkypeOutNr",&dbv)) { + db_get_s(hContact,"UserInfo","MyPhone0",&dbv); + FixNumber(dbv.pszVal+1); + } + SetDlgItemTextA(hwndDlg, IDC_NUMBER, dbv.pszVal); + db_free(&dbv); + if (bDialNow) PostMessage(hwndDlg, WM_COMMAND, IDDIAL, 0); + } else { + DBVARIANT dbv; + char number[64]; + + for (entries=0;entriesMAX_ENTRIES) entries=MAX_ENTRIES; + for (i=entries;i>0;i--) { + sprintf(buf, "LastNumber%d", i-1); + if (!db_get_s(NULL, SKYPE_PROTONAME, buf, &dbv)) { + sprintf(buf, "LastNumber%d", i); + db_set_s(NULL, SKYPE_PROTONAME, buf, dbv.pszVal); + db_free(&dbv); + } else break; + } + db_set_s(NULL, SKYPE_PROTONAME, "LastNumber0", number); + } + TempAdded=TRUE; + } + if (!db_set_s(hContact, SKYPE_PROTONAME, "SkypeOutNr", number)) { + msg=(char *)malloc(strlen(number)+6); + strcpy(msg, "CALL "); + strcat(msg, number); + if (SkypeSend(msg) || (ptr=SkypeRcv("ERROR", 500))) { + db_unset(hContact, SKYPE_PROTONAME, "SkypeOutNr"); + if (ptr) { + OUTPUTA(ptr); + free(ptr); + } + if (TempAdded) CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0); + } + free(msg); + } + case IDCANCEL: + DestroyWindow(hwndDlg); + break; + } + break; + case WM_DESTROY: + Utils_SaveWindowPosition(hwndDlg, NULL, SKYPE_PROTONAME, "DIALdlg"); + if (httbButton) CallService(MS_TTB_SETBUTTONSTATE, (WPARAM)httbButton, TTBST_RELEASED); + break; + } + return FALSE; +} + +/* CallstatDlgProc + * + * Purpose: Dialog procedure for the CallStatus Dialog + */ +static INT_PTR CALLBACK CallstatDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + static int selected; + static DBVARIANT dbv, dbv2={0}; + + switch (uMsg){ + case WM_INITDIALOG: + { + MCONTACT hContact; + + if (!db_get_s((MCONTACT)lParam, SKYPE_PROTONAME, "CallId", &dbv)) { + + // Check, if another call is in progress + for (hContact=db_find_first();hContact != NULL;hContact=db_find_next(hContact)) { + char *szProto = (char*)CallService( MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0 ); + if (szProto != NULL && !strcmp(szProto, SKYPE_PROTONAME) && hContact != (MCONTACT)lParam && + db_get_b(hContact, SKYPE_PROTONAME, "ChatRoom", 0) == 0 && + !db_get_s(hContact, SKYPE_PROTONAME, "CallId", &dbv2)) + { + if (db_get_b(hContact, SKYPE_PROTONAME, "OnHold", 0)) { + db_free(&dbv2); + continue; + } else break; + } + } + + if (dbv2.pszVal) + { + char buf[256], buf2[256]; + char *szOtherCaller=(char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact,0); + + Utils_RestoreWindowPosition(hwndDlg, NULL, SKYPE_PROTONAME, "CALLSTATdlg"); + TranslateDialogDefault(hwndDlg); + SendMessage(hwndDlg, WM_COMMAND, IDC_JOIN, 0); + + GetWindowTextA(hwndDlg, buf, sizeof(buf)); + _snprintf(buf2, sizeof(buf), buf, CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)lParam,0)); + SetWindowTextA(hwndDlg, buf2); + + GetDlgItemTextA(hwndDlg, IDC_JOIN, buf, sizeof(buf)); + _snprintf(buf2, sizeof(buf), buf, szOtherCaller); + SetDlgItemTextA(hwndDlg, IDC_JOIN, buf2); + + GetDlgItemTextA(hwndDlg, IDC_HOLD, buf, sizeof(buf)); + _snprintf(buf2, sizeof(buf), buf, szOtherCaller); + SetDlgItemTextA(hwndDlg, IDC_HOLD, buf2); + + return TRUE; + } + + // No other call in progress, no need for this Dlg., just answer the call + SkypeSend("SET %s STATUS INPROGRESS", dbv.pszVal); + testfor ("ERROR", 200); + db_free(&dbv); + } + DestroyWindow(hwndDlg); + break; + } + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_JOIN: + case IDC_HOLD: + case IDC_HANGUP: + CheckRadioButton(hwndDlg, IDC_JOIN, IDC_HANGUP, (selected=LOWORD(wParam))); + break; + case IDOK: + { + char *szIdCall2; + + switch (selected) { + case IDC_JOIN: + if (szIdCall2=strchr(dbv2.pszVal, ' ')) + SkypeSend("SET %s JOIN_CONFERENCE%s", dbv.pszVal, szIdCall2); + break; + case IDC_HOLD: + SkypeSend("SET %s STATUS ONHOLD", dbv2.pszVal); + SkypeSend("SET %s STATUS INPROGRESS", dbv.pszVal); + break; + case IDC_HANGUP: + SkypeSend("SET %s STATUS FINISHED", dbv.pszVal); + break; + } + + db_free(&dbv); + db_free(&dbv2); + DestroyWindow(hwndDlg); + break; + } + } + break; + case WM_DESTROY: + Utils_SaveWindowPosition(hwndDlg, NULL, SKYPE_PROTONAME, "CALLSTATdlg"); + break; + } + return FALSE; +} + + +/* SkypeOutCallErrorCheck + * + * Purpose: Checks, if an error has occured after call and + * if so, hangs up the call + * This procedure is a seperate thread to not block the core + * while waiting for "ERROR" + * Params : szCallId - ID of the call + */ +void SkypeOutCallErrorCheck(char *szCallId) { + if (testfor("ERROR", 500)) EndCallThread(szCallId); +} + +/* SkypeOutCall + * + * Purpose: Give a SkypeOut call to the given User in wParam + * or hangs up existing call + * The user's record is searched for Phone-number entries. + * If there is more than 1 entry, the Dial-Dialog is shown + * Params : wParam - Handle to the User to be called + * If NULL, the dial-dialog is shown + * Returns: 0 - Success + * -1 - Failure + */ +INT_PTR SkypeOutCall(WPARAM wParam, LPARAM lParam) { + DBVARIANT dbv; + int res = -1; + + if (wParam && !db_get_s((MCONTACT)wParam, SKYPE_PROTONAME, "CallId", &dbv)) { + res=SkypeSend("SET %s STATUS FINISHED", dbv.pszVal); + pthread_create(( pThreadFunc )SkypeOutCallErrorCheck, _strdup(dbv.pszVal)); + db_free(&dbv); + } else if (!CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_DIAL), NULL, DialDlgProc, (LPARAM)wParam)) return -1; + return res; +} + +/* SkypeHoldCall + * + * Purpose: Put the call to the User given in wParam on Hold or Resumes it + * Params : wParam - Handle to the User + * Returns: 0 - Success + * -1 - Failure + */ +INT_PTR SkypeHoldCall(WPARAM wParam, LPARAM lParam) { + DBVARIANT dbv; + int retval; + + LOG(("SkypeHoldCall started")); + if (!wParam || db_get_s((MCONTACT)wParam, SKYPE_PROTONAME, "CallId", &dbv)) + return -1; + retval = SkypeSend ("SET %s STATUS %s", dbv.pszVal, + db_get_b((MCONTACT)wParam, SKYPE_PROTONAME, "OnHold", 0)?"INPROGRESS":"ONHOLD"); + db_free(&dbv); + return retval; +} + +/* SkypeAnswerCall + * + * Purpose: Answer a Skype-call when a user double-clicks on + * The incoming-call-Symbol. Works for both, Skype and SkypeOut-calls + * Params : wParam - Not used + * lParam - CLISTEVENT* + * Returns: 0 - Success + * -1 - Failure + */ +INT_PTR SkypeAnswerCall(WPARAM wParam, LPARAM lParam) { + + LOG(("SkypeAnswerCall started")); + CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_CALLSTAT), NULL, CallstatDlgProc, (LPARAM)((CLISTEVENT*)lParam)->hContact); + return 0; +} +/* SkypeSetNick + * + * Purpose: Set Full Name in profile + * Params : wParam=0 + * lParam=(LPARAM)(const char*)Nick text + * Returns: 0 - Success + * -1 - Failure + */ +INT_PTR SkypeSetNick(WPARAM wParam, LPARAM lParam) { + int retval = -1; + char *Nick = NULL; + + if (wParam & SMNN_UNICODE) + { + db_set_ws(0, SKYPE_PROTONAME, "Nick", (WCHAR*)lParam); + if (AttachStatus == SKYPECONTROLAPI_ATTACH_SUCCESS && + !(Nick = (char*)make_utf8_string((WCHAR*)lParam))) return -1; + } + else + { + db_set_s(0, SKYPE_PROTONAME, "Nick", (char*)lParam); + if(AttachStatus == SKYPECONTROLAPI_ATTACH_SUCCESS && + utf8_encode((const char *)lParam, &Nick) == -1 ) return -1; + } + if(AttachStatus == SKYPECONTROLAPI_ATTACH_SUCCESS) + retval = SkypeSend("SET PROFILE FULLNAME %s", Nick); + if (Nick) free (Nick); + + return retval; + +} +/* SkypeSetAwayMessage + * + * Purpose: Set Mood message in profile + * Params : wParam=status mode + * lParam=(LPARAM)(const char*)message text + * Returns: 0 - Success + * -1 - Failure + */ +INT_PTR SkypeSetAwayMessage(WPARAM wParam, LPARAM lParam) { + int retval = -1; + char *Mood = NULL; + + if (!lParam) lParam=(LPARAM)""; + if(utf8_encode((const char *)lParam, &Mood) == -1 ) return -1; + db_set_s(NULL, SKYPE_PROTONAME, "MoodText", (const char *)lParam); + + if(AttachStatus == SKYPECONTROLAPI_ATTACH_SUCCESS) + retval = SkypeSend("SET PROFILE MOOD_TEXT %s", Mood); + free (Mood); + + return retval; +} +INT_PTR SkypeSetAwayMessageW(WPARAM wParam, LPARAM lParam) { + int retval = -1; + char *Mood = NULL; + + if (!lParam) lParam=(LPARAM)""; + if (!(Mood = (char*)make_utf8_string((WCHAR*)lParam))) return -1; + db_set_ws(NULL, SKYPE_PROTONAME, "MoodText", (WCHAR*)lParam); + + if(AttachStatus == SKYPECONTROLAPI_ATTACH_SUCCESS) + retval = SkypeSend("SET PROFILE MOOD_TEXT %s", Mood); + free (Mood); + + return retval; +} + +/* SkypeSetAvatar + * + * Purpose: Set user avatar in profile + * Params : wParam=0 + * lParam=(LPARAM)(const char*)filename + * Returns: 0 - Success + * -1 - Failure + */ +INT_PTR SkypeSetAvatar(WPARAM wParam, LPARAM lParam) { + char *filename = (char *) lParam, *ext; + char AvatarFile[MAX_PATH+1], OldAvatarFile[1024]; + char *ptr = NULL; + int ret; + char command[500]; + DBVARIANT dbv = {0}; + BOOL hasOldAvatar = (db_get_s(NULL, SKYPE_PROTONAME, "AvatarFile", &dbv) == 0 && dbv.type == DBVT_ASCIIZ); + size_t len; + + if (AttachStatus != SKYPECONTROLAPI_ATTACH_SUCCESS) + return -3; + + if (filename == NULL) + return -1; + len = strlen(filename); + if (len < 4) + return -1; + + ext = &filename[len-4]; + if (_stricmp(ext, ".jpg")==0 || _stricmp(ext-1, ".jpeg")==0) + ext = "jpg"; + else if (_stricmp(ext, ".png")==0) + ext = "png"; + else + return -2; + + FoldersGetCustomPath(hProtocolAvatarsFolder, AvatarFile, sizeof(AvatarFile), DefaultAvatarsFolder); + if (!*AvatarFile) strcpy (AvatarFile, DefaultAvatarsFolder); + mir_snprintf(AvatarFile, sizeof(AvatarFile), "%s\\%s avatar.%s", AvatarFile, SKYPE_PROTONAME, ext); + + // Backup old file + if (hasOldAvatar) + { + strncpy(OldAvatarFile, dbv.pszVal, sizeof(OldAvatarFile)-4); + OldAvatarFile[sizeof(OldAvatarFile)-5] = '\0'; + strcat(OldAvatarFile, "_old"); + DeleteFileA(OldAvatarFile); + if (!MoveFileA(dbv.pszVal, OldAvatarFile)) + { + db_free(&dbv); + return -3; + } + } + + // Copy new file + if (!CopyFileA(filename, AvatarFile, FALSE)) + { + if (hasOldAvatar) + { + MoveFileA(OldAvatarFile, dbv.pszVal); + db_free(&dbv); + } + return -3; + } + + // Try to set with skype + mir_snprintf(command, sizeof(command), "SET AVATAR 1 %s", AvatarFile); + if (SkypeSend(command) || (ptr = SkypeRcv(command+4, INFINITE)) == NULL || !strncmp(ptr, "ERROR", 5)) + { + DeleteFileA(AvatarFile); + + if (hasOldAvatar) + MoveFileA(OldAvatarFile, dbv.pszVal); + + ret = -4; + } + else + { + if (hasOldAvatar) + DeleteFileA(OldAvatarFile); + + db_set_s(NULL, SKYPE_PROTONAME, "AvatarFile", AvatarFile); + + ret = 0; + } + + if (ptr != NULL) + free(ptr); + + if (hasOldAvatar) + db_free(&dbv); + + return ret; +} + + +/* SkypeSendFile + * + * Purpose: Opens the Skype-dialog to send a file + * Params : wParam - Handle to the User + * lParam - Not used + * Returns: 0 - Success + * -1 - Failure + */ +INT_PTR SkypeSendFile(WPARAM wParam, LPARAM lParam) { + DBVARIANT dbv; + int retval; + + if (!wParam || db_get_s((MCONTACT)wParam, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) + return -1; + retval=SkypeSend("OPEN FILETRANSFER %s", dbv.pszVal); + db_free(&dbv); + return retval; +} + +/* SkypeChatCreate + * + * Purpose: Creates a groupchat with the user + * Params : wParam - Handle to the User + * lParam - Not used + * Returns: 0 - Success + * -1 - Failure + */ +INT_PTR SkypeChatCreate(WPARAM wParam, LPARAM lParam) { + DBVARIANT dbv; + MCONTACT hContact=(MCONTACT)wParam; + char *ptr, *ptr2; + + if (!hContact || db_get_s(hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) + return -1; + // Flush old messages + while (testfor("\0CHAT \0 STATUS \0", 0)); + if (SkypeSend("CHAT CREATE %s", dbv.pszVal) || !(ptr=SkypeRcv ("\0CHAT \0 STATUS \0", INFINITE))) + { + db_free(&dbv); + return -1; + } + db_free(&dbv); + if (ptr2=strstr (ptr, "STATUS")) { + *(ptr2-1)=0; + ChatStart (ptr+5, FALSE); + } + free(ptr); + return 0; +} + +/* SkypeAdduserDlg + * + * Purpose: Show Skype's Add user Dialog + */ +INT_PTR SkypeAdduserDlg(WPARAM wParam, LPARAM lParam) { + SkypeSend("OPEN ADDAFRIEND"); + return 0; +} + +/* SkypeFlush + * + * Purpose: Flush the Skype Message-List + */ +void SkypeFlush(void) { + char *ptr; + + while ((ptr=SkypeRcv(NULL, 0))!=NULL) free(ptr); +} + +/* SkypeStatusToMiranda + * + * Purpose: Converts the specified Skype-Status mode to the corresponding Miranda-Status mode + * Params : s - Skype Status + * Returns: The correct Status + * 0 - Nothing found + */ +int SkypeStatusToMiranda(char *s) { + int i; + if (!strcmp("SKYPEOUT", s)) return db_get_dw(NULL, SKYPE_PROTONAME, "SkypeOutStatusMode", ID_STATUS_ONTHEPHONE); + for(i=0; status_codes[i].szStat; i++) + if (!strcmp(status_codes[i].szStat, s)) + return status_codes[i].id; + return 0; +} + +/* MirandaStatusToSkype + * + * Purpose: Converts the specified Miranda-Status mode to the corresponding Skype-Status mode + * Params : id - Miranda Status + * Returns: The correct Status + * NULL - Nothing found + */ +char *MirandaStatusToSkype(int id) { + int i; + if (db_get_b(NULL, SKYPE_PROTONAME, "NoSkype3Stats", 0)) { + switch (id) + { + case ID_STATUS_NA: return "AWAY"; + case ID_STATUS_FREECHAT: return "ONLINE"; + } + } + for(i=0; status_codes[i].szStat; i++) + if (status_codes[i].id==id) + return status_codes[i].szStat; + return NULL; +} + +/* GetSkypeErrorMsg + * + * Purpose: Get a human-readable Error-Message for the supplied Skype Error-Message + * Params : str - Skype Error-Message string + * Returns: Human-readable Error Message or NULL, if nothing was found + * Warning: Don't forget to free() return value + */ +char *GetSkypeErrorMsg(char *str) { + char *pos, *reason, *msg; + + LOG (("GetSkypeErrorMsg received error: %s", str)); + if (!strncmp(str, "ERROR", 5)) { + reason=_strdup(str); + return reason; + } + if ((pos=strstr(str, "FAILURE")) ) { + switch(atoi(pos+14)) { + case MISC_ERROR: msg="Misc. Error"; break; + case USER_NOT_FOUND: msg="User does not exist, check username"; break; + case USER_NOT_ONLINE: msg="Trying to send IM to an user, who is not online"; break; + case USER_BLOCKED: msg="IM blocked by recipient"; break; + case TYPE_UNSUPPORTED: msg="Type unsupported"; break; + case SENDER_NOT_FRIEND: msg="Sending IM message to user, who has not added you to friendslist and has chosen 'only people in my friendslist can start IM'"; break; + case SENDER_NOT_AUTHORIZED: msg="Sending IM message to user, who has not authorized you and has chosen 'only people whom I have authorized can start IM'"; break; + default: msg="Unknown error"; + } + reason=(char *)malloc(strlen(pos)+strlen(msg)+3); + sprintf (reason, "%s: %s", pos, msg); + return reason; + } + return NULL; +} + +/* testfor + * + * Purpose: Wait, until the given Message-Fragment is received from Skype within + * the given amount of time + * Params : see SkypeRcv + * Returns: TRUE - Message was received within the given amount of time + * FALSE- nope, sorry + */ +BOOL testfor(char *what, DWORD maxwait) { + char *res; + + if ((res=SkypeRcv(what, maxwait))==NULL) return FALSE; + free(res); + return TRUE; +} + +char SendSkypeproxyCommand(char command) { + int length=0; + char reply=0; + BOOL res; + + res = send(ClientSocket, (char *)&length, sizeof(length), 0)==SOCKET_ERROR + || send(ClientSocket, (char *)&command, sizeof(command), 0)==SOCKET_ERROR + || recv(ClientSocket, (char *)&reply, sizeof(reply), 0)==SOCKET_ERROR; + if (res) + return -1; + else + return reply; +} + +/* ConnectToSkypeAPI + * + * Purpose: Establish a connection to the Skype API + * Params : path - Path to the Skype application + * iStart - Need to start skype for status change. + * 1 = Normal start if Skype not running + * 2 = Forced startp code execution no matter what + * Returns: 0 - Connecting succeeded + * -1 - Something went wrong + */ +int ConnectToSkypeAPI(char *path, int iStart) { + static int iRet = -1; // last request result + static volatile long newRequest = TRUE; + + InterlockedExchange(&newRequest, TRUE); // place new request + EnterCriticalSection(&ConnectMutex); // Prevent reentrance + if (iRet == -1 || newRequest) + { + iRet = _ConnectToSkypeAPI(path, iStart); + InterlockedExchange(&newRequest, FALSE); // every thread which is waiting for connect mutex will get our result as well.. but subsequent calls will set this value to true and call _Connect again + } + LeaveCriticalSection(&ConnectMutex); + return iRet; +} + +void TranslateMirandaRelativePathToAbsolute(LPCSTR cszPath, LPSTR szAbsolutePath, BOOL fQuoteSpaces) { + *szAbsolutePath = 0; + CallService (MS_UTILS_PATHTOABSOLUTE, (WPARAM)(*cszPath ? cszPath : ".\\"), (LPARAM)szAbsolutePath); + if(fQuoteSpaces && strchr((LPCSTR)szAbsolutePath, ' ')){ + memmove (szAbsolutePath+1, szAbsolutePath, strlen(szAbsolutePath)+1); + *szAbsolutePath='"'; + strcat (szAbsolutePath, "\""); + } + + TRACEA(szAbsolutePath); +} + +static int my_spawnv(const char *cmdname, const char *const *argv, PROCESS_INFORMATION *pi) +{ + int i, iLen=0; + char *CommandLine; + STARTUPINFOA si={0}; + BOOL bRet; + + memset (pi, 0, sizeof(PROCESS_INFORMATION)); + for (i=0; argv[i]; i++) + iLen += (int)strlen(argv[i])+1; + if (!(CommandLine = (char*)calloc(1, iLen))) return -1; + for (i=0; argv[i]; i++) { + if (i) strcat (CommandLine, " "); + strcat (CommandLine, argv[i]); + } + si.cb = sizeof(si); + + bRet = CreateProcessA( cmdname,CommandLine,NULL,NULL,FALSE,0,NULL,NULL,&si,pi); + free(CommandLine); + if (!bRet) return -1; + return (DWORD)pi->hProcess; +} + +static int _ConnectToSkypeAPI(char *path, int iStart) { + BOOL SkypeLaunched=FALSE; + BOOL UseCustomCommand = db_get_b(NULL, SKYPE_PROTONAME, "UseCustomCommand", 0); + int counter=0, i, j, maxattempts=db_get_w(NULL, SKYPE_PROTONAME, "ConnectionAttempts", 10); + char *args[16], *pFree = NULL; + char *SkypeOptions[]={"/notray", "/nosplash", "/minimized", "/removable", "/datapath:", "/secondary"}; + const int SkypeDefaults[]={0, 1, 1, 0, 0}; + + char szAbsolutePath[MAX_PATH]; + + LOG(("ConnectToSkypeAPI started.")); + if (UseSockets) + { + SOCKADDR_IN service; + DBVARIANT dbv; + long inet; + struct hostent *hp; + + LOG(("ConnectToSkypeAPI: Connecting to Skype2socket socket...")); + if ((ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))==INVALID_SOCKET) return -1; + + if (!db_get_s(NULL, SKYPE_PROTONAME, "Host", &dbv)) { + if ((inet=inet_addr(dbv.pszVal))==-1) { + if (hp=gethostbyname(dbv.pszVal)) + memcpy(&inet, hp->h_addr, sizeof(inet)); + else { + OUTPUT(_T("Cannot resolve host!")); + db_free(&dbv); + return -1; + } + } + db_free(&dbv); + } else { + OUTPUT(_T("Cannot find valid host to connect to.")); + return -1; + } + + service.sin_family = AF_INET; + service.sin_addr.s_addr = inet; + service.sin_port = htons((unsigned short)db_get_w(NULL, SKYPE_PROTONAME, "Port", 1401)); + + if ( connect( ClientSocket, (SOCKADDR*) &service, sizeof(service) ) == SOCKET_ERROR) return -1; + + if (db_get_b(NULL, SKYPE_PROTONAME, "RequiresPassword", 0) && !db_get_s(NULL, SKYPE_PROTONAME, "Password", &dbv)) + { + char reply=0; + + if ((reply=SendSkypeproxyCommand(AUTHENTICATE))==-1) { + db_free(&dbv); + return -1; + } + if (!reply) { + OUTPUT(_T("Authentication is not supported/needed for this Skype proxy server. It will be disabled.")); + db_set_b(NULL, SKYPE_PROTONAME, "RequiresPassword", 0); + } else { + unsigned int length=(unsigned int)strlen(dbv.pszVal); + BOOL res; + res = send(ClientSocket, (char *)&length, sizeof(length), 0)==SOCKET_ERROR + || send(ClientSocket, dbv.pszVal, length, 0)==SOCKET_ERROR + || recv(ClientSocket, (char *)&reply, sizeof(reply), 0)==SOCKET_ERROR; + if (res) + { + db_free(&dbv); + return -1; + } + if (!reply) + { + OUTPUT(_T("Authentication failed for this server, connection was not successful. Verify that your password is correct!")); + db_free(&dbv); + return -1; + } + } + db_free(&dbv); + } + else + { + char reply=0; + + if ((reply=SendSkypeproxyCommand(CAPABILITIES))==-1) return -1; + if (reply&USE_AUTHENTICATION) { + OUTPUT(_T("The server you specified requires authentication, but you have not supplied a password for it. Check the Skype plugin settings and try again.")); + return -1; + } + } + + + if (!rcvThreadRunning) + if(_beginthread(( pThreadFunc )rcvThread, 0, NULL)==-1) return -1; + + AttachStatus=SKYPECONTROLAPI_ATTACH_SUCCESS; + return 0; + } + + if (pszProxyCallout) + { + if (SkypeSend("SET USERSTATUS ONLINE")==-1) + { + AttachStatus=SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE; + return -1; + } + for ( ;; ) { + char *ptr = SkypeRcv ("CONNSTATUS", INFINITE); + if (!ptr) + { + AttachStatus=SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE; + return -1; + } + + if (strcmp (ptr+11, "CONNECTING")) + { + free (ptr); + break; + } + free (ptr); + } + + AttachStatus=SKYPECONTROLAPI_ATTACH_SUCCESS; + return 0; + } + + do + { + int retval; + /* To initiate communication, Client should broadcast windows message + ('SkypeControlAPIDiscover') to all windows in the system, specifying its own + window handle in wParam parameter. + */ + if (iStart != 2 || counter) + { + LOG(("ConnectToSkypeAPI sending discover message.. hWnd=%08X", (long)g_hWnd)); + retval = (int)SendMessageTimeout(HWND_BROADCAST, ControlAPIDiscover, (WPARAM)g_hWnd, 0, SMTO_ABORTIFHUNG, 3000, NULL); + LOG(("ConnectToSkypeAPI sent discover message returning %d", retval)); + } + + /* In response, Skype responds with + message 'SkypeControlAPIAttach' to the handle specified, and indicates + connection status + SkypeReady is set if there is an answer by Skype other than API_AVAILABLE. + If there is no answer after 3 seconds, launch Skype as it's propably + not running. + */ + if (iStart == 2 || (WaitForSingleObject(SkypeReady, 3000)==WAIT_TIMEOUT && AttachStatus!=SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION)) + { + if (iStart != 2 && g_hWnd==NULL) + { + LOG(("ConnectToSkypeAPI: hWnd of SkypeDispatchWindow not yet set..")); + continue; + } + if ((iStart == 2 || !SkypeLaunched) && (path || UseCustomCommand)) + { + static PROCESS_INFORMATION pi={0}; + DWORD dwExitStatus = 0; + + if ((!pi.hProcess || !GetExitCodeProcess(pi.hProcess, &dwExitStatus) || dwExitStatus != STILL_ACTIVE) && + (db_get_b(NULL, SKYPE_PROTONAME, "StartSkype", 1) || iStart)) + { + LOG(("ConnectToSkypeAPI Starting Skype, as it's not running")); + + j=1; + for (i=0; i < SIZEOF(SkypeOptions); i++) + if (db_get_b(NULL, SKYPE_PROTONAME, SkypeOptions[i]+1, SkypeDefaults[i])) { + DBVARIANT dbv; + + switch (i) + { + case 4: + if(!db_get_s(NULL,SKYPE_PROTONAME,"datapath",&dbv)) + { + int paramSize; + TranslateMirandaRelativePathToAbsolute(dbv.pszVal, szAbsolutePath, TRUE); + paramSize = (int)strlen(SkypeOptions[i]) + (int)strlen(szAbsolutePath); + pFree = args[j] = (char*)malloc(paramSize + 1); + sprintf(args[j],"%s%s",SkypeOptions[i],szAbsolutePath); + db_free(&dbv); + } + break; + case 2: + args[j++]="/legacylogin"; + default: + args[j]=SkypeOptions[i]; + break; + } + LOG(("Using Skype parameter: %s", args[j])); + //MessageBox(NULL,"Using Skype parameter: ",args[j],0); + j++; + } + args[j]=NULL; + + if(UseCustomCommand) + { + DBVARIANT dbv; + + if(!db_get_s(NULL,SKYPE_PROTONAME,"CommandLine",&dbv)) + { + TranslateMirandaRelativePathToAbsolute(dbv.pszVal, szAbsolutePath, FALSE); + args[0] = (LPSTR)szAbsolutePath; + LOG(("ConnectToSkypeAPI: Launch skype using command line")); + if (!*szAbsolutePath || my_spawnv(szAbsolutePath, args, &pi) == -1) { + LOG(("ConnectToSkypeAPI: Failed to launch skype!")); + } else { + WaitForInputIdle((HANDLE)pi.hProcess, 5000); + setUserNamePassword(pi.dwProcessId); + } + db_free(&dbv); + } + } + else + { + args[0]=path; + LOG(("ConnectToSkypeAPI: Launch skype")); + /*for(int i=0;i=maxattempts && AttachStatus==-1) + { + int oldstatus=SkypeStatus; + InterlockedExchange((long *)&SkypeStatus, (int)ID_STATUS_OFFLINE); + ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldstatus, SkypeStatus); + OUTPUT(_T("ERROR: Skype not running / too old / working!")); + return -1; + } + } + } + LOG(("Attachstatus %d", AttachStatus)); + } while (AttachStatus==SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE || AttachStatus==SKYPECONTROLAPI_ATTACH_API_AVAILABLE || AttachStatus==-1); + + while (AttachStatus==SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION) Sleep(1000); + LOG(("Attachstatus %d", AttachStatus)); + if (AttachStatus!=SKYPECONTROLAPI_ATTACH_SUCCESS) { + int oldstatus; + + switch(AttachStatus) { + case SKYPECONTROLAPI_ATTACH_REFUSED: + OUTPUT(_T("Skype refused the connection :(")); + break; + case SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE: + OUTPUT(_T("The Skype API is not available")); + break; + default: + LOG(("ERROR: AttachStatus: %d", AttachStatus)); + OUTPUT(_T("Wheee, Skype won't let me use the API. :(")); + } + oldstatus=SkypeStatus; + InterlockedExchange((long *)&SkypeStatus, (int)ID_STATUS_OFFLINE); + ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldstatus, SkypeStatus); + return -1; + } + + return 0; +} + +/* CloseSkypeAPI + * Purpose: Closes existing api connection + * Params: path - Path to the Skype application; could be NULL when using proxy + * Returns: always 0 + */ +int CloseSkypeAPI(char *skypePath) +{ + char szAbsolutePath[MAX_PATH]; + + logoff_contacts(TRUE); + if (UseSockets) + { + if (ClientSocket != INVALID_SOCKET) + { + closesocket(ClientSocket); + ClientSocket = INVALID_SOCKET; + } + } + else { + if (!pszProxyCallout) + { + if (AttachStatus!=-1) + { + // it was crashing when the skype-network-proxy is used (imo2sproxy for imo.im) and skype-path is empty + // now, with the "UseSockets" check and the skypePath[0] != 0 check its fixed + if (skypePath != NULL && skypePath[0] != 0) { + TranslateMirandaRelativePathToAbsolute(skypePath, szAbsolutePath, FALSE); + _spawnl(_P_NOWAIT, szAbsolutePath, szAbsolutePath, "/SHUTDOWN", NULL); + } + } + } + } + SkypeInitialized=FALSE; + ResetEvent(SkypeReady); + AttachStatus=-1; + if (g_hWnd) KillTimer (g_hWnd, 1); + return 0; +} +/* ConnectToSkypeAPI + * + * Purpose: Establish a connection to the Skype API + * Params : path - Path to the Skype application + * Returns: 0 - Connecting succeeded + * -1 - Something went wrong + */ +//int __connectAPI(char *path) { +// int retval; +// +// EnterCriticalSection(&ConnectMutex); +// if (AttachStatus!=-1) { +// LeaveCriticalSection(&ConnectMutex); +// return -1; +// } +// InterlockedExchange((long *)&SkypeStatus, ID_STATUS_CONNECTING); +// ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) ID_STATUS_OFFLINE, SkypeStatus); +// retval=__connectAPI(path); +// if (retval==-1) { +// logoff_contacts(); +// InterlockedExchange((long *)&SkypeStatus, ID_STATUS_OFFLINE); +// ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) ID_STATUS_CONNECTING, SkypeStatus); +// } +// LeaveCriticalSection(&ConnectMutex); +// return retval; +//} diff --git a/protocols/SkypeClassic/src/skypeopt.c b/protocols/SkypeClassic/src/skypeopt.c deleted file mode 100644 index 45020b2f32..0000000000 --- a/protocols/SkypeClassic/src/skypeopt.c +++ /dev/null @@ -1,968 +0,0 @@ -#include "skype.h" -#include "skypeopt.h" -#include "pthread.h" -#include "gchat.h" -#include "skypeprofile.h" -#if(WINVER >= 0x0500) -#include "uxtheme.h" -#define HAVE_UXTHEMES -#endif - -#ifdef SKYPE_AUTO_DETECTION -#include "ezxml/ezxml.c" -#endif - -#ifdef UNICODE -#include "utf8.h" -#endif - -#pragma warning (disable: 4706) // assignment within conditional expression - -// VC6 SDK defines -#ifndef BIF_SHAREABLE -#define BIF_SHAREABLE 0x8000 // sharable resources displayed (remote shares, requires BIF_USENEWUI) -#endif -#ifndef BIF_NEWDIALOGSTYLE -#define BIF_NEWDIALOGSTYLE 0x0040 // Use the new dialog layout with the ability to resize -#endif // Caller needs to call OleInitialize() before using this API -#ifndef BIF_NONEWFOLDERBUTTON -#define BIF_NONEWFOLDERBUTTON 0x0200 // Do not add the "New Folder" button to the dialog. Only applicable with BIF_NEWDIALOGSTYLE. -#endif - - -extern HINSTANCE hInst; -extern char protocol, g_szProtoName[]; -extern BOOL SkypeInitialized, bProtocolSet, bIsImoproxy; -extern DWORD mirandaVersion; - -BOOL showPopup, showPopupErr, popupWindowColor, popupWindowColorErr; -unsigned int popupBackColor, popupBackColorErr; -unsigned int popupTextColor, popupTextColorErr; -int popupTimeSec, popupTimeSecErr; -POPUPDATAT InCallPopup; -POPUPDATAT ErrorPopup; - -static SkypeProfile myProfile; -static HBITMAP hAvatar = NULL; - -extern BOOL PopupServiceExists; -extern BOOL (WINAPI *MyEnableThemeDialogTexture)(HANDLE, DWORD); - -int RegisterOptions(WPARAM wParam, LPARAM lParam) { - OPTIONSDIALOGPAGE odp; - - UNREFERENCED_PARAMETER(lParam); - - ZeroMemory(&odp, sizeof(odp)); - odp.cbSize = sizeof(odp); - odp.hInstance = hInst; - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS); - odp.pszGroup = "Network"; - odp.pszTitle = SKYPE_PROTONAME; - odp.pfnDlgProc = OptionsDlgProc; - odp.flags = ODPF_BOLDGROUPS; - Options_AddPage(wParam, &odp); - - if(PopupServiceExists) - { - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_POPUP); - odp.pszGroup = "Popups"; - odp.pfnDlgProc = OptPopupDlgProc; - Options_AddPage(wParam, &odp); - } - - return 0; -} - -INT_PTR CALLBACK OptPopupDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static RECT r; - - switch ( msg ) - { - case WM_INITDIALOG: - TranslateDialogDefault( hwnd ); - // Message Popup - popupTimeSec = db_get_dw(NULL, SKYPE_PROTONAME, "popupTimeSec", 4); - popupTextColor = db_get_dw(NULL, SKYPE_PROTONAME, "popupTextColor", GetSysColor(COLOR_WINDOWTEXT)); - popupBackColor = db_get_dw(NULL, SKYPE_PROTONAME, "popupBackColor", GetSysColor(COLOR_BTNFACE)); - popupWindowColor = db_get_b(NULL, SKYPE_PROTONAME, "popupWindowColor", FALSE); - showPopup = db_get_b(NULL, SKYPE_PROTONAME, "showPopup", TRUE); - // ERROR Message Popup - popupTimeSecErr = db_get_dw(NULL, SKYPE_PROTONAME, "popupTimeSecErr", 4); - popupTextColorErr = db_get_dw(NULL, SKYPE_PROTONAME, "popupTextColorErr", GetSysColor(COLOR_WINDOWTEXT)); - popupBackColorErr = db_get_dw(NULL, SKYPE_PROTONAME, "popupBackColorErr", GetSysColor(COLOR_BTNFACE)); - popupWindowColorErr = db_get_b(NULL, SKYPE_PROTONAME, "popupWindowColorErr", FALSE); - showPopupErr = db_get_b(NULL, SKYPE_PROTONAME, "showPopupErr", TRUE); - - EnableWindow(GetDlgItem(hwnd,IDC_USEWINCOLORS),showPopup); - EnableWindow(GetDlgItem(hwnd,IDC_POPUPBACKCOLOR),showPopup && ! popupWindowColor); - EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPBACKCOLOR),showPopup && ! popupWindowColor); - EnableWindow(GetDlgItem(hwnd,IDC_POPUPTEXTCOLOR),showPopup && ! popupWindowColor); - EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPTEXTCOLOR),showPopup && ! popupWindowColor); - EnableWindow(GetDlgItem(hwnd,IDC_POPUPTIME),showPopup); - EnableWindow(GetDlgItem(hwnd,IDC_PREVIEW),showPopup); - EnableWindow(GetDlgItem(hwnd,IDC_USEWINCOLORSERR),showPopupErr); - EnableWindow(GetDlgItem(hwnd,IDC_POPUPBACKCOLORERR),showPopupErr && ! popupWindowColorErr); - EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPBACKCOLORERR),showPopupErr && ! popupWindowColorErr); - EnableWindow(GetDlgItem(hwnd,IDC_POPUPTEXTCOLORERR),showPopupErr && ! popupWindowColorErr); - EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPTEXTCOLORERR),showPopupErr && ! popupWindowColorErr); - EnableWindow(GetDlgItem(hwnd,IDC_POPUPTIMEERR),showPopupErr); - EnableWindow(GetDlgItem(hwnd,IDC_PREVIEWERR),showPopupErr); - CheckDlgButton(hwnd, IDC_POPUPINCOMING, (WPARAM) showPopup); - CheckDlgButton(hwnd, IDC_USEWINCOLORS, (WPARAM) popupWindowColor); - CheckDlgButton(hwnd, IDC_POPUPERROR, (WPARAM) showPopupErr); - CheckDlgButton(hwnd, IDC_USEWINCOLORSERR, (WPARAM) popupWindowColorErr); - SendDlgItemMessage(hwnd, IDC_POPUPTIME, EM_SETLIMITTEXT, 3, 0L); - SetDlgItemInt(hwnd, IDC_POPUPTIME, popupTimeSec,FALSE); - SendDlgItemMessage(hwnd, IDC_POPUPTIMEERR, EM_SETLIMITTEXT, 3, 0L); - SetDlgItemInt(hwnd, IDC_POPUPTIMEERR, popupTimeSecErr,FALSE); - SendDlgItemMessage(hwnd, IDC_POPUPBACKCOLOR, CPM_SETCOLOUR,0, popupBackColor); - SendDlgItemMessage(hwnd, IDC_POPUPBACKCOLOR, CPM_SETDEFAULTCOLOUR, 0, GetSysColor(COLOR_BTNFACE)); - SendDlgItemMessage(hwnd, IDC_POPUPTEXTCOLOR, CPM_SETCOLOUR,0, popupTextColor); - SendDlgItemMessage(hwnd, IDC_POPUPTEXTCOLOR, CPM_SETDEFAULTCOLOUR, 0, GetSysColor(COLOR_WINDOWTEXT)); - SendDlgItemMessage(hwnd, IDC_POPUPBACKCOLORERR, CPM_SETCOLOUR,0, popupBackColorErr); - SendDlgItemMessage(hwnd, IDC_POPUPBACKCOLORERR, CPM_SETDEFAULTCOLOUR, 0, GetSysColor(COLOR_BTNFACE)); - SendDlgItemMessage(hwnd, IDC_POPUPTEXTCOLORERR, CPM_SETCOLOUR,0, popupTextColorErr); - SendDlgItemMessage(hwnd, IDC_POPUPTEXTCOLORERR, CPM_SETDEFAULTCOLOUR, 0, GetSysColor(COLOR_WINDOWTEXT)); - - - return TRUE; - break; - - case WM_NOTIFY: - switch(((LPNMHDR)lParam)->idFrom) - { - case 0: - switch (((LPNMHDR)lParam)->code) - { - case PSN_APPLY: - db_set_dw(NULL, SKYPE_PROTONAME, "popupBackColor", popupBackColor); - db_set_dw(NULL, SKYPE_PROTONAME, "popupTextColor", popupTextColor); - db_set_dw(NULL, SKYPE_PROTONAME, "popupTimeSec", popupTimeSec); - db_set_b(NULL, SKYPE_PROTONAME, "popupWindowColor", (BYTE)popupWindowColor); - db_set_b(NULL, SKYPE_PROTONAME, "showPopup", (BYTE)showPopup); - db_set_dw(NULL, SKYPE_PROTONAME, "popupBackColorErr", popupBackColorErr); - db_set_dw(NULL, SKYPE_PROTONAME, "popupTextColorErr", popupTextColorErr); - db_set_dw(NULL, SKYPE_PROTONAME, "popupTimeSecErr", popupTimeSecErr); - db_set_b(NULL, SKYPE_PROTONAME, "popupWindowColorErr", (BYTE)popupWindowColorErr); - db_set_b(NULL, SKYPE_PROTONAME, "showPopupErr", (BYTE)showPopupErr); - break; - } - } - break; - - - - case WM_COMMAND: - switch( LOWORD( wParam )) - { - case IDC_PREVIEW: - { - MCONTACT hContact; - TCHAR * lpzContactName; - - hContact = db_find_first(SKYPE_PROTONAME); - lpzContactName = (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact,GCDNF_TCHAR); - InCallPopup.lchContact = hContact; - InCallPopup.lchIcon = LoadIcon(hInst,MAKEINTRESOURCE(IDI_CALL)); - InCallPopup.colorBack = ! popupWindowColor ? popupBackColor : GetSysColor(COLOR_BTNFACE); - InCallPopup.colorText = ! popupWindowColor ? popupTextColor : GetSysColor(COLOR_WINDOWTEXT); - InCallPopup.iSeconds = popupTimeSec; - InCallPopup.PluginData = (void *)1; - - lstrcpy(InCallPopup.lptzText, TranslateT("Incoming Skype Call")); - - lstrcpy(InCallPopup.lptzContactName, lpzContactName); - - CallService(MS_POPUP_ADDPOPUPT,(WPARAM)&InCallPopup,0); - - - break; - } - case IDC_PREVIEWERR: - ErrorPopup.lchContact = NULL; - ErrorPopup.lchIcon = LoadIcon(hInst,MAKEINTRESOURCE(IDI_CALL)); - ErrorPopup.colorBack = ! popupWindowColorErr ? popupBackColorErr : GetSysColor(COLOR_BTNFACE); - ErrorPopup.colorText = ! popupWindowColorErr ? popupTextColorErr : GetSysColor(COLOR_WINDOWTEXT); - ErrorPopup.iSeconds = popupTimeSecErr; - ErrorPopup.PluginData = (void *)1; - - lstrcpy(ErrorPopup.lptzText, TranslateT("Preview Error Message")); - - lstrcpy(ErrorPopup.lptzContactName, _T("Error Message")); - - - CallService(MS_POPUP_ADDPOPUPT,(WPARAM)&ErrorPopup,0); - - break; - - case IDC_POPUPTIME: - case IDC_POPUPTIMEERR: - { - BOOL Translated; - popupTimeSec = GetDlgItemInt(hwnd,IDC_POPUPTIME,&Translated,FALSE); - popupTimeSecErr = GetDlgItemInt(hwnd,IDC_POPUPTIMEERR,&Translated,FALSE); - SendMessage(GetParent(hwnd),PSM_CHANGED,0,0); - break; - } - case IDC_POPUPTEXTCOLOR: - case IDC_POPUPBACKCOLOR: - case IDC_POPUPTEXTCOLORERR: - case IDC_POPUPBACKCOLORERR: - popupBackColor = (UINT)SendDlgItemMessage(hwnd,IDC_POPUPBACKCOLOR,CPM_GETCOLOUR,0,0); - popupTextColor = (UINT)SendDlgItemMessage(hwnd,IDC_POPUPTEXTCOLOR,CPM_GETCOLOUR,0,0); - popupBackColorErr = (UINT)SendDlgItemMessage(hwnd,IDC_POPUPBACKCOLORERR,CPM_GETCOLOUR,0,0); - popupTextColorErr = (UINT)SendDlgItemMessage(hwnd,IDC_POPUPTEXTCOLORERR,CPM_GETCOLOUR,0,0); - SendMessage(GetParent(hwnd),PSM_CHANGED,0,0); - break; - case IDC_USEWINCOLORS: - popupWindowColor = (IsDlgButtonChecked(hwnd,IDC_USEWINCOLORS)==BST_CHECKED); - EnableWindow(GetDlgItem(hwnd,IDC_POPUPBACKCOLOR), showPopup && ! popupWindowColor); - EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPBACKCOLOR), showPopup && ! popupWindowColor); - EnableWindow(GetDlgItem(hwnd,IDC_POPUPTEXTCOLOR), showPopup && ! popupWindowColor); - EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPTEXTCOLOR), showPopup && ! popupWindowColor); - SendMessage(GetParent(hwnd),PSM_CHANGED,0,0); - break; - case IDC_POPUPINCOMING: - showPopup = (IsDlgButtonChecked(hwnd,IDC_POPUPINCOMING)==BST_CHECKED); - EnableWindow(GetDlgItem(hwnd,IDC_USEWINCOLORS),showPopup); - EnableWindow(GetDlgItem(hwnd,IDC_POPUPBACKCOLOR),showPopup && ! popupWindowColor); - EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPBACKCOLOR),showPopup && ! popupWindowColor); - EnableWindow(GetDlgItem(hwnd,IDC_POPUPTEXTCOLOR),showPopup && ! popupWindowColor); - EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPTEXTCOLOR),showPopup && ! popupWindowColor); - EnableWindow(GetDlgItem(hwnd,IDC_POPUPTIME),showPopup); - EnableWindow(GetDlgItem(hwnd,IDC_PREVIEW),showPopup); - SendMessage(GetParent(hwnd),PSM_CHANGED,0,0); - break; - case IDC_USEWINCOLORSERR: - popupWindowColorErr = (IsDlgButtonChecked(hwnd,IDC_USEWINCOLORSERR)==BST_CHECKED); - EnableWindow(GetDlgItem(hwnd,IDC_POPUPBACKCOLORERR), showPopupErr && ! popupWindowColorErr); - EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPBACKCOLORERR), showPopupErr && ! popupWindowColorErr); - EnableWindow(GetDlgItem(hwnd,IDC_POPUPTEXTCOLORERR), showPopupErr && ! popupWindowColorErr); - EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPTEXTCOLORERR), showPopupErr && ! popupWindowColorErr); - SendMessage(GetParent(hwnd),PSM_CHANGED,0,0); - break; - case IDC_POPUPERROR: - showPopupErr = (IsDlgButtonChecked(hwnd,IDC_POPUPERROR)==BST_CHECKED); - EnableWindow(GetDlgItem(hwnd,IDC_USEWINCOLORSERR),showPopupErr); - EnableWindow(GetDlgItem(hwnd,IDC_POPUPBACKCOLORERR),showPopupErr && ! popupWindowColorErr); - EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPBACKCOLORERR),showPopupErr && ! popupWindowColorErr); - EnableWindow(GetDlgItem(hwnd,IDC_POPUPTEXTCOLORERR),showPopupErr && ! popupWindowColorErr); - EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPTEXTCOLORERR),showPopupErr && ! popupWindowColorErr); - EnableWindow(GetDlgItem(hwnd,IDC_POPUPTIMEERR),showPopupErr); - EnableWindow(GetDlgItem(hwnd,IDC_PREVIEWERR),showPopupErr); - SendMessage(GetParent(hwnd),PSM_CHANGED,0,0); - break; - } - - break; - - case WM_DESTROY: - break; - } - - return 0; -} - -INT_PTR CALLBACK OptionsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static int iInit = TRUE; - - UNREFERENCED_PARAMETER(wParam); - - switch(msg) - { - case WM_INITDIALOG: - { - TCITEM tci; - RECT rcClient; - GetClientRect(hwnd, &rcClient); - - iInit = TRUE; - tci.mask = TCIF_PARAM|TCIF_TEXT; - tci.lParam = (LPARAM)CreateDialog(hInst,MAKEINTRESOURCE(IDD_OPT_DEFAULT), hwnd, OptionsDefaultDlgProc); - tci.pszText = TranslateT("Skype default"); - TabCtrl_InsertItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), 0, &tci); - MoveWindow((HWND)tci.lParam,1,28,rcClient.right-5,rcClient.bottom-31,1); -#ifdef HAVE_UXTHEMES - if(MyEnableThemeDialogTexture) - MyEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB); -#endif - - tci.lParam = (LPARAM)CreateDialog(hInst,MAKEINTRESOURCE(IDD_OPT_ADVANCED),hwnd,OptionsAdvancedDlgProc); - tci.pszText = TranslateT("Skype advanced"); - TabCtrl_InsertItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), 1, &tci); - MoveWindow((HWND)tci.lParam,1,28,rcClient.right-5,rcClient.bottom-31,1); - ShowWindow((HWND)tci.lParam, SW_HIDE); -#ifdef HAVE_UXTHEMES - if(MyEnableThemeDialogTexture) - MyEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB); -#endif - - tci.lParam = (LPARAM)CreateDialog(hInst,MAKEINTRESOURCE(IDD_OPT_PROXY),hwnd,OptionsProxyDlgProc); - tci.pszText = TranslateT("Skype proxy"); - TabCtrl_InsertItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), 2, &tci); - MoveWindow((HWND)tci.lParam,1,28,rcClient.right-5,rcClient.bottom-31,1); - ShowWindow((HWND)tci.lParam, SW_HIDE); -#ifdef HAVE_UXTHEMES - if(MyEnableThemeDialogTexture) - MyEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB); -#endif - - iInit = FALSE; - return FALSE; - } - - case PSM_CHANGED: // used so tabs dont have to call SendMessage(GetParent(GetParent(hwnd)), PSM_CHANGED, 0, 0); - if(!iInit) - SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); - break; - case WM_NOTIFY: - switch(((LPNMHDR)lParam)->idFrom) { - case 0: - switch (((LPNMHDR)lParam)->code) - { - case PSN_APPLY: - { - TCITEM tci; - int i,count; - tci.mask = TCIF_PARAM; - count = TabCtrl_GetItemCount(GetDlgItem(hwnd,IDC_OPTIONSTAB)); - for (i=0;icode) - { - case TCN_SELCHANGING: - { - TCITEM tci; - tci.mask = TCIF_PARAM; - TabCtrl_GetItem(GetDlgItem(hwnd,IDC_OPTIONSTAB),TabCtrl_GetCurSel(GetDlgItem(hwnd,IDC_OPTIONSTAB)),&tci); - ShowWindow((HWND)tci.lParam,SW_HIDE); - } - break; - case TCN_SELCHANGE: - { - TCITEM tci; - tci.mask = TCIF_PARAM; - TabCtrl_GetItem(GetDlgItem(hwnd,IDC_OPTIONSTAB),TabCtrl_GetCurSel(GetDlgItem(hwnd,IDC_OPTIONSTAB)),&tci); - ShowWindow((HWND)tci.lParam,SW_SHOW); - } - break; - } - break; - - } - break; - } - return FALSE; -} - -INT_PTR CALLBACK OptionsProxyDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - const int Skype2SocketControls[]={ IDC_STATIC_HOST, IDC_HOST, IDC_STATIC_PORT, IDC_PORT, IDC_REQPASS, IDC_PASSWORD, IDC_STATIC_RESTART }; - static BOOL initDlg=FALSE; - DBVARIANT dbv; - int i; - - switch (uMsg){ - case WM_INITDIALOG: - initDlg=TRUE; - TranslateDialogDefault(hwndDlg); - if (!db_get_s(NULL, SKYPE_PROTONAME, "Host", &dbv)) { - SetDlgItemTextA(hwndDlg, IDC_HOST, dbv.pszVal); - db_free(&dbv); - } else SetDlgItemText(hwndDlg, IDC_HOST, _T("localhost")); - SendDlgItemMessage(hwndDlg, IDC_PORT, EM_SETLIMITTEXT, 5, 0L); - SetDlgItemInt(hwndDlg, IDC_PORT, db_get_w(NULL, SKYPE_PROTONAME, "Port", 1401), FALSE); - CheckDlgButton(hwndDlg, IDC_REQPASS, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "RequiresPassword", 0)); - CheckDlgButton(hwndDlg, IDC_USES2S, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "UseSkype2Socket", 0)); - if (!db_get_s(NULL, SKYPE_PROTONAME, "Password", &dbv)) { - SetDlgItemTextA(hwndDlg, IDC_PASSWORD, dbv.pszVal); - db_free(&dbv); - } - SendMessage(hwndDlg, WM_COMMAND, IDC_USES2S, 0); - SendMessage(hwndDlg, WM_COMMAND, IDC_REQPASS, 0); - initDlg=FALSE; - return TRUE; - case WM_NOTIFY: { - NMHDR* nmhdr = (NMHDR*)lParam; - - switch (nmhdr->code){ - case PSN_APPLY: - case PSN_KILLACTIVE: - { - char buf[1024]; - GetDlgItemTextA(hwndDlg, IDC_HOST, buf, sizeof(buf)); - db_set_s(NULL, SKYPE_PROTONAME, "Host", buf); - db_set_w(NULL, SKYPE_PROTONAME, "Port", (unsigned short)GetDlgItemInt(hwndDlg, IDC_PORT, NULL, FALSE)); - db_set_b(NULL, SKYPE_PROTONAME, "RequiresPassword", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_REQPASS), BM_GETCHECK,0,0))); - db_set_b (NULL, SKYPE_PROTONAME, "UseSkype2Socket", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_USES2S), BM_GETCHECK,0,0))); - ZeroMemory(buf, sizeof(buf)); - GetDlgItemTextA(hwndDlg, IDC_PASSWORD, buf, sizeof(buf)); - db_set_s(NULL, SKYPE_PROTONAME, "Password", buf); - return TRUE; - } - } - break; - } - case WM_COMMAND: { - switch (LOWORD(wParam)) { - case IDC_USES2S: - for (i=0; i < SIZEOF(Skype2SocketControls); i++) - EnableWindow(GetDlgItem(hwndDlg, Skype2SocketControls[i]), SendMessage(GetDlgItem(hwndDlg, LOWORD(wParam)), BM_GETCHECK,0,0)); - if (SendMessage(GetDlgItem(hwndDlg, LOWORD(wParam)), BM_GETCHECK,0,0)) - SendMessage(hwndDlg, WM_COMMAND, IDC_REQPASS, 0); - break; - case IDC_REQPASS: - EnableWindow(GetDlgItem(hwndDlg, IDC_PASSWORD), SendMessage(GetDlgItem(hwndDlg, LOWORD(wParam)), BM_GETCHECK,0,0)); - break; - - } - if (!initDlg) SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - } - } - return 0; -} - -INT_PTR CALLBACK OptionsAdvancedDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - static BOOL initDlg=FALSE; - static int statusModes[]={ID_STATUS_OFFLINE,ID_STATUS_ONLINE,ID_STATUS_AWAY,ID_STATUS_NA,ID_STATUS_OCCUPIED,ID_STATUS_DND,ID_STATUS_FREECHAT,ID_STATUS_INVISIBLE,ID_STATUS_OUTTOLUNCH,ID_STATUS_ONTHEPHONE}; - int i, j; - - switch (uMsg){ - case WM_INITDIALOG: - initDlg=TRUE; - - TranslateDialogDefault(hwndDlg); - CheckDlgButton(hwndDlg, IDC_ENABLEMENU, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "EnableMenu", 1)); - CheckDlgButton(hwndDlg, IDC_NOERRORS, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "SuppressErrors", 0)); - CheckDlgButton(hwndDlg, IDC_KEEPSTATE, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "KeepState", 0)); - CheckDlgButton(hwndDlg, IDC_TIMEZONE, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "UseTimeZonePatch", 0)); - CheckDlgButton(hwndDlg, IDC_IGNTZ, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "IgnoreTimeZones", 0)); - CheckDlgButton(hwndDlg, IDC_SHOWDEFAULTAVATAR, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "ShowDefaultSkypeAvatar", 0)); - CheckDlgButton(hwndDlg, IDC_SUPPRESSCALLSUMMARYMESSAGE, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "SuppressCallSummaryMessage", 1)); - CheckDlgButton(hwndDlg, IDC_NOSKYPE3STATS, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "NoSkype3Stats", 0)); - CheckDlgButton(hwndDlg, IDC_SHOWFULLNAME, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "ShowFullname", 1)); - - if (ServiceExists(MS_GC_NEWSESSION) && (!bProtocolSet || protocol>=5)) { - CheckDlgButton(hwndDlg, IDC_GROUPCHAT, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "UseGroupchat", 0)); - CheckDlgButton(hwndDlg, IDC_GROUPCHATREAD, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "MarkGroupchatRead", 0)); - } else { - EnableWindow(GetDlgItem(hwndDlg, IDC_GROUPCHAT), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_GROUPCHATREAD), FALSE); - } - -#ifdef USEPOPUP - if (ServiceExists(MS_POPUP_ADDPOPUPT)) - CheckDlgButton(hwndDlg, IDC_USEPOPUP, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "UsePopup", 0)); - else -#endif - EnableWindow(GetDlgItem(hwndDlg, IDC_USEPOPUP), FALSE); - - j=db_get_dw(NULL, SKYPE_PROTONAME, "SkypeOutStatusMode", ID_STATUS_ONTHEPHONE); - for(i=0;icode){ - case PSN_APPLY: - case PSN_KILLACTIVE: - db_set_b (NULL, SKYPE_PROTONAME, "EnableMenu", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_ENABLEMENU), BM_GETCHECK,0,0))); - db_set_b (NULL, SKYPE_PROTONAME, "UsePopup", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_USEPOPUP), BM_GETCHECK,0,0))); - db_set_b (NULL, SKYPE_PROTONAME, "UseGroupchat", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_GROUPCHAT), BM_GETCHECK,0,0))); - db_set_b (NULL, SKYPE_PROTONAME, "MarkGroupchatRead", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_GROUPCHATREAD), BM_GETCHECK,0,0))); - db_set_b (NULL, SKYPE_PROTONAME, "SuppressErrors", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_NOERRORS), BM_GETCHECK,0,0))); - db_set_b (NULL, SKYPE_PROTONAME, "KeepState", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_KEEPSTATE), BM_GETCHECK,0,0))); - db_set_dw(NULL, SKYPE_PROTONAME, "SkypeOutStatusMode", SendDlgItemMessage(hwndDlg,IDC_SKYPEOUTSTAT,CB_GETITEMDATA,SendDlgItemMessage(hwndDlg,IDC_SKYPEOUTSTAT,CB_GETCURSEL,0,0),0)); - db_set_b (NULL, SKYPE_PROTONAME, "UseTimeZonePatch", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_TIMEZONE), BM_GETCHECK,0,0))); - db_set_b (NULL, SKYPE_PROTONAME, "IgnoreTimeZones", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_IGNTZ), BM_GETCHECK,0,0))); - db_set_b (NULL, SKYPE_PROTONAME, "ShowDefaultSkypeAvatar", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_SHOWDEFAULTAVATAR), BM_GETCHECK,0,0))); - db_set_b (NULL, SKYPE_PROTONAME, "SuppressCallSummaryMessage", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_SUPPRESSCALLSUMMARYMESSAGE), BM_GETCHECK,0,0))); - db_set_b (NULL, SKYPE_PROTONAME, "NoSkype3Stats", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_NOSKYPE3STATS), BM_GETCHECK,0,0))); - db_set_b (NULL, SKYPE_PROTONAME, "ShowFullname", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_SHOWFULLNAME), BM_GETCHECK,0,0))); - return TRUE; - } - break; - } - case WM_COMMAND: { - switch (LOWORD(wParam)) { - case IDC_CLEANUP: - pthread_create(( pThreadFunc )CleanupNicknames, NULL); - break; - } - if (!initDlg) SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - } - } - return 0; -} - -static int CALLBACK BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData) -{ - UNREFERENCED_PARAMETER(lParam); - - switch (uMsg) - { - case BFFM_INITIALIZED: - { - // Set initial directory. -#ifdef UNICODE - wchar_t* wszInitFolder = make_unicode_string((const unsigned char*)lpData); - SendMessage(hWnd, BFFM_SETSELECTION, TRUE, (LPARAM)wszInitFolder); - free(wszInitFolder); -#else - SendMessage(hWnd, BFFM_SETSELECTION, TRUE, lpData); -#endif - break; - } - } - return 0; -} - -INT_PTR CALLBACK OptionsDefaultDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - static BOOL initDlg=FALSE; - static int skypeLaunchControls[]={IDC_NOSPLASH,IDC_MINIMIZED,IDC_NOTRAY,IDC_REMOVEABLE,IDC_SECONDARY,IDC_DATAPATHO,IDC_CUSTOMCOMMAND,IDC_STATIC_PATHINFO}; - - switch (uMsg){ - case WM_INITDIALOG: - { - DBVARIANT dbv; - BOOL startSkype; - int i; - - initDlg=TRUE; - TranslateDialogDefault(hwndDlg); - - startSkype=db_get_b(NULL, SKYPE_PROTONAME, "StartSkype", 1); - - CheckDlgButton(hwndDlg, IDC_STARTSKYPE, (BYTE)startSkype); - CheckDlgButton(hwndDlg, IDC_NOSPLASH, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "nosplash", 1)); - CheckDlgButton(hwndDlg, IDC_MINIMIZED, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "minimized", 1)); - CheckDlgButton(hwndDlg, IDC_NOTRAY, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "notray", 0)); - CheckDlgButton(hwndDlg, IDC_REMOVEABLE, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "removable", 0)); - CheckDlgButton(hwndDlg, IDC_SECONDARY, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "secondary", 0)); - CheckDlgButton(hwndDlg, IDC_DATAPATHO, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "datapath:", 0)); - CheckDlgButton(hwndDlg, IDC_SHUTDOWN, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "Shutdown", 0)); - CheckDlgButton(hwndDlg, IDC_UNLOADOFFLINE, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "UnloadOnOffline", 0)); - - CheckDlgButton(hwndDlg, IDC_CUSTOMCOMMAND, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "UseCustomCommand", 0)); - SendDlgItemMessage(hwndDlg, IDC_COMMANDLINE, EM_SETLIMITTEXT, MAX_PATH-1, 0L); - if(!db_get_s(NULL,SKYPE_PROTONAME,"CommandLine",&dbv)) - { - SetWindowTextA(GetDlgItem(hwndDlg, IDC_COMMANDLINE), dbv.pszVal); - db_free(&dbv); - } - - SendDlgItemMessage(hwndDlg, IDC_DATAPATH, EM_SETLIMITTEXT, MAX_PATH-1, 0L); - if(!db_get_s(NULL,SKYPE_PROTONAME,"datapath",&dbv)) - { - SetWindowTextA(GetDlgItem(hwndDlg, IDC_DATAPATH), dbv.pszVal); - db_free(&dbv); - } - - for(i=0; i < sizeof(skypeLaunchControls)/sizeof(skypeLaunchControls[0]); i++) - EnableWindow(GetDlgItem(hwndDlg, skypeLaunchControls[i]), startSkype); - - EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSECMDL), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0)); - EnableWindow(GetDlgItem(hwndDlg, IDC_COMMANDLINE), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0)); - - EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSEDP), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0)); - EnableWindow(GetDlgItem(hwndDlg, IDC_DATAPATH), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0)); - - // LoginUserName - if(!db_get_ts(NULL,SKYPE_PROTONAME,"LoginUserName",&dbv)) - { - SetWindowText(GetDlgItem(hwndDlg, IDC_USERNAME), dbv.ptszVal); - db_free(&dbv); - } - - // LoginPassword - if(!db_get_ts(NULL,SKYPE_PROTONAME,"LoginPassword",&dbv)) - { - SetWindowText(GetDlgItem(hwndDlg, IDC_PASSWORD), dbv.ptszVal); - db_free(&dbv); - } - - SendDlgItemMessage(hwndDlg, IDC_CONNATTEMPTS, EM_SETLIMITTEXT, 3, 0L); - SetDlgItemInt (hwndDlg, IDC_CONNATTEMPTS, db_get_w(NULL, SKYPE_PROTONAME, "ConnectionAttempts", 10), FALSE); - SendMessage(hwndDlg, WM_COMMAND, IDC_STARTSKYPE, 0); - initDlg=FALSE; - return TRUE; - } - case WM_NOTIFY: { - NMHDR* nmhdr = (NMHDR*)lParam; - - switch (nmhdr->code){ - case PSN_APPLY: - case PSN_KILLACTIVE: - { - char text[500]; - TCHAR wtext[500]; - char szRelativePath[MAX_PATH]; - - db_set_b (NULL, SKYPE_PROTONAME, "StartSkype", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_STARTSKYPE), BM_GETCHECK,0,0))); - db_set_b (NULL, SKYPE_PROTONAME, "nosplash", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_NOSPLASH), BM_GETCHECK,0,0))); - db_set_b (NULL, SKYPE_PROTONAME, "minimized", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_MINIMIZED), BM_GETCHECK,0,0))); - db_set_b (NULL, SKYPE_PROTONAME, "notray", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_NOTRAY), BM_GETCHECK,0,0))); - db_set_b (NULL, SKYPE_PROTONAME, "Shutdown", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_SHUTDOWN), BM_GETCHECK,0,0))); - db_set_b (NULL, SKYPE_PROTONAME, "UnloadOnOffline", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_UNLOADOFFLINE), BM_GETCHECK,0,0))); - db_set_w (NULL, SKYPE_PROTONAME, "ConnectionAttempts", (unsigned short)GetDlgItemInt(hwndDlg, IDC_CONNATTEMPTS, NULL, FALSE)); - db_set_b (NULL, SKYPE_PROTONAME, "UseCustomCommand", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0))); - db_set_b (NULL, SKYPE_PROTONAME, "datapath:", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0))); - db_set_b (NULL, SKYPE_PROTONAME, "removable", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_REMOVEABLE), BM_GETCHECK,0,0))); - db_set_b (NULL, SKYPE_PROTONAME, "secondary", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_SECONDARY), BM_GETCHECK,0,0))); - - GetDlgItemTextA(hwndDlg,IDC_COMMANDLINE,text,sizeof(text)); - strncpy(szRelativePath, text, sizeof(szRelativePath)-1); - CallService (MS_UTILS_PATHTORELATIVE, (WPARAM)text, (LPARAM)szRelativePath); - db_set_s(NULL, SKYPE_PROTONAME, "CommandLine", szRelativePath); - - GetDlgItemTextA(hwndDlg,IDC_DATAPATH,text,sizeof(text)); - strncpy(szRelativePath, text, sizeof(szRelativePath)-1); - CallService (MS_UTILS_PATHTORELATIVE, (WPARAM)text, (LPARAM)szRelativePath); - db_set_s(NULL, SKYPE_PROTONAME, "datapath", szRelativePath); - - // LoginUserName - GetDlgItemText(hwndDlg,IDC_USERNAME,wtext,sizeof(wtext)/sizeof(TCHAR)); - db_set_ts(NULL, SKYPE_PROTONAME, "LoginUserName", wtext); - - // LoginPassword - GetDlgItemText(hwndDlg,IDC_PASSWORD,wtext,sizeof(wtext)/sizeof(TCHAR)); - db_set_ts(NULL, SKYPE_PROTONAME, "LoginPassword", wtext); - - return TRUE; - } - } - break; - } - case WM_COMMAND: { - switch (LOWORD(wParam)) { - BOOL startSkype; - int i; - case IDC_STARTSKYPE: - startSkype=SendMessage(GetDlgItem(hwndDlg, IDC_STARTSKYPE), BM_GETCHECK,0,0); - - for(i=0; i < sizeof(skypeLaunchControls)/sizeof(skypeLaunchControls[0]); i++) - EnableWindow(GetDlgItem(hwndDlg, skypeLaunchControls[i]), startSkype); - - EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSECMDL), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0)); - EnableWindow(GetDlgItem(hwndDlg, IDC_COMMANDLINE), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0)); - - EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSEDP), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0)); - EnableWindow(GetDlgItem(hwndDlg, IDC_DATAPATH), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0)); - break; - case IDC_CLEANUP: - pthread_create(( pThreadFunc )CleanupNicknames, NULL); - break; - case IDC_DATAPATHO: - EnableWindow(GetDlgItem(hwndDlg, IDC_DATAPATH), SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0)); - EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSEDP), SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0)); - break; - case IDC_CUSTOMCOMMAND: - EnableWindow(GetDlgItem(hwndDlg, IDC_COMMANDLINE), SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0)); - EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSECMDL), SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0)); - break; - case IDC_BROWSECMDL: - { - OPENFILENAMEA ofn={0}; - BOOL gofnResult; - char szFileName[MAX_PATH]; - char szAbsolutePath[MAX_PATH]; - - ofn.lStructSize=sizeof(ofn); - ofn.hwndOwner=hwndDlg; - ofn.lpstrFilter="Executable files (*.exe)\0*.exe\0All files (*.*)\0*.*\0"; - ofn.nMaxFile=sizeof(szFileName); - ofn.lpstrDefExt="exe"; - ofn.lpstrFile=szFileName; - ofn.Flags=OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_ENABLESIZING; - - GetDlgItemTextA(hwndDlg,IDC_COMMANDLINE,szFileName,sizeof(szFileName)); - TranslateMirandaRelativePathToAbsolute(szFileName, szAbsolutePath, FALSE); - strcpy (szFileName, szAbsolutePath); - - if (!(gofnResult = GetOpenFileNameA(&ofn)) && CommDlgExtendedError() == FNERR_INVALIDFILENAME){ - strcpy(szFileName, ".\\Skype.exe"); - TranslateMirandaRelativePathToAbsolute(szFileName, szAbsolutePath, FALSE); - strcpy (szFileName, szAbsolutePath); - gofnResult = GetOpenFileNameA(&ofn); - } - - if(gofnResult) - SetWindowTextA(GetDlgItem(hwndDlg, IDC_COMMANDLINE), szFileName); - - break; - } - case IDC_BROWSEDP: - { - BROWSEINFOA bi={0}; - LPITEMIDLIST pidl; - char szFileName[MAX_PATH]; - char szAbsolutePath[MAX_PATH]; - - GetDlgItemTextA (hwndDlg, IDC_DATAPATH, szFileName, MAX_PATH); - - TranslateMirandaRelativePathToAbsolute(szFileName, szAbsolutePath, FALSE); - bi.hwndOwner = hwndDlg; - bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_SHAREABLE | BIF_NEWDIALOGSTYLE | BIF_NONEWFOLDERBUTTON; - bi.lpfn = BrowseCallbackProc; - bi.lParam = (LPARAM)szAbsolutePath; - - if ( (pidl = SHBrowseForFolderA (&bi)) ) { - if (SHGetPathFromIDListA (pidl, szFileName)) - SetDlgItemTextA (hwndDlg, IDC_DATAPATH, szFileName); - CoTaskMemFree (pidl); - } - break; - } - -#ifdef SKYPE_AUTO_DETECTION - case IDC_AUTODETECTION: - DoAutoDetect(hwndDlg); - break; -#endif - } - if (!initDlg) SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - } - } - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// OnDetailsInit - initializes user info dialog pages. - -int OnDetailsInit( WPARAM wParam, LPARAM lParam ) -{ - OPTIONSDIALOGPAGE odp = {0}; - MCONTACT hContact = (MCONTACT)lParam; - - odp.cbSize = sizeof(odp); - odp.hIcon = NULL; - odp.hInstance = hInst; - - if ( hContact == NULL ) { - - char szTitle[256]; - - if (mirandaVersion < PLUGIN_MAKE_VERSION(0, 7, 0, 27) && !bIsImoproxy) - { - mir_snprintf( szTitle, sizeof( szTitle ), "%s %s", SKYPE_PROTONAME, Translate( "Avatar" )); - - odp.pfnDlgProc = AvatarDlgProc; - odp.position = 1900000000; - odp.pszTemplate = MAKEINTRESOURCEA(IDD_SETAVATAR); - odp.pszTitle = szTitle; - UserInfo_AddPage(wParam, &odp); - } - - mir_snprintf( szTitle, sizeof( szTitle ), "%s %s", SKYPE_PROTONAME, Translate( "Details" )); - - odp.pfnDlgProc = DetailsDlgProc; - odp.position = 1900000000; - odp.pszTemplate = MAKEINTRESOURCEA(IDD_SETDETAILS); - odp.pszTitle = szTitle; - UserInfo_AddPage(wParam, &odp); - } - - return 0; -} - -/*AvatarDlgProc -* -* For setting the skype avatar -* -*/ -INT_PTR CALLBACK AvatarDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static RECT r; - - UNREFERENCED_PARAMETER(lParam); - - switch ( msg ) { - case WM_INITDIALOG: - TranslateDialogDefault( hwndDlg ); - - hAvatar = NULL; - if(ServiceExists(MS_AV_GETMYAVATAR)){ - struct avatarCacheEntry *ace = (struct avatarCacheEntry *)CallService(MS_AV_GETMYAVATAR, 0,(LPARAM) SKYPE_PROTONAME); - if (ace!=NULL) { - hAvatar = ( HBITMAP )CallService( MS_UTILS_LOADBITMAP, 0, ( LPARAM )ace->szFilename); - if ( hAvatar != NULL ) - SendDlgItemMessage(hwndDlg, IDC_AVATAR, STM_SETIMAGE, IMAGE_BITMAP, (WPARAM)hAvatar ); - } - } - - - - return TRUE; - - case WM_COMMAND: - if ( HIWORD( wParam ) == BN_CLICKED ) { - switch( LOWORD( wParam )) { - case IDC_SETAVATAR: - { - char szFileName[ MAX_PATH ]; - if ( EnterBitmapFileName( szFileName ) != ERROR_SUCCESS ) - return FALSE; - - hAvatar = ( HBITMAP )CallService( MS_UTILS_LOADBITMAP, 0, ( LPARAM )szFileName); - if ( hAvatar != NULL ){ - SendDlgItemMessage(hwndDlg, IDC_AVATAR, STM_SETIMAGE, IMAGE_BITMAP, (WPARAM)hAvatar ); - CallService(SKYPE_SETAVATAR, 0, ( LPARAM )szFileName); - } - break; - } - case IDC_DELETEAVATAR: - if ( hAvatar != NULL ) { - DeleteObject( hAvatar ); - hAvatar = NULL; - CallService(SKYPE_SETAVATAR, 0, 0); - } - db_unset( NULL, SKYPE_PROTONAME, "AvatarFile" ); - InvalidateRect( hwndDlg, NULL, TRUE ); - break; - } } - break; - - case WM_DESTROY: - if ( hAvatar != NULL ) - DeleteObject( hAvatar ); - break; - } - - return 0; -} - -/*DetailsDlgProc -* -* For setting the skype infos -* -*/ -INT_PTR CALLBACK DetailsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static int sexM = 0,sexF = 0, sex; - - UNREFERENCED_PARAMETER(lParam); - - switch ( msg ) { - case WM_INITDIALOG: - TranslateDialogDefault( hwndDlg ); - - ZeroMemory (&myProfile, sizeof(myProfile)); - SkypeProfile_Load(&myProfile); - if(SkypeInitialized) - SkypeProfile_LoadFromSkype(&myProfile); - - SendDlgItemMessage(hwndDlg,IDC_SEX,CB_ADDSTRING,0,(LPARAM)_T("")); - sexM = SendDlgItemMessage(hwndDlg,IDC_SEX,CB_ADDSTRING,0,(LPARAM)TranslateT("MALE")); - sexF = SendDlgItemMessage(hwndDlg,IDC_SEX,CB_ADDSTRING,0,(LPARAM)TranslateT("FEMALE")); - - switch(myProfile.Sex) { - case 0x4D: SendDlgItemMessage(hwndDlg,IDC_SEX,CB_SETCURSEL, sexM, 0); break; - case 0x46: SendDlgItemMessage(hwndDlg,IDC_SEX,CB_SETCURSEL, sexF, 0); break; - } - - SetDlgItemText(hwndDlg, IDC_FULLNAME, myProfile.FullName); - SetDlgItemTextA(hwndDlg, IDC_HOMEPAGE, myProfile.HomePage); - SetDlgItemTextA(hwndDlg, IDC_HOMEPHONE, myProfile.HomePhone); - SetDlgItemTextA(hwndDlg, IDC_OFFICEPHONE, myProfile.OfficePhone); - SetDlgItemText(hwndDlg, IDC_CITY, myProfile.City); - SetDlgItemText(hwndDlg, IDC_PROVINCE, myProfile.Province); - DateTime_SetSystemtime (GetDlgItem (hwndDlg, IDC_BIRTHDAY), GDT_VALID, &myProfile.Birthday); - return TRUE; - - case WM_COMMAND: - if ( HIWORD( wParam ) == BN_CLICKED ) { - switch( LOWORD( wParam )) { - case IDC_SAVEDETAILS: - GetDlgItemText(hwndDlg,IDC_FULLNAME,myProfile.FullName,sizeof(myProfile.FullName)/sizeof(TCHAR)); - GetDlgItemTextA(hwndDlg,IDC_HOMEPAGE,myProfile.HomePage,sizeof(myProfile.HomePage)/sizeof(TCHAR)); - GetDlgItemTextA(hwndDlg,IDC_HOMEPHONE,myProfile.HomePhone,sizeof(myProfile.HomePhone)/sizeof(TCHAR)); - GetDlgItemTextA(hwndDlg,IDC_OFFICEPHONE,myProfile.OfficePhone,sizeof(myProfile.OfficePhone)/sizeof(TCHAR)); - GetDlgItemText(hwndDlg,IDC_CITY,myProfile.City,sizeof(myProfile.City)/sizeof(TCHAR)); - GetDlgItemText(hwndDlg,IDC_PROVINCE,myProfile.Province,sizeof(myProfile.Province)/sizeof(TCHAR)); - sex = SendMessage(GetDlgItem(hwndDlg,IDC_SEX),CB_GETCURSEL,0,0); - - myProfile.Sex = 0; - if(sex == sexF) myProfile.Sex = 0x46; else - if(sex == sexM) myProfile.Sex = 0x4D; - DateTime_GetSystemtime (GetDlgItem (hwndDlg, IDC_BIRTHDAY), &myProfile.Birthday); - - SkypeProfile_Save(&myProfile); - if(SkypeInitialized) - SkypeProfile_SaveToSkype(&myProfile); - break; - } - } - break; - - case WM_DESTROY: - if ( hAvatar != NULL ) - DeleteObject( hAvatar ); - break; - } - - return 0; -} - -#ifdef SKYPE_AUTO_DETECTION -/** - * DoAutoDetect - * @param dlg The default option dialog handle - */ -void DoAutoDetect(HWND dlg) -{ - char basePath[MAX_PATH]; - char fileName[MAX_PATH]; - char tmpUser[255]; - ezxml_t f1, acc; - - if (FAILED(SHGetFolderPath(dlg,CSIDL_APPDATA,NULL,0,basePath))) - { - OUTPUT("Error in retrieving appdata path!"); - return; - } - - strcat(basePath,"\\Skype\\"); - sprintf (fileName, "%s\\shared.xml", basePath); - - if (f1 = ezxml_parse_file(fileName)) - { - if (acc = ezxml_get(f1, "Lib", 0, "Account", 0, "Default", -1)) - { - if (GetWindowTextA(GetDlgItem(dlg,IDC_USERNAME),tmpUser,sizeof(tmpUser))) - SetWindowTextA(GetDlgItem(dlg,IDC_USERNAME),acc->txt); - /* Can't find this stuff in current Skype verions?? - sprintf (fileName, "%s\\%s\\config.xml", basePath, acc->txt); - if ((acc = ezxml_get(f1, "UI", 0, "Messages", 0, "OpenWindowInCompactMode", -1)) && *acc->txt!='0') - { - ezxml_set_txt (acc, "0"); - // ezXML doesn't supprot saving yet - } - */ - } - ezxml_free(f1); - } - else - { - OUTPUT("Failed to open skypes configuration files!"); - return; - } -} -#endif diff --git a/protocols/SkypeClassic/src/skypeopt.cpp b/protocols/SkypeClassic/src/skypeopt.cpp new file mode 100644 index 0000000000..07fa5905db --- /dev/null +++ b/protocols/SkypeClassic/src/skypeopt.cpp @@ -0,0 +1,968 @@ +#include "skype.h" +#include "skypeopt.h" +#include "pthread.h" +#include "gchat.h" +#include "skypeprofile.h" +#if(WINVER >= 0x0500) +#include "uxtheme.h" +#define HAVE_UXTHEMES +#endif + +#ifdef SKYPE_AUTO_DETECTION +#include "ezxml/ezxml.c" +#endif + +#ifdef UNICODE +#include "utf8.h" +#endif + +#pragma warning (disable: 4706) // assignment within conditional expression + +// VC6 SDK defines +#ifndef BIF_SHAREABLE +#define BIF_SHAREABLE 0x8000 // sharable resources displayed (remote shares, requires BIF_USENEWUI) +#endif +#ifndef BIF_NEWDIALOGSTYLE +#define BIF_NEWDIALOGSTYLE 0x0040 // Use the new dialog layout with the ability to resize +#endif // Caller needs to call OleInitialize() before using this API +#ifndef BIF_NONEWFOLDERBUTTON +#define BIF_NONEWFOLDERBUTTON 0x0200 // Do not add the "New Folder" button to the dialog. Only applicable with BIF_NEWDIALOGSTYLE. +#endif + + +extern HINSTANCE hInst; +extern char protocol, g_szProtoName[]; +extern BOOL SkypeInitialized, bProtocolSet, bIsImoproxy; +extern DWORD mirandaVersion; + +BOOL showPopup, showPopupErr, popupWindowColor, popupWindowColorErr; +unsigned int popupBackColor, popupBackColorErr; +unsigned int popupTextColor, popupTextColorErr; +int popupTimeSec, popupTimeSecErr; +POPUPDATAT InCallPopup; +POPUPDATAT ErrorPopup; + +static SkypeProfile myProfile; +static HBITMAP hAvatar = NULL; + +extern BOOL PopupServiceExists; +extern BOOL (WINAPI *MyEnableThemeDialogTexture)(HANDLE, DWORD); + +int RegisterOptions(WPARAM wParam, LPARAM lParam) { + OPTIONSDIALOGPAGE odp; + + UNREFERENCED_PARAMETER(lParam); + + ZeroMemory(&odp, sizeof(odp)); + odp.cbSize = sizeof(odp); + odp.hInstance = hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS); + odp.pszGroup = "Network"; + odp.pszTitle = SKYPE_PROTONAME; + odp.pfnDlgProc = OptionsDlgProc; + odp.flags = ODPF_BOLDGROUPS; + Options_AddPage(wParam, &odp); + + if(PopupServiceExists) + { + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_POPUP); + odp.pszGroup = "Popups"; + odp.pfnDlgProc = OptPopupDlgProc; + Options_AddPage(wParam, &odp); + } + + return 0; +} + +INT_PTR CALLBACK OptPopupDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static RECT r; + + switch ( msg ) + { + case WM_INITDIALOG: + TranslateDialogDefault( hwnd ); + // Message Popup + popupTimeSec = db_get_dw(NULL, SKYPE_PROTONAME, "popupTimeSec", 4); + popupTextColor = db_get_dw(NULL, SKYPE_PROTONAME, "popupTextColor", GetSysColor(COLOR_WINDOWTEXT)); + popupBackColor = db_get_dw(NULL, SKYPE_PROTONAME, "popupBackColor", GetSysColor(COLOR_BTNFACE)); + popupWindowColor = db_get_b(NULL, SKYPE_PROTONAME, "popupWindowColor", FALSE); + showPopup = db_get_b(NULL, SKYPE_PROTONAME, "showPopup", TRUE); + // ERROR Message Popup + popupTimeSecErr = db_get_dw(NULL, SKYPE_PROTONAME, "popupTimeSecErr", 4); + popupTextColorErr = db_get_dw(NULL, SKYPE_PROTONAME, "popupTextColorErr", GetSysColor(COLOR_WINDOWTEXT)); + popupBackColorErr = db_get_dw(NULL, SKYPE_PROTONAME, "popupBackColorErr", GetSysColor(COLOR_BTNFACE)); + popupWindowColorErr = db_get_b(NULL, SKYPE_PROTONAME, "popupWindowColorErr", FALSE); + showPopupErr = db_get_b(NULL, SKYPE_PROTONAME, "showPopupErr", TRUE); + + EnableWindow(GetDlgItem(hwnd,IDC_USEWINCOLORS),showPopup); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPBACKCOLOR),showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPBACKCOLOR),showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPTEXTCOLOR),showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPTEXTCOLOR),showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPTIME),showPopup); + EnableWindow(GetDlgItem(hwnd,IDC_PREVIEW),showPopup); + EnableWindow(GetDlgItem(hwnd,IDC_USEWINCOLORSERR),showPopupErr); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPBACKCOLORERR),showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPBACKCOLORERR),showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPTEXTCOLORERR),showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPTEXTCOLORERR),showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPTIMEERR),showPopupErr); + EnableWindow(GetDlgItem(hwnd,IDC_PREVIEWERR),showPopupErr); + CheckDlgButton(hwnd, IDC_POPUPINCOMING, (WPARAM) showPopup); + CheckDlgButton(hwnd, IDC_USEWINCOLORS, (WPARAM) popupWindowColor); + CheckDlgButton(hwnd, IDC_POPUPERROR, (WPARAM) showPopupErr); + CheckDlgButton(hwnd, IDC_USEWINCOLORSERR, (WPARAM) popupWindowColorErr); + SendDlgItemMessage(hwnd, IDC_POPUPTIME, EM_SETLIMITTEXT, 3, 0L); + SetDlgItemInt(hwnd, IDC_POPUPTIME, popupTimeSec,FALSE); + SendDlgItemMessage(hwnd, IDC_POPUPTIMEERR, EM_SETLIMITTEXT, 3, 0L); + SetDlgItemInt(hwnd, IDC_POPUPTIMEERR, popupTimeSecErr,FALSE); + SendDlgItemMessage(hwnd, IDC_POPUPBACKCOLOR, CPM_SETCOLOUR,0, popupBackColor); + SendDlgItemMessage(hwnd, IDC_POPUPBACKCOLOR, CPM_SETDEFAULTCOLOUR, 0, GetSysColor(COLOR_BTNFACE)); + SendDlgItemMessage(hwnd, IDC_POPUPTEXTCOLOR, CPM_SETCOLOUR,0, popupTextColor); + SendDlgItemMessage(hwnd, IDC_POPUPTEXTCOLOR, CPM_SETDEFAULTCOLOUR, 0, GetSysColor(COLOR_WINDOWTEXT)); + SendDlgItemMessage(hwnd, IDC_POPUPBACKCOLORERR, CPM_SETCOLOUR,0, popupBackColorErr); + SendDlgItemMessage(hwnd, IDC_POPUPBACKCOLORERR, CPM_SETDEFAULTCOLOUR, 0, GetSysColor(COLOR_BTNFACE)); + SendDlgItemMessage(hwnd, IDC_POPUPTEXTCOLORERR, CPM_SETCOLOUR,0, popupTextColorErr); + SendDlgItemMessage(hwnd, IDC_POPUPTEXTCOLORERR, CPM_SETDEFAULTCOLOUR, 0, GetSysColor(COLOR_WINDOWTEXT)); + + + return TRUE; + break; + + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->idFrom) + { + case 0: + switch (((LPNMHDR)lParam)->code) + { + case PSN_APPLY: + db_set_dw(NULL, SKYPE_PROTONAME, "popupBackColor", popupBackColor); + db_set_dw(NULL, SKYPE_PROTONAME, "popupTextColor", popupTextColor); + db_set_dw(NULL, SKYPE_PROTONAME, "popupTimeSec", popupTimeSec); + db_set_b(NULL, SKYPE_PROTONAME, "popupWindowColor", (BYTE)popupWindowColor); + db_set_b(NULL, SKYPE_PROTONAME, "showPopup", (BYTE)showPopup); + db_set_dw(NULL, SKYPE_PROTONAME, "popupBackColorErr", popupBackColorErr); + db_set_dw(NULL, SKYPE_PROTONAME, "popupTextColorErr", popupTextColorErr); + db_set_dw(NULL, SKYPE_PROTONAME, "popupTimeSecErr", popupTimeSecErr); + db_set_b(NULL, SKYPE_PROTONAME, "popupWindowColorErr", (BYTE)popupWindowColorErr); + db_set_b(NULL, SKYPE_PROTONAME, "showPopupErr", (BYTE)showPopupErr); + break; + } + } + break; + + + + case WM_COMMAND: + switch( LOWORD( wParam )) + { + case IDC_PREVIEW: + { + MCONTACT hContact; + TCHAR * lpzContactName; + + hContact = db_find_first(); + lpzContactName = (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact,GCDNF_TCHAR); + InCallPopup.lchContact = hContact; + InCallPopup.lchIcon = LoadIcon(hInst,MAKEINTRESOURCE(IDI_CALL)); + InCallPopup.colorBack = ! popupWindowColor ? popupBackColor : GetSysColor(COLOR_BTNFACE); + InCallPopup.colorText = ! popupWindowColor ? popupTextColor : GetSysColor(COLOR_WINDOWTEXT); + InCallPopup.iSeconds = popupTimeSec; + InCallPopup.PluginData = (void *)1; + + lstrcpy(InCallPopup.lptzText, TranslateT("Incoming Skype Call")); + + lstrcpy(InCallPopup.lptzContactName, lpzContactName); + + CallService(MS_POPUP_ADDPOPUPT,(WPARAM)&InCallPopup,0); + + + break; + } + case IDC_PREVIEWERR: + ErrorPopup.lchContact = NULL; + ErrorPopup.lchIcon = LoadIcon(hInst,MAKEINTRESOURCE(IDI_CALL)); + ErrorPopup.colorBack = ! popupWindowColorErr ? popupBackColorErr : GetSysColor(COLOR_BTNFACE); + ErrorPopup.colorText = ! popupWindowColorErr ? popupTextColorErr : GetSysColor(COLOR_WINDOWTEXT); + ErrorPopup.iSeconds = popupTimeSecErr; + ErrorPopup.PluginData = (void *)1; + + lstrcpy(ErrorPopup.lptzText, TranslateT("Preview Error Message")); + + lstrcpy(ErrorPopup.lptzContactName, _T("Error Message")); + + + CallService(MS_POPUP_ADDPOPUPT,(WPARAM)&ErrorPopup,0); + + break; + + case IDC_POPUPTIME: + case IDC_POPUPTIMEERR: + { + BOOL Translated; + popupTimeSec = GetDlgItemInt(hwnd,IDC_POPUPTIME,&Translated,FALSE); + popupTimeSecErr = GetDlgItemInt(hwnd,IDC_POPUPTIMEERR,&Translated,FALSE); + SendMessage(GetParent(hwnd),PSM_CHANGED,0,0); + break; + } + case IDC_POPUPTEXTCOLOR: + case IDC_POPUPBACKCOLOR: + case IDC_POPUPTEXTCOLORERR: + case IDC_POPUPBACKCOLORERR: + popupBackColor = (UINT)SendDlgItemMessage(hwnd,IDC_POPUPBACKCOLOR,CPM_GETCOLOUR,0,0); + popupTextColor = (UINT)SendDlgItemMessage(hwnd,IDC_POPUPTEXTCOLOR,CPM_GETCOLOUR,0,0); + popupBackColorErr = (UINT)SendDlgItemMessage(hwnd,IDC_POPUPBACKCOLORERR,CPM_GETCOLOUR,0,0); + popupTextColorErr = (UINT)SendDlgItemMessage(hwnd,IDC_POPUPTEXTCOLORERR,CPM_GETCOLOUR,0,0); + SendMessage(GetParent(hwnd),PSM_CHANGED,0,0); + break; + case IDC_USEWINCOLORS: + popupWindowColor = (IsDlgButtonChecked(hwnd,IDC_USEWINCOLORS)==BST_CHECKED); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPBACKCOLOR), showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPBACKCOLOR), showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPTEXTCOLOR), showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPTEXTCOLOR), showPopup && ! popupWindowColor); + SendMessage(GetParent(hwnd),PSM_CHANGED,0,0); + break; + case IDC_POPUPINCOMING: + showPopup = (IsDlgButtonChecked(hwnd,IDC_POPUPINCOMING)==BST_CHECKED); + EnableWindow(GetDlgItem(hwnd,IDC_USEWINCOLORS),showPopup); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPBACKCOLOR),showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPBACKCOLOR),showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPTEXTCOLOR),showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPTEXTCOLOR),showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPTIME),showPopup); + EnableWindow(GetDlgItem(hwnd,IDC_PREVIEW),showPopup); + SendMessage(GetParent(hwnd),PSM_CHANGED,0,0); + break; + case IDC_USEWINCOLORSERR: + popupWindowColorErr = (IsDlgButtonChecked(hwnd,IDC_USEWINCOLORSERR)==BST_CHECKED); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPBACKCOLORERR), showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPBACKCOLORERR), showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPTEXTCOLORERR), showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPTEXTCOLORERR), showPopupErr && ! popupWindowColorErr); + SendMessage(GetParent(hwnd),PSM_CHANGED,0,0); + break; + case IDC_POPUPERROR: + showPopupErr = (IsDlgButtonChecked(hwnd,IDC_POPUPERROR)==BST_CHECKED); + EnableWindow(GetDlgItem(hwnd,IDC_USEWINCOLORSERR),showPopupErr); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPBACKCOLORERR),showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPBACKCOLORERR),showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPTEXTCOLORERR),showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPTEXTCOLORERR),showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPTIMEERR),showPopupErr); + EnableWindow(GetDlgItem(hwnd,IDC_PREVIEWERR),showPopupErr); + SendMessage(GetParent(hwnd),PSM_CHANGED,0,0); + break; + } + + break; + + case WM_DESTROY: + break; + } + + return 0; +} + +INT_PTR CALLBACK OptionsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static int iInit = TRUE; + + UNREFERENCED_PARAMETER(wParam); + + switch(msg) + { + case WM_INITDIALOG: + { + TCITEM tci; + RECT rcClient; + GetClientRect(hwnd, &rcClient); + + iInit = TRUE; + tci.mask = TCIF_PARAM|TCIF_TEXT; + tci.lParam = (LPARAM)CreateDialog(hInst,MAKEINTRESOURCE(IDD_OPT_DEFAULT), hwnd, OptionsDefaultDlgProc); + tci.pszText = TranslateT("Skype default"); + TabCtrl_InsertItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), 0, &tci); + MoveWindow((HWND)tci.lParam,1,28,rcClient.right-5,rcClient.bottom-31,1); +#ifdef HAVE_UXTHEMES + if(MyEnableThemeDialogTexture) + MyEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB); +#endif + + tci.lParam = (LPARAM)CreateDialog(hInst,MAKEINTRESOURCE(IDD_OPT_ADVANCED),hwnd,OptionsAdvancedDlgProc); + tci.pszText = TranslateT("Skype advanced"); + TabCtrl_InsertItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), 1, &tci); + MoveWindow((HWND)tci.lParam,1,28,rcClient.right-5,rcClient.bottom-31,1); + ShowWindow((HWND)tci.lParam, SW_HIDE); +#ifdef HAVE_UXTHEMES + if(MyEnableThemeDialogTexture) + MyEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB); +#endif + + tci.lParam = (LPARAM)CreateDialog(hInst,MAKEINTRESOURCE(IDD_OPT_PROXY),hwnd,OptionsProxyDlgProc); + tci.pszText = TranslateT("Skype proxy"); + TabCtrl_InsertItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), 2, &tci); + MoveWindow((HWND)tci.lParam,1,28,rcClient.right-5,rcClient.bottom-31,1); + ShowWindow((HWND)tci.lParam, SW_HIDE); +#ifdef HAVE_UXTHEMES + if(MyEnableThemeDialogTexture) + MyEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB); +#endif + + iInit = FALSE; + return FALSE; + } + + case PSM_CHANGED: // used so tabs dont have to call SendMessage(GetParent(GetParent(hwnd)), PSM_CHANGED, 0, 0); + if(!iInit) + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->idFrom) { + case 0: + switch (((LPNMHDR)lParam)->code) + { + case PSN_APPLY: + { + TCITEM tci; + int i,count; + tci.mask = TCIF_PARAM; + count = TabCtrl_GetItemCount(GetDlgItem(hwnd,IDC_OPTIONSTAB)); + for (i=0;icode) + { + case TCN_SELCHANGING: + { + TCITEM tci; + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(GetDlgItem(hwnd,IDC_OPTIONSTAB),TabCtrl_GetCurSel(GetDlgItem(hwnd,IDC_OPTIONSTAB)),&tci); + ShowWindow((HWND)tci.lParam,SW_HIDE); + } + break; + case TCN_SELCHANGE: + { + TCITEM tci; + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(GetDlgItem(hwnd,IDC_OPTIONSTAB),TabCtrl_GetCurSel(GetDlgItem(hwnd,IDC_OPTIONSTAB)),&tci); + ShowWindow((HWND)tci.lParam,SW_SHOW); + } + break; + } + break; + + } + break; + } + return FALSE; +} + +INT_PTR CALLBACK OptionsProxyDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + const int Skype2SocketControls[]={ IDC_STATIC_HOST, IDC_HOST, IDC_STATIC_PORT, IDC_PORT, IDC_REQPASS, IDC_PASSWORD, IDC_STATIC_RESTART }; + static BOOL initDlg=FALSE; + DBVARIANT dbv; + int i; + + switch (uMsg){ + case WM_INITDIALOG: + initDlg=TRUE; + TranslateDialogDefault(hwndDlg); + if (!db_get_s(NULL, SKYPE_PROTONAME, "Host", &dbv)) { + SetDlgItemTextA(hwndDlg, IDC_HOST, dbv.pszVal); + db_free(&dbv); + } else SetDlgItemText(hwndDlg, IDC_HOST, _T("localhost")); + SendDlgItemMessage(hwndDlg, IDC_PORT, EM_SETLIMITTEXT, 5, 0L); + SetDlgItemInt(hwndDlg, IDC_PORT, db_get_w(NULL, SKYPE_PROTONAME, "Port", 1401), FALSE); + CheckDlgButton(hwndDlg, IDC_REQPASS, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "RequiresPassword", 0)); + CheckDlgButton(hwndDlg, IDC_USES2S, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "UseSkype2Socket", 0)); + if (!db_get_s(NULL, SKYPE_PROTONAME, "Password", &dbv)) { + SetDlgItemTextA(hwndDlg, IDC_PASSWORD, dbv.pszVal); + db_free(&dbv); + } + SendMessage(hwndDlg, WM_COMMAND, IDC_USES2S, 0); + SendMessage(hwndDlg, WM_COMMAND, IDC_REQPASS, 0); + initDlg=FALSE; + return TRUE; + case WM_NOTIFY: { + NMHDR* nmhdr = (NMHDR*)lParam; + + switch (nmhdr->code){ + case PSN_APPLY: + case PSN_KILLACTIVE: + { + char buf[1024]; + GetDlgItemTextA(hwndDlg, IDC_HOST, buf, sizeof(buf)); + db_set_s(NULL, SKYPE_PROTONAME, "Host", buf); + db_set_w(NULL, SKYPE_PROTONAME, "Port", (unsigned short)GetDlgItemInt(hwndDlg, IDC_PORT, NULL, FALSE)); + db_set_b(NULL, SKYPE_PROTONAME, "RequiresPassword", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_REQPASS), BM_GETCHECK,0,0))); + db_set_b (NULL, SKYPE_PROTONAME, "UseSkype2Socket", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_USES2S), BM_GETCHECK,0,0))); + ZeroMemory(buf, sizeof(buf)); + GetDlgItemTextA(hwndDlg, IDC_PASSWORD, buf, sizeof(buf)); + db_set_s(NULL, SKYPE_PROTONAME, "Password", buf); + return TRUE; + } + } + break; + } + case WM_COMMAND: { + switch (LOWORD(wParam)) { + case IDC_USES2S: + for (i=0; i < SIZEOF(Skype2SocketControls); i++) + EnableWindow(GetDlgItem(hwndDlg, Skype2SocketControls[i]), SendMessage(GetDlgItem(hwndDlg, LOWORD(wParam)), BM_GETCHECK,0,0)); + if (SendMessage(GetDlgItem(hwndDlg, LOWORD(wParam)), BM_GETCHECK,0,0)) + SendMessage(hwndDlg, WM_COMMAND, IDC_REQPASS, 0); + break; + case IDC_REQPASS: + EnableWindow(GetDlgItem(hwndDlg, IDC_PASSWORD), SendMessage(GetDlgItem(hwndDlg, LOWORD(wParam)), BM_GETCHECK,0,0)); + break; + + } + if (!initDlg) SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + } + return 0; +} + +INT_PTR CALLBACK OptionsAdvancedDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + static BOOL initDlg=FALSE; + static int statusModes[]={ID_STATUS_OFFLINE,ID_STATUS_ONLINE,ID_STATUS_AWAY,ID_STATUS_NA,ID_STATUS_OCCUPIED,ID_STATUS_DND,ID_STATUS_FREECHAT,ID_STATUS_INVISIBLE,ID_STATUS_OUTTOLUNCH,ID_STATUS_ONTHEPHONE}; + int i, j; + + switch (uMsg){ + case WM_INITDIALOG: + initDlg=TRUE; + + TranslateDialogDefault(hwndDlg); + CheckDlgButton(hwndDlg, IDC_ENABLEMENU, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "EnableMenu", 1)); + CheckDlgButton(hwndDlg, IDC_NOERRORS, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "SuppressErrors", 0)); + CheckDlgButton(hwndDlg, IDC_KEEPSTATE, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "KeepState", 0)); + CheckDlgButton(hwndDlg, IDC_TIMEZONE, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "UseTimeZonePatch", 0)); + CheckDlgButton(hwndDlg, IDC_IGNTZ, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "IgnoreTimeZones", 0)); + CheckDlgButton(hwndDlg, IDC_SHOWDEFAULTAVATAR, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "ShowDefaultSkypeAvatar", 0)); + CheckDlgButton(hwndDlg, IDC_SUPPRESSCALLSUMMARYMESSAGE, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "SuppressCallSummaryMessage", 1)); + CheckDlgButton(hwndDlg, IDC_NOSKYPE3STATS, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "NoSkype3Stats", 0)); + CheckDlgButton(hwndDlg, IDC_SHOWFULLNAME, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "ShowFullname", 1)); + + if (ServiceExists(MS_GC_NEWSESSION) && (!bProtocolSet || protocol>=5)) { + CheckDlgButton(hwndDlg, IDC_GROUPCHAT, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "UseGroupchat", 0)); + CheckDlgButton(hwndDlg, IDC_GROUPCHATREAD, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "MarkGroupchatRead", 0)); + } else { + EnableWindow(GetDlgItem(hwndDlg, IDC_GROUPCHAT), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_GROUPCHATREAD), FALSE); + } + +#ifdef USEPOPUP + if (ServiceExists(MS_POPUP_ADDPOPUPT)) + CheckDlgButton(hwndDlg, IDC_USEPOPUP, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "UsePopup", 0)); + else +#endif + EnableWindow(GetDlgItem(hwndDlg, IDC_USEPOPUP), FALSE); + + j=db_get_dw(NULL, SKYPE_PROTONAME, "SkypeOutStatusMode", ID_STATUS_ONTHEPHONE); + for(i=0;icode){ + case PSN_APPLY: + case PSN_KILLACTIVE: + db_set_b (NULL, SKYPE_PROTONAME, "EnableMenu", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_ENABLEMENU), BM_GETCHECK,0,0))); + db_set_b (NULL, SKYPE_PROTONAME, "UsePopup", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_USEPOPUP), BM_GETCHECK,0,0))); + db_set_b (NULL, SKYPE_PROTONAME, "UseGroupchat", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_GROUPCHAT), BM_GETCHECK,0,0))); + db_set_b (NULL, SKYPE_PROTONAME, "MarkGroupchatRead", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_GROUPCHATREAD), BM_GETCHECK,0,0))); + db_set_b (NULL, SKYPE_PROTONAME, "SuppressErrors", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_NOERRORS), BM_GETCHECK,0,0))); + db_set_b (NULL, SKYPE_PROTONAME, "KeepState", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_KEEPSTATE), BM_GETCHECK,0,0))); + db_set_dw(NULL, SKYPE_PROTONAME, "SkypeOutStatusMode", SendDlgItemMessage(hwndDlg,IDC_SKYPEOUTSTAT,CB_GETITEMDATA,SendDlgItemMessage(hwndDlg,IDC_SKYPEOUTSTAT,CB_GETCURSEL,0,0),0)); + db_set_b (NULL, SKYPE_PROTONAME, "UseTimeZonePatch", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_TIMEZONE), BM_GETCHECK,0,0))); + db_set_b (NULL, SKYPE_PROTONAME, "IgnoreTimeZones", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_IGNTZ), BM_GETCHECK,0,0))); + db_set_b (NULL, SKYPE_PROTONAME, "ShowDefaultSkypeAvatar", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_SHOWDEFAULTAVATAR), BM_GETCHECK,0,0))); + db_set_b (NULL, SKYPE_PROTONAME, "SuppressCallSummaryMessage", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_SUPPRESSCALLSUMMARYMESSAGE), BM_GETCHECK,0,0))); + db_set_b (NULL, SKYPE_PROTONAME, "NoSkype3Stats", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_NOSKYPE3STATS), BM_GETCHECK,0,0))); + db_set_b (NULL, SKYPE_PROTONAME, "ShowFullname", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_SHOWFULLNAME), BM_GETCHECK,0,0))); + return TRUE; + } + break; + } + case WM_COMMAND: { + switch (LOWORD(wParam)) { + case IDC_CLEANUP: + pthread_create(( pThreadFunc )CleanupNicknames, NULL); + break; + } + if (!initDlg) SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + } + return 0; +} + +static int CALLBACK BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData) +{ + UNREFERENCED_PARAMETER(lParam); + + switch (uMsg) + { + case BFFM_INITIALIZED: + { + // Set initial directory. +#ifdef UNICODE + wchar_t* wszInitFolder = make_unicode_string((const unsigned char*)lpData); + SendMessage(hWnd, BFFM_SETSELECTION, TRUE, (LPARAM)wszInitFolder); + free(wszInitFolder); +#else + SendMessage(hWnd, BFFM_SETSELECTION, TRUE, lpData); +#endif + break; + } + } + return 0; +} + +INT_PTR CALLBACK OptionsDefaultDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + static BOOL initDlg=FALSE; + static int skypeLaunchControls[]={IDC_NOSPLASH,IDC_MINIMIZED,IDC_NOTRAY,IDC_REMOVEABLE,IDC_SECONDARY,IDC_DATAPATHO,IDC_CUSTOMCOMMAND,IDC_STATIC_PATHINFO}; + + switch (uMsg){ + case WM_INITDIALOG: + { + DBVARIANT dbv; + BOOL startSkype; + int i; + + initDlg=TRUE; + TranslateDialogDefault(hwndDlg); + + startSkype=db_get_b(NULL, SKYPE_PROTONAME, "StartSkype", 1); + + CheckDlgButton(hwndDlg, IDC_STARTSKYPE, (BYTE)startSkype); + CheckDlgButton(hwndDlg, IDC_NOSPLASH, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "nosplash", 1)); + CheckDlgButton(hwndDlg, IDC_MINIMIZED, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "minimized", 1)); + CheckDlgButton(hwndDlg, IDC_NOTRAY, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "notray", 0)); + CheckDlgButton(hwndDlg, IDC_REMOVEABLE, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "removable", 0)); + CheckDlgButton(hwndDlg, IDC_SECONDARY, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "secondary", 0)); + CheckDlgButton(hwndDlg, IDC_DATAPATHO, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "datapath:", 0)); + CheckDlgButton(hwndDlg, IDC_SHUTDOWN, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "Shutdown", 0)); + CheckDlgButton(hwndDlg, IDC_UNLOADOFFLINE, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "UnloadOnOffline", 0)); + + CheckDlgButton(hwndDlg, IDC_CUSTOMCOMMAND, (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "UseCustomCommand", 0)); + SendDlgItemMessage(hwndDlg, IDC_COMMANDLINE, EM_SETLIMITTEXT, MAX_PATH-1, 0L); + if(!db_get_s(NULL,SKYPE_PROTONAME,"CommandLine",&dbv)) + { + SetWindowTextA(GetDlgItem(hwndDlg, IDC_COMMANDLINE), dbv.pszVal); + db_free(&dbv); + } + + SendDlgItemMessage(hwndDlg, IDC_DATAPATH, EM_SETLIMITTEXT, MAX_PATH-1, 0L); + if(!db_get_s(NULL,SKYPE_PROTONAME,"datapath",&dbv)) + { + SetWindowTextA(GetDlgItem(hwndDlg, IDC_DATAPATH), dbv.pszVal); + db_free(&dbv); + } + + for(i=0; i < sizeof(skypeLaunchControls)/sizeof(skypeLaunchControls[0]); i++) + EnableWindow(GetDlgItem(hwndDlg, skypeLaunchControls[i]), startSkype); + + EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSECMDL), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0)); + EnableWindow(GetDlgItem(hwndDlg, IDC_COMMANDLINE), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0)); + + EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSEDP), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0)); + EnableWindow(GetDlgItem(hwndDlg, IDC_DATAPATH), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0)); + + // LoginUserName + if(!db_get_ts(NULL,SKYPE_PROTONAME,"LoginUserName",&dbv)) + { + SetWindowText(GetDlgItem(hwndDlg, IDC_USERNAME), dbv.ptszVal); + db_free(&dbv); + } + + // LoginPassword + if(!db_get_ts(NULL,SKYPE_PROTONAME,"LoginPassword",&dbv)) + { + SetWindowText(GetDlgItem(hwndDlg, IDC_PASSWORD), dbv.ptszVal); + db_free(&dbv); + } + + SendDlgItemMessage(hwndDlg, IDC_CONNATTEMPTS, EM_SETLIMITTEXT, 3, 0L); + SetDlgItemInt (hwndDlg, IDC_CONNATTEMPTS, db_get_w(NULL, SKYPE_PROTONAME, "ConnectionAttempts", 10), FALSE); + SendMessage(hwndDlg, WM_COMMAND, IDC_STARTSKYPE, 0); + initDlg=FALSE; + return TRUE; + } + case WM_NOTIFY: { + NMHDR* nmhdr = (NMHDR*)lParam; + + switch (nmhdr->code){ + case PSN_APPLY: + case PSN_KILLACTIVE: + { + char text[500]; + TCHAR wtext[500]; + char szRelativePath[MAX_PATH]; + + db_set_b (NULL, SKYPE_PROTONAME, "StartSkype", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_STARTSKYPE), BM_GETCHECK,0,0))); + db_set_b (NULL, SKYPE_PROTONAME, "nosplash", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_NOSPLASH), BM_GETCHECK,0,0))); + db_set_b (NULL, SKYPE_PROTONAME, "minimized", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_MINIMIZED), BM_GETCHECK,0,0))); + db_set_b (NULL, SKYPE_PROTONAME, "notray", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_NOTRAY), BM_GETCHECK,0,0))); + db_set_b (NULL, SKYPE_PROTONAME, "Shutdown", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_SHUTDOWN), BM_GETCHECK,0,0))); + db_set_b (NULL, SKYPE_PROTONAME, "UnloadOnOffline", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_UNLOADOFFLINE), BM_GETCHECK,0,0))); + db_set_w (NULL, SKYPE_PROTONAME, "ConnectionAttempts", (unsigned short)GetDlgItemInt(hwndDlg, IDC_CONNATTEMPTS, NULL, FALSE)); + db_set_b (NULL, SKYPE_PROTONAME, "UseCustomCommand", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0))); + db_set_b (NULL, SKYPE_PROTONAME, "datapath:", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0))); + db_set_b (NULL, SKYPE_PROTONAME, "removable", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_REMOVEABLE), BM_GETCHECK,0,0))); + db_set_b (NULL, SKYPE_PROTONAME, "secondary", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_SECONDARY), BM_GETCHECK,0,0))); + + GetDlgItemTextA(hwndDlg,IDC_COMMANDLINE,text,sizeof(text)); + strncpy(szRelativePath, text, sizeof(szRelativePath)-1); + CallService (MS_UTILS_PATHTORELATIVE, (WPARAM)text, (LPARAM)szRelativePath); + db_set_s(NULL, SKYPE_PROTONAME, "CommandLine", szRelativePath); + + GetDlgItemTextA(hwndDlg,IDC_DATAPATH,text,sizeof(text)); + strncpy(szRelativePath, text, sizeof(szRelativePath)-1); + CallService (MS_UTILS_PATHTORELATIVE, (WPARAM)text, (LPARAM)szRelativePath); + db_set_s(NULL, SKYPE_PROTONAME, "datapath", szRelativePath); + + // LoginUserName + GetDlgItemText(hwndDlg,IDC_USERNAME,wtext,sizeof(wtext)/sizeof(TCHAR)); + db_set_ts(NULL, SKYPE_PROTONAME, "LoginUserName", wtext); + + // LoginPassword + GetDlgItemText(hwndDlg,IDC_PASSWORD,wtext,sizeof(wtext)/sizeof(TCHAR)); + db_set_ts(NULL, SKYPE_PROTONAME, "LoginPassword", wtext); + + return TRUE; + } + } + break; + } + case WM_COMMAND: { + switch (LOWORD(wParam)) { + BOOL startSkype; + int i; + case IDC_STARTSKYPE: + startSkype=SendMessage(GetDlgItem(hwndDlg, IDC_STARTSKYPE), BM_GETCHECK,0,0); + + for(i=0; i < sizeof(skypeLaunchControls)/sizeof(skypeLaunchControls[0]); i++) + EnableWindow(GetDlgItem(hwndDlg, skypeLaunchControls[i]), startSkype); + + EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSECMDL), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0)); + EnableWindow(GetDlgItem(hwndDlg, IDC_COMMANDLINE), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0)); + + EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSEDP), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0)); + EnableWindow(GetDlgItem(hwndDlg, IDC_DATAPATH), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0)); + break; + case IDC_CLEANUP: + pthread_create(( pThreadFunc )CleanupNicknames, NULL); + break; + case IDC_DATAPATHO: + EnableWindow(GetDlgItem(hwndDlg, IDC_DATAPATH), SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0)); + EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSEDP), SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0)); + break; + case IDC_CUSTOMCOMMAND: + EnableWindow(GetDlgItem(hwndDlg, IDC_COMMANDLINE), SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0)); + EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSECMDL), SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0)); + break; + case IDC_BROWSECMDL: + { + OPENFILENAMEA ofn={0}; + BOOL gofnResult; + char szFileName[MAX_PATH]; + char szAbsolutePath[MAX_PATH]; + + ofn.lStructSize=sizeof(ofn); + ofn.hwndOwner=hwndDlg; + ofn.lpstrFilter="Executable files (*.exe)\0*.exe\0All files (*.*)\0*.*\0"; + ofn.nMaxFile=sizeof(szFileName); + ofn.lpstrDefExt="exe"; + ofn.lpstrFile=szFileName; + ofn.Flags=OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_ENABLESIZING; + + GetDlgItemTextA(hwndDlg,IDC_COMMANDLINE,szFileName,sizeof(szFileName)); + TranslateMirandaRelativePathToAbsolute(szFileName, szAbsolutePath, FALSE); + strcpy (szFileName, szAbsolutePath); + + if (!(gofnResult = GetOpenFileNameA(&ofn)) && CommDlgExtendedError() == FNERR_INVALIDFILENAME){ + strcpy(szFileName, ".\\Skype.exe"); + TranslateMirandaRelativePathToAbsolute(szFileName, szAbsolutePath, FALSE); + strcpy (szFileName, szAbsolutePath); + gofnResult = GetOpenFileNameA(&ofn); + } + + if(gofnResult) + SetWindowTextA(GetDlgItem(hwndDlg, IDC_COMMANDLINE), szFileName); + + break; + } + case IDC_BROWSEDP: + { + BROWSEINFOA bi={0}; + LPITEMIDLIST pidl; + char szFileName[MAX_PATH]; + char szAbsolutePath[MAX_PATH]; + + GetDlgItemTextA (hwndDlg, IDC_DATAPATH, szFileName, MAX_PATH); + + TranslateMirandaRelativePathToAbsolute(szFileName, szAbsolutePath, FALSE); + bi.hwndOwner = hwndDlg; + bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_SHAREABLE | BIF_NEWDIALOGSTYLE | BIF_NONEWFOLDERBUTTON; + bi.lpfn = BrowseCallbackProc; + bi.lParam = (LPARAM)szAbsolutePath; + + if ( (pidl = SHBrowseForFolderA (&bi)) ) { + if (SHGetPathFromIDListA (pidl, szFileName)) + SetDlgItemTextA (hwndDlg, IDC_DATAPATH, szFileName); + CoTaskMemFree (pidl); + } + break; + } + +#ifdef SKYPE_AUTO_DETECTION + case IDC_AUTODETECTION: + DoAutoDetect(hwndDlg); + break; +#endif + } + if (!initDlg) SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + } + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// OnDetailsInit - initializes user info dialog pages. + +int OnDetailsInit( WPARAM wParam, LPARAM lParam ) +{ + OPTIONSDIALOGPAGE odp = {0}; + MCONTACT hContact = (MCONTACT)lParam; + + odp.cbSize = sizeof(odp); + odp.hIcon = NULL; + odp.hInstance = hInst; + + if ( hContact == NULL ) { + + char szTitle[256]; + + if (mirandaVersion < PLUGIN_MAKE_VERSION(0, 7, 0, 27) && !bIsImoproxy) + { + mir_snprintf( szTitle, sizeof( szTitle ), "%s %s", SKYPE_PROTONAME, Translate( "Avatar" )); + + odp.pfnDlgProc = AvatarDlgProc; + odp.position = 1900000000; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_SETAVATAR); + odp.pszTitle = szTitle; + UserInfo_AddPage(wParam, &odp); + } + + mir_snprintf( szTitle, sizeof( szTitle ), "%s %s", SKYPE_PROTONAME, Translate( "Details" )); + + odp.pfnDlgProc = DetailsDlgProc; + odp.position = 1900000000; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_SETDETAILS); + odp.pszTitle = szTitle; + UserInfo_AddPage(wParam, &odp); + } + + return 0; +} + +/*AvatarDlgProc +* +* For setting the skype avatar +* +*/ +INT_PTR CALLBACK AvatarDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static RECT r; + + UNREFERENCED_PARAMETER(lParam); + + switch ( msg ) { + case WM_INITDIALOG: + TranslateDialogDefault( hwndDlg ); + + hAvatar = NULL; + if(ServiceExists(MS_AV_GETMYAVATAR)){ + struct avatarCacheEntry *ace = (struct avatarCacheEntry *)CallService(MS_AV_GETMYAVATAR, 0,(LPARAM) SKYPE_PROTONAME); + if (ace!=NULL) { + hAvatar = ( HBITMAP )CallService( MS_UTILS_LOADBITMAP, 0, ( LPARAM )ace->szFilename); + if ( hAvatar != NULL ) + SendDlgItemMessage(hwndDlg, IDC_AVATAR, STM_SETIMAGE, IMAGE_BITMAP, (WPARAM)hAvatar ); + } + } + + + + return TRUE; + + case WM_COMMAND: + if ( HIWORD( wParam ) == BN_CLICKED ) { + switch( LOWORD( wParam )) { + case IDC_SETAVATAR: + { + char szFileName[ MAX_PATH ]; + if ( EnterBitmapFileName( szFileName ) != ERROR_SUCCESS ) + return FALSE; + + hAvatar = ( HBITMAP )CallService( MS_UTILS_LOADBITMAP, 0, ( LPARAM )szFileName); + if ( hAvatar != NULL ){ + SendDlgItemMessage(hwndDlg, IDC_AVATAR, STM_SETIMAGE, IMAGE_BITMAP, (WPARAM)hAvatar ); + CallService(SKYPE_SETAVATAR, 0, ( LPARAM )szFileName); + } + break; + } + case IDC_DELETEAVATAR: + if ( hAvatar != NULL ) { + DeleteObject( hAvatar ); + hAvatar = NULL; + CallService(SKYPE_SETAVATAR, 0, 0); + } + db_unset( NULL, SKYPE_PROTONAME, "AvatarFile" ); + InvalidateRect( hwndDlg, NULL, TRUE ); + break; + } } + break; + + case WM_DESTROY: + if ( hAvatar != NULL ) + DeleteObject( hAvatar ); + break; + } + + return 0; +} + +/*DetailsDlgProc +* +* For setting the skype infos +* +*/ +INT_PTR CALLBACK DetailsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static int sexM = 0,sexF = 0, sex; + + UNREFERENCED_PARAMETER(lParam); + + switch ( msg ) { + case WM_INITDIALOG: + TranslateDialogDefault( hwndDlg ); + + ZeroMemory (&myProfile, sizeof(myProfile)); + SkypeProfile_Load(&myProfile); + if(SkypeInitialized) + SkypeProfile_LoadFromSkype(&myProfile); + + SendDlgItemMessage(hwndDlg,IDC_SEX,CB_ADDSTRING,0,(LPARAM)_T("")); + sexM = SendDlgItemMessage(hwndDlg,IDC_SEX,CB_ADDSTRING,0,(LPARAM)TranslateT("MALE")); + sexF = SendDlgItemMessage(hwndDlg,IDC_SEX,CB_ADDSTRING,0,(LPARAM)TranslateT("FEMALE")); + + switch(myProfile.Sex) { + case 0x4D: SendDlgItemMessage(hwndDlg,IDC_SEX,CB_SETCURSEL, sexM, 0); break; + case 0x46: SendDlgItemMessage(hwndDlg,IDC_SEX,CB_SETCURSEL, sexF, 0); break; + } + + SetDlgItemText(hwndDlg, IDC_FULLNAME, myProfile.FullName); + SetDlgItemTextA(hwndDlg, IDC_HOMEPAGE, myProfile.HomePage); + SetDlgItemTextA(hwndDlg, IDC_HOMEPHONE, myProfile.HomePhone); + SetDlgItemTextA(hwndDlg, IDC_OFFICEPHONE, myProfile.OfficePhone); + SetDlgItemText(hwndDlg, IDC_CITY, myProfile.City); + SetDlgItemText(hwndDlg, IDC_PROVINCE, myProfile.Province); + DateTime_SetSystemtime (GetDlgItem (hwndDlg, IDC_BIRTHDAY), GDT_VALID, &myProfile.Birthday); + return TRUE; + + case WM_COMMAND: + if ( HIWORD( wParam ) == BN_CLICKED ) { + switch( LOWORD( wParam )) { + case IDC_SAVEDETAILS: + GetDlgItemText(hwndDlg,IDC_FULLNAME,myProfile.FullName,sizeof(myProfile.FullName)/sizeof(TCHAR)); + GetDlgItemTextA(hwndDlg,IDC_HOMEPAGE,myProfile.HomePage,sizeof(myProfile.HomePage)/sizeof(TCHAR)); + GetDlgItemTextA(hwndDlg,IDC_HOMEPHONE,myProfile.HomePhone,sizeof(myProfile.HomePhone)/sizeof(TCHAR)); + GetDlgItemTextA(hwndDlg,IDC_OFFICEPHONE,myProfile.OfficePhone,sizeof(myProfile.OfficePhone)/sizeof(TCHAR)); + GetDlgItemText(hwndDlg,IDC_CITY,myProfile.City,sizeof(myProfile.City)/sizeof(TCHAR)); + GetDlgItemText(hwndDlg,IDC_PROVINCE,myProfile.Province,sizeof(myProfile.Province)/sizeof(TCHAR)); + sex = SendMessage(GetDlgItem(hwndDlg,IDC_SEX),CB_GETCURSEL,0,0); + + myProfile.Sex = 0; + if(sex == sexF) myProfile.Sex = 0x46; else + if(sex == sexM) myProfile.Sex = 0x4D; + DateTime_GetSystemtime (GetDlgItem (hwndDlg, IDC_BIRTHDAY), &myProfile.Birthday); + + SkypeProfile_Save(&myProfile); + if(SkypeInitialized) + SkypeProfile_SaveToSkype(&myProfile); + break; + } + } + break; + + case WM_DESTROY: + if ( hAvatar != NULL ) + DeleteObject( hAvatar ); + break; + } + + return 0; +} + +#ifdef SKYPE_AUTO_DETECTION +/** + * DoAutoDetect + * @param dlg The default option dialog handle + */ +void DoAutoDetect(HWND dlg) +{ + char basePath[MAX_PATH]; + char fileName[MAX_PATH]; + char tmpUser[255]; + ezxml_t f1, acc; + + if (FAILED(SHGetFolderPath(dlg,CSIDL_APPDATA,NULL,0,basePath))) + { + OUTPUT("Error in retrieving appdata path!"); + return; + } + + strcat(basePath,"\\Skype\\"); + sprintf (fileName, "%s\\shared.xml", basePath); + + if (f1 = ezxml_parse_file(fileName)) + { + if (acc = ezxml_get(f1, "Lib", 0, "Account", 0, "Default", -1)) + { + if (GetWindowTextA(GetDlgItem(dlg,IDC_USERNAME),tmpUser,sizeof(tmpUser))) + SetWindowTextA(GetDlgItem(dlg,IDC_USERNAME),acc->txt); + /* Can't find this stuff in current Skype verions?? + sprintf (fileName, "%s\\%s\\config.xml", basePath, acc->txt); + if ((acc = ezxml_get(f1, "UI", 0, "Messages", 0, "OpenWindowInCompactMode", -1)) && *acc->txt!='0') + { + ezxml_set_txt (acc, "0"); + // ezXML doesn't supprot saving yet + } + */ + } + ezxml_free(f1); + } + else + { + OUTPUT("Failed to open skypes configuration files!"); + return; + } +} +#endif diff --git a/protocols/SkypeClassic/src/skypeprofile.c b/protocols/SkypeClassic/src/skypeprofile.c deleted file mode 100644 index 168dbfa97c..0000000000 --- a/protocols/SkypeClassic/src/skypeprofile.c +++ /dev/null @@ -1,145 +0,0 @@ -#pragma warning (disable: 4706) // assignment within conditional expression - -#include "skypeprofile.h" -#include "skypeapi.h" -#include "utf8.h" - -extern char g_szProtoName[]; - -void SkypeProfile_Save(SkypeProfile *pstProf) -{ - db_set_b(NULL, SKYPE_PROTONAME, "Gender", pstProf->Sex); - db_set_s(NULL, SKYPE_PROTONAME, "HomePhone", pstProf->HomePhone); - db_set_s(NULL, SKYPE_PROTONAME, "OfficePhone", pstProf->OfficePhone); - db_set_s(NULL, SKYPE_PROTONAME, "HomePage", pstProf->HomePage); - db_set_ts(NULL, SKYPE_PROTONAME, "Nick", pstProf->FullName); - db_set_ts(NULL, SKYPE_PROTONAME, "City", pstProf->City); - db_set_ts(NULL, SKYPE_PROTONAME, "Province", pstProf->Province); - db_set_w(NULL, SKYPE_PROTONAME, "BirthYear", (WORD)pstProf->Birthday.wYear); - db_set_b(NULL, SKYPE_PROTONAME, "BirthMonth", (BYTE)pstProf->Birthday.wMonth); - db_set_b(NULL, SKYPE_PROTONAME, "BirthDay", (BYTE)pstProf->Birthday.wDay); -} - -void SkypeProfile_Load(SkypeProfile *pstProf) -{ - DBVARIANT dbv; - - pstProf->Sex = (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "Gender", 0); - pstProf->Birthday.wYear = (WORD)db_get_w(NULL, SKYPE_PROTONAME, "BirthYear", 1900); - pstProf->Birthday.wMonth = (WORD)db_get_b(NULL, SKYPE_PROTONAME, "BirthMonth", 01); - pstProf->Birthday.wDay = (WORD)db_get_b(NULL, SKYPE_PROTONAME, "BirthDay", 01); - if(!db_get_ts(NULL,SKYPE_PROTONAME,"Nick",&dbv)) - { - _tcsncpy (pstProf->FullName, dbv.ptszVal, sizeof(pstProf->FullName)/sizeof(TCHAR)); - db_free(&dbv); - } - if(!db_get_s(NULL,SKYPE_PROTONAME,"HomePage",&dbv)) - { - strncpy (pstProf->HomePage, dbv.pszVal, sizeof(pstProf->HomePage)); - db_free(&dbv); - } - if(!db_get_ts(NULL,SKYPE_PROTONAME,"Province",&dbv)) - { - _tcsncpy (pstProf->Province, dbv.ptszVal, sizeof(pstProf->Province)/sizeof(TCHAR)); - db_free(&dbv); - } - if(!db_get_ts(NULL,SKYPE_PROTONAME,"City",&dbv)) - { - _tcsncpy (pstProf->City, dbv.ptszVal, sizeof(pstProf->City)/sizeof(TCHAR)); - db_free(&dbv); - } - if(!db_get_s(NULL,SKYPE_PROTONAME,"OfficePhone",&dbv)) - { - strncpy (pstProf->OfficePhone, dbv.pszVal, sizeof(pstProf->OfficePhone)); - db_free(&dbv); - } - if(!db_get_s(NULL,SKYPE_PROTONAME,"HomePhone",&dbv)) - { - strncpy (pstProf->HomePhone, dbv.pszVal, sizeof(pstProf->HomePhone)); - db_free(&dbv); - } -} - -static void LoadSaveSkype(SkypeProfile *pstProf, BOOL bSet) -{ -#pragma warning (push) -#pragma warning (disable: 4204) // nonstandard extension used : non-constant aggregate initializer -#define ENTRY(x,y) {x, pstProf->y, sizeof(pstProf->y)/sizeof(pstProf->y[0]), sizeof(pstProf->y[0])} - const struct { - char *pszSetting; - LPVOID lpDest; - int iSize; - char cType; - } astSettings[] = { - ENTRY("FULLNAME", FullName), - ENTRY("PHONE_HOME", HomePhone), - ENTRY("PHONE_OFFICE", OfficePhone), - ENTRY("HOMEPAGE", HomePage), - ENTRY("CITY", City), - ENTRY("PROVINCE", Province) - }; -#pragma warning (pop) -#undef ENTRY - char *ptr; - int i; - - if (bSet) { - char *pBuf, szBirthday[16]; - for (i=0; iSex) - { - case 0x4D: SkypeSetProfile ("SEX", "MALE"); break; - case 0x46: SkypeSetProfile ("SEX", "FEMALE"); break; - } - sprintf (szBirthday, "%04d%02d%02d", pstProf->Birthday.wYear, pstProf->Birthday.wMonth, pstProf->Birthday.wDay); - SkypeSetProfile ("BIRTHDAY", szBirthday); - } else { - for (i=0; iSex=0x4D; else - if (!_stricmp(ptr, "FEMALE")) pstProf->Sex=0x46; - free (ptr); - } - if (ptr=SkypeGetProfile("BIRTHDAY")) - { - if (*ptr != '0') - sscanf(ptr, "%04hd%02hd%02hd", &pstProf->Birthday.wYear, &pstProf->Birthday.wMonth, - &pstProf->Birthday.wDay); - free(ptr); - } - } -} - -void SkypeProfile_LoadFromSkype(SkypeProfile *pstProf) -{ - LoadSaveSkype (pstProf, FALSE); -} - -void SkypeProfile_SaveToSkype(SkypeProfile *pstProf) -{ - LoadSaveSkype (pstProf, TRUE); -} \ No newline at end of file diff --git a/protocols/SkypeClassic/src/skypeprofile.cpp b/protocols/SkypeClassic/src/skypeprofile.cpp new file mode 100644 index 0000000000..168dbfa97c --- /dev/null +++ b/protocols/SkypeClassic/src/skypeprofile.cpp @@ -0,0 +1,145 @@ +#pragma warning (disable: 4706) // assignment within conditional expression + +#include "skypeprofile.h" +#include "skypeapi.h" +#include "utf8.h" + +extern char g_szProtoName[]; + +void SkypeProfile_Save(SkypeProfile *pstProf) +{ + db_set_b(NULL, SKYPE_PROTONAME, "Gender", pstProf->Sex); + db_set_s(NULL, SKYPE_PROTONAME, "HomePhone", pstProf->HomePhone); + db_set_s(NULL, SKYPE_PROTONAME, "OfficePhone", pstProf->OfficePhone); + db_set_s(NULL, SKYPE_PROTONAME, "HomePage", pstProf->HomePage); + db_set_ts(NULL, SKYPE_PROTONAME, "Nick", pstProf->FullName); + db_set_ts(NULL, SKYPE_PROTONAME, "City", pstProf->City); + db_set_ts(NULL, SKYPE_PROTONAME, "Province", pstProf->Province); + db_set_w(NULL, SKYPE_PROTONAME, "BirthYear", (WORD)pstProf->Birthday.wYear); + db_set_b(NULL, SKYPE_PROTONAME, "BirthMonth", (BYTE)pstProf->Birthday.wMonth); + db_set_b(NULL, SKYPE_PROTONAME, "BirthDay", (BYTE)pstProf->Birthday.wDay); +} + +void SkypeProfile_Load(SkypeProfile *pstProf) +{ + DBVARIANT dbv; + + pstProf->Sex = (BYTE)db_get_b(NULL, SKYPE_PROTONAME, "Gender", 0); + pstProf->Birthday.wYear = (WORD)db_get_w(NULL, SKYPE_PROTONAME, "BirthYear", 1900); + pstProf->Birthday.wMonth = (WORD)db_get_b(NULL, SKYPE_PROTONAME, "BirthMonth", 01); + pstProf->Birthday.wDay = (WORD)db_get_b(NULL, SKYPE_PROTONAME, "BirthDay", 01); + if(!db_get_ts(NULL,SKYPE_PROTONAME,"Nick",&dbv)) + { + _tcsncpy (pstProf->FullName, dbv.ptszVal, sizeof(pstProf->FullName)/sizeof(TCHAR)); + db_free(&dbv); + } + if(!db_get_s(NULL,SKYPE_PROTONAME,"HomePage",&dbv)) + { + strncpy (pstProf->HomePage, dbv.pszVal, sizeof(pstProf->HomePage)); + db_free(&dbv); + } + if(!db_get_ts(NULL,SKYPE_PROTONAME,"Province",&dbv)) + { + _tcsncpy (pstProf->Province, dbv.ptszVal, sizeof(pstProf->Province)/sizeof(TCHAR)); + db_free(&dbv); + } + if(!db_get_ts(NULL,SKYPE_PROTONAME,"City",&dbv)) + { + _tcsncpy (pstProf->City, dbv.ptszVal, sizeof(pstProf->City)/sizeof(TCHAR)); + db_free(&dbv); + } + if(!db_get_s(NULL,SKYPE_PROTONAME,"OfficePhone",&dbv)) + { + strncpy (pstProf->OfficePhone, dbv.pszVal, sizeof(pstProf->OfficePhone)); + db_free(&dbv); + } + if(!db_get_s(NULL,SKYPE_PROTONAME,"HomePhone",&dbv)) + { + strncpy (pstProf->HomePhone, dbv.pszVal, sizeof(pstProf->HomePhone)); + db_free(&dbv); + } +} + +static void LoadSaveSkype(SkypeProfile *pstProf, BOOL bSet) +{ +#pragma warning (push) +#pragma warning (disable: 4204) // nonstandard extension used : non-constant aggregate initializer +#define ENTRY(x,y) {x, pstProf->y, sizeof(pstProf->y)/sizeof(pstProf->y[0]), sizeof(pstProf->y[0])} + const struct { + char *pszSetting; + LPVOID lpDest; + int iSize; + char cType; + } astSettings[] = { + ENTRY("FULLNAME", FullName), + ENTRY("PHONE_HOME", HomePhone), + ENTRY("PHONE_OFFICE", OfficePhone), + ENTRY("HOMEPAGE", HomePage), + ENTRY("CITY", City), + ENTRY("PROVINCE", Province) + }; +#pragma warning (pop) +#undef ENTRY + char *ptr; + int i; + + if (bSet) { + char *pBuf, szBirthday[16]; + for (i=0; iSex) + { + case 0x4D: SkypeSetProfile ("SEX", "MALE"); break; + case 0x46: SkypeSetProfile ("SEX", "FEMALE"); break; + } + sprintf (szBirthday, "%04d%02d%02d", pstProf->Birthday.wYear, pstProf->Birthday.wMonth, pstProf->Birthday.wDay); + SkypeSetProfile ("BIRTHDAY", szBirthday); + } else { + for (i=0; iSex=0x4D; else + if (!_stricmp(ptr, "FEMALE")) pstProf->Sex=0x46; + free (ptr); + } + if (ptr=SkypeGetProfile("BIRTHDAY")) + { + if (*ptr != '0') + sscanf(ptr, "%04hd%02hd%02hd", &pstProf->Birthday.wYear, &pstProf->Birthday.wMonth, + &pstProf->Birthday.wDay); + free(ptr); + } + } +} + +void SkypeProfile_LoadFromSkype(SkypeProfile *pstProf) +{ + LoadSaveSkype (pstProf, FALSE); +} + +void SkypeProfile_SaveToSkype(SkypeProfile *pstProf) +{ + LoadSaveSkype (pstProf, TRUE); +} \ No newline at end of file diff --git a/protocols/SkypeClassic/src/skypesvc.c b/protocols/SkypeClassic/src/skypesvc.c deleted file mode 100644 index df9ed9595f..0000000000 --- a/protocols/SkypeClassic/src/skypesvc.c +++ /dev/null @@ -1,187 +0,0 @@ -#define __SKYPESVC_C__ -#include "skype.h" -#include "skypesvc.h" -#include "skypeapi.h" -#include "skypeopt.h" -#include "contacts.h" -#include "m_toptoolbar.h" - -// Exports -SKYPE_SVCNAMES g_svcNames; - -//From skype.c -extern char protocol, g_szProtoName[]; -extern HINSTANCE hInst; -extern DWORD mirandaVersion; -static HANDLE m_hPrebuildCMenu=NULL, m_hStatusHookContact=NULL, m_hContactDeleted=NULL, - m_hHookModulesLoaded=NULL, m_hHookOkToExit=NULL, m_hOptHook=NULL, m_hHookMirandaExit=NULL, - m_hTTBModuleLoadedHook = NULL, m_hHookOnUserInfoInit = NULL; - -void CreateProtoService(const char* szService, MIRANDASERVICE svc) -{ - char str[MAXMODULELABELLENGTH]; - _snprintf(str, sizeof(str), "%s%s", SKYPE_PROTONAME, szService); - CreateServiceFunction(str, svc); -} - -#define CreateServiceName(srvce) _snprintf (g_svcNames.##srvce, sizeof(g_svcNames.##srvce), "%s/"#srvce, SKYPE_PROTONAME); - -void CreateServices(void) -{ - CreateServiceName(ChatNew); - CreateServiceName(SetAvatar); - CreateServiceName(SendFile); - CreateServiceName(HoldCall); - CreateServiceName(AnswerCall); - CreateServiceName(ImportHistory); - CreateServiceName(AddUser); - CreateServiceName(SkypeOutCallUser); - CreateServiceName(CallHangupUser); - CreateServiceName(CallUser); - - CreateServiceFunction(SKYPE_CALL, SkypeCall); - CreateServiceFunction(SKYPE_CALLHANGUP, SkypeCallHangup); - CreateServiceFunction(SKYPEOUT_CALL, SkypeOutCall); - CreateServiceFunction(SKYPE_HOLDCALL, SkypeHoldCall); - CreateServiceFunction(SKYPE_ADDUSER, SkypeAdduserDlg); - CreateServiceFunction(SKYPE_IMPORTHISTORY, ImportHistory); - CreateServiceFunction(SKYPE_ANSWERCALL, SkypeAnswerCall); - CreateServiceFunction(SKYPE_SENDFILE, SkypeSendFile); - CreateServiceFunction(SKYPE_SETAVATAR, SkypeSetAvatar); - - CreateProtoService(PS_GETCAPS, SkypeGetCaps); - CreateProtoService(PS_GETNAME, SkypeGetName); - CreateProtoService(PS_LOADICON, SkypeLoadIcon); - CreateProtoService(PS_SETSTATUS, SkypeSetStatus); - CreateProtoService(PS_GETSTATUS, SkypeGetStatus); - CreateProtoService(PS_ADDTOLIST, SkypeAddToList); - CreateProtoService(PS_ADDTOLISTBYEVENT, SkypeAddToListByEvent); - CreateProtoService(PS_BASICSEARCH, SkypeBasicSearch); - - CreateProtoService(PSS_GETINFO, SkypeGetInfo); - CreateProtoService(PSS_MESSAGE, SkypeSendMessage); - CreateProtoService(PSR_MESSAGE, SkypeRecvMessage); - CreateProtoService(PSS_USERISTYPING, SkypeUserIsTyping); - CreateProtoService(PSS_AUTHREQUEST, SkypeSendAuthRequest); - CreateProtoService(PSR_AUTH, SkypeRecvAuth); - CreateProtoService(PS_AUTHALLOW, SkypeAuthAllow); - CreateProtoService(PS_AUTHDENY, SkypeAuthDeny); - - CreateProtoService(PS_GETAVATARINFO, SkypeGetAvatarInfo); - CreateProtoService(PS_GETAVATARCAPS, SkypeGetAvatarCaps); - CreateProtoService(PS_GETMYAVATAR, SkypeGetAvatar); - CreateProtoService(PS_SETMYAVATAR, SkypeSetAvatar); - - CreateProtoService(PS_SETAWAYMSG, SkypeSetAwayMessage); - CreateProtoService(PS_SETAWAYMSGW, SkypeSetAwayMessageW); - CreateProtoService(PSS_GETAWAYMSG, SkypeGetAwayMessage); - CreateProtoService(PS_SETMYNICKNAME, SkypeSetNick); - - CreateProtoService(PSS_SKYPEAPIMSG, SkypeReceivedAPIMessage); - CreateProtoService(SKYPE_REGPROXY, SkypeRegisterProxy); -} - -void HookEvents(void) -{ - m_hPrebuildCMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, PrebuildContactMenu); - - //HookEvent(ME_CLIST_DOUBLECLICKED, ClistDblClick); - m_hOptHook = HookEvent(ME_OPT_INITIALISE, RegisterOptions); - m_hStatusHookContact = HookEvent(ME_DB_CONTACT_ADDED,HookContactAdded); - m_hContactDeleted = HookEvent( ME_DB_CONTACT_DELETED, HookContactDeleted ); - m_hHookModulesLoaded = HookEvent( ME_SYSTEM_MODULESLOADED, OnModulesLoaded); - m_hHookMirandaExit = HookEvent(ME_SYSTEM_OKTOEXIT, MirandaExit); - m_hHookOkToExit = HookEvent(ME_SYSTEM_PRESHUTDOWN, OkToExit); -} - -void HookEventsLoaded(void) -{ - // We cannot check for the TTB-service before this event gets fired... :-/ - m_hTTBModuleLoadedHook = HookEvent(ME_TTB_MODULELOADED, CreateTopToolbarButton); - m_hHookOnUserInfoInit = HookEvent( ME_USERINFO_INITIALISE, OnDetailsInit ); -} - -void UnhookEvents(void) -{ - UnhookEvent(m_hOptHook); - UnhookEvent(m_hTTBModuleLoadedHook); - UnhookEvent(m_hHookOnUserInfoInit); - UnhookEvent(m_hStatusHookContact); - UnhookEvent(m_hContactDeleted); - UnhookEvent(m_hHookModulesLoaded); - UnhookEvent(m_hPrebuildCMenu); - UnhookEvent(m_hHookOkToExit); - UnhookEvent(m_hHookMirandaExit); - //UnhookEvent(ClistDblClick); -} - -INT_PTR SkypeGetCaps(WPARAM wParam, LPARAM lParam) { - int ret = 0; - - UNREFERENCED_PARAMETER(lParam); - - switch (wParam) { - case PFLAGNUM_1: - ret = PF1_BASICSEARCH | PF1_IM | PF1_MODEMSG; // | PF1_AUTHREQ; - if (protocol>=5) ret |= PF1_ADDSEARCHRES; - break; - - case PFLAGNUM_2: - ret = PF2_ONLINE | PF2_SHORTAWAY | PF2_INVISIBLE | PF2_HEAVYDND; -#ifdef MAPDND - ret |= PF2_LIGHTDND | PF2_HEAVYDND; -#endif - if (!db_get_b(NULL, SKYPE_PROTONAME, "NoSkype3Stats", 0)) - ret |= PF2_LONGAWAY | PF2_FREECHAT; - break; - - case PFLAGNUM_3: - ret = PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND | PF2_FREECHAT | PF2_OUTTOLUNCH | PF2_ONTHEPHONE | PF2_IDLE; - break; - - case PFLAGNUM_4: - ret = PF4_FORCEAUTH | PF4_FORCEADDED | PF4_AVATARS | PF4_SUPPORTTYPING /* Not really, but libgaim compat. */; - if (mirandaVersion >= 0x070000) ret |= PF4_IMSENDUTF; - break; - case PFLAG_UNIQUEIDTEXT: - ret = (INT_PTR)Translate("Skype ID"); - break; - case PFLAG_UNIQUEIDSETTING: - ret = (INT_PTR) SKYPE_NAME; - break; - } - return ret; -} - -INT_PTR SkypeGetName(WPARAM wParam, LPARAM lParam) -{ - if (lParam) - { - strncpy((char *)lParam, SKYPE_PROTONAME, wParam); - return 0; // Success - } - return 1; // Failure -} - - -INT_PTR SkypeLoadIcon(WPARAM wParam,LPARAM lParam) -{ - UINT id; - - UNREFERENCED_PARAMETER(lParam); - - switch(wParam&0xFFFF) { - case PLI_PROTOCOL: id=IDI_SKYPE; break; // IDI_MAIN is the main icon for the protocol - default: return (int)(HICON)NULL; - } - return (int)LoadImage(hInst,MAKEINTRESOURCE(id),IMAGE_ICON,GetSystemMetrics(wParam&PLIF_SMALL?SM_CXSMICON:SM_CXICON),GetSystemMetrics(wParam&PLIF_SMALL?SM_CYSMICON:SM_CYICON),0); -} - -INT_PTR SkypeGetAvatar(WPARAM wParam,LPARAM lParam) -{ DBVARIANT dbv; - if (!db_get_s(NULL,SKYPE_PROTONAME, "AvatarFile", &dbv)){ - lstrcpynA((char*)wParam, dbv.pszVal, (int)lParam); - db_free(&dbv); - } - return 0; -} diff --git a/protocols/SkypeClassic/src/skypesvc.cpp b/protocols/SkypeClassic/src/skypesvc.cpp new file mode 100644 index 0000000000..df9ed9595f --- /dev/null +++ b/protocols/SkypeClassic/src/skypesvc.cpp @@ -0,0 +1,187 @@ +#define __SKYPESVC_C__ +#include "skype.h" +#include "skypesvc.h" +#include "skypeapi.h" +#include "skypeopt.h" +#include "contacts.h" +#include "m_toptoolbar.h" + +// Exports +SKYPE_SVCNAMES g_svcNames; + +//From skype.c +extern char protocol, g_szProtoName[]; +extern HINSTANCE hInst; +extern DWORD mirandaVersion; +static HANDLE m_hPrebuildCMenu=NULL, m_hStatusHookContact=NULL, m_hContactDeleted=NULL, + m_hHookModulesLoaded=NULL, m_hHookOkToExit=NULL, m_hOptHook=NULL, m_hHookMirandaExit=NULL, + m_hTTBModuleLoadedHook = NULL, m_hHookOnUserInfoInit = NULL; + +void CreateProtoService(const char* szService, MIRANDASERVICE svc) +{ + char str[MAXMODULELABELLENGTH]; + _snprintf(str, sizeof(str), "%s%s", SKYPE_PROTONAME, szService); + CreateServiceFunction(str, svc); +} + +#define CreateServiceName(srvce) _snprintf (g_svcNames.##srvce, sizeof(g_svcNames.##srvce), "%s/"#srvce, SKYPE_PROTONAME); + +void CreateServices(void) +{ + CreateServiceName(ChatNew); + CreateServiceName(SetAvatar); + CreateServiceName(SendFile); + CreateServiceName(HoldCall); + CreateServiceName(AnswerCall); + CreateServiceName(ImportHistory); + CreateServiceName(AddUser); + CreateServiceName(SkypeOutCallUser); + CreateServiceName(CallHangupUser); + CreateServiceName(CallUser); + + CreateServiceFunction(SKYPE_CALL, SkypeCall); + CreateServiceFunction(SKYPE_CALLHANGUP, SkypeCallHangup); + CreateServiceFunction(SKYPEOUT_CALL, SkypeOutCall); + CreateServiceFunction(SKYPE_HOLDCALL, SkypeHoldCall); + CreateServiceFunction(SKYPE_ADDUSER, SkypeAdduserDlg); + CreateServiceFunction(SKYPE_IMPORTHISTORY, ImportHistory); + CreateServiceFunction(SKYPE_ANSWERCALL, SkypeAnswerCall); + CreateServiceFunction(SKYPE_SENDFILE, SkypeSendFile); + CreateServiceFunction(SKYPE_SETAVATAR, SkypeSetAvatar); + + CreateProtoService(PS_GETCAPS, SkypeGetCaps); + CreateProtoService(PS_GETNAME, SkypeGetName); + CreateProtoService(PS_LOADICON, SkypeLoadIcon); + CreateProtoService(PS_SETSTATUS, SkypeSetStatus); + CreateProtoService(PS_GETSTATUS, SkypeGetStatus); + CreateProtoService(PS_ADDTOLIST, SkypeAddToList); + CreateProtoService(PS_ADDTOLISTBYEVENT, SkypeAddToListByEvent); + CreateProtoService(PS_BASICSEARCH, SkypeBasicSearch); + + CreateProtoService(PSS_GETINFO, SkypeGetInfo); + CreateProtoService(PSS_MESSAGE, SkypeSendMessage); + CreateProtoService(PSR_MESSAGE, SkypeRecvMessage); + CreateProtoService(PSS_USERISTYPING, SkypeUserIsTyping); + CreateProtoService(PSS_AUTHREQUEST, SkypeSendAuthRequest); + CreateProtoService(PSR_AUTH, SkypeRecvAuth); + CreateProtoService(PS_AUTHALLOW, SkypeAuthAllow); + CreateProtoService(PS_AUTHDENY, SkypeAuthDeny); + + CreateProtoService(PS_GETAVATARINFO, SkypeGetAvatarInfo); + CreateProtoService(PS_GETAVATARCAPS, SkypeGetAvatarCaps); + CreateProtoService(PS_GETMYAVATAR, SkypeGetAvatar); + CreateProtoService(PS_SETMYAVATAR, SkypeSetAvatar); + + CreateProtoService(PS_SETAWAYMSG, SkypeSetAwayMessage); + CreateProtoService(PS_SETAWAYMSGW, SkypeSetAwayMessageW); + CreateProtoService(PSS_GETAWAYMSG, SkypeGetAwayMessage); + CreateProtoService(PS_SETMYNICKNAME, SkypeSetNick); + + CreateProtoService(PSS_SKYPEAPIMSG, SkypeReceivedAPIMessage); + CreateProtoService(SKYPE_REGPROXY, SkypeRegisterProxy); +} + +void HookEvents(void) +{ + m_hPrebuildCMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, PrebuildContactMenu); + + //HookEvent(ME_CLIST_DOUBLECLICKED, ClistDblClick); + m_hOptHook = HookEvent(ME_OPT_INITIALISE, RegisterOptions); + m_hStatusHookContact = HookEvent(ME_DB_CONTACT_ADDED,HookContactAdded); + m_hContactDeleted = HookEvent( ME_DB_CONTACT_DELETED, HookContactDeleted ); + m_hHookModulesLoaded = HookEvent( ME_SYSTEM_MODULESLOADED, OnModulesLoaded); + m_hHookMirandaExit = HookEvent(ME_SYSTEM_OKTOEXIT, MirandaExit); + m_hHookOkToExit = HookEvent(ME_SYSTEM_PRESHUTDOWN, OkToExit); +} + +void HookEventsLoaded(void) +{ + // We cannot check for the TTB-service before this event gets fired... :-/ + m_hTTBModuleLoadedHook = HookEvent(ME_TTB_MODULELOADED, CreateTopToolbarButton); + m_hHookOnUserInfoInit = HookEvent( ME_USERINFO_INITIALISE, OnDetailsInit ); +} + +void UnhookEvents(void) +{ + UnhookEvent(m_hOptHook); + UnhookEvent(m_hTTBModuleLoadedHook); + UnhookEvent(m_hHookOnUserInfoInit); + UnhookEvent(m_hStatusHookContact); + UnhookEvent(m_hContactDeleted); + UnhookEvent(m_hHookModulesLoaded); + UnhookEvent(m_hPrebuildCMenu); + UnhookEvent(m_hHookOkToExit); + UnhookEvent(m_hHookMirandaExit); + //UnhookEvent(ClistDblClick); +} + +INT_PTR SkypeGetCaps(WPARAM wParam, LPARAM lParam) { + int ret = 0; + + UNREFERENCED_PARAMETER(lParam); + + switch (wParam) { + case PFLAGNUM_1: + ret = PF1_BASICSEARCH | PF1_IM | PF1_MODEMSG; // | PF1_AUTHREQ; + if (protocol>=5) ret |= PF1_ADDSEARCHRES; + break; + + case PFLAGNUM_2: + ret = PF2_ONLINE | PF2_SHORTAWAY | PF2_INVISIBLE | PF2_HEAVYDND; +#ifdef MAPDND + ret |= PF2_LIGHTDND | PF2_HEAVYDND; +#endif + if (!db_get_b(NULL, SKYPE_PROTONAME, "NoSkype3Stats", 0)) + ret |= PF2_LONGAWAY | PF2_FREECHAT; + break; + + case PFLAGNUM_3: + ret = PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND | PF2_FREECHAT | PF2_OUTTOLUNCH | PF2_ONTHEPHONE | PF2_IDLE; + break; + + case PFLAGNUM_4: + ret = PF4_FORCEAUTH | PF4_FORCEADDED | PF4_AVATARS | PF4_SUPPORTTYPING /* Not really, but libgaim compat. */; + if (mirandaVersion >= 0x070000) ret |= PF4_IMSENDUTF; + break; + case PFLAG_UNIQUEIDTEXT: + ret = (INT_PTR)Translate("Skype ID"); + break; + case PFLAG_UNIQUEIDSETTING: + ret = (INT_PTR) SKYPE_NAME; + break; + } + return ret; +} + +INT_PTR SkypeGetName(WPARAM wParam, LPARAM lParam) +{ + if (lParam) + { + strncpy((char *)lParam, SKYPE_PROTONAME, wParam); + return 0; // Success + } + return 1; // Failure +} + + +INT_PTR SkypeLoadIcon(WPARAM wParam,LPARAM lParam) +{ + UINT id; + + UNREFERENCED_PARAMETER(lParam); + + switch(wParam&0xFFFF) { + case PLI_PROTOCOL: id=IDI_SKYPE; break; // IDI_MAIN is the main icon for the protocol + default: return (int)(HICON)NULL; + } + return (int)LoadImage(hInst,MAKEINTRESOURCE(id),IMAGE_ICON,GetSystemMetrics(wParam&PLIF_SMALL?SM_CXSMICON:SM_CXICON),GetSystemMetrics(wParam&PLIF_SMALL?SM_CYSMICON:SM_CYICON),0); +} + +INT_PTR SkypeGetAvatar(WPARAM wParam,LPARAM lParam) +{ DBVARIANT dbv; + if (!db_get_s(NULL,SKYPE_PROTONAME, "AvatarFile", &dbv)){ + lstrcpynA((char*)wParam, dbv.pszVal, (int)lParam); + db_free(&dbv); + } + return 0; +} diff --git a/protocols/SkypeClassic/src/utf8.c b/protocols/SkypeClassic/src/utf8.c deleted file mode 100644 index 8ae746e871..0000000000 --- a/protocols/SkypeClassic/src/utf8.c +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright (C) 2001 Peter Harris - * Copyright (C) 2001 Edmund Grimley Evans - * - * 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 - */ - -/* - * Convert a string between UTF-8 and the locale's charset. - */ - -#include -#include - -#include "utf8.h" - -#ifdef _WIN32 - - /* Thanks to Peter Harris for this win32 - * code. - */ - -#include -#include - -unsigned char *make_utf8_string(const wchar_t *unicode) -{ - int size = 0, index = 0, out_index = 0; - unsigned char *out; - unsigned short c; - - /* first calculate the size of the target string */ - c = unicode[index++]; - while(c) { - if(c < 0x0080) { - size += 1; - } else if(c < 0x0800) { - size += 2; - } else { - size += 3; - } - c = unicode[index++]; - } - - out = (unsigned char *) malloc(size + 1); - if (out == NULL) - return NULL; - index = 0; - - c = unicode[index++]; - while(c) - { - if(c < 0x080) { - out[out_index++] = (unsigned char)c; - } else if(c < 0x800) { - #pragma warning (suppress: 4244) // conversion from 'int' to 'unsigned char', possible loss of data - out[out_index++] = 0xc0 | (c >> 6); - out[out_index++] = 0x80 | (c & 0x3f); - } else { - out[out_index++] = 0xe0 | (c >> 12); - out[out_index++] = 0x80 | ((c >> 6) & 0x3f); - out[out_index++] = 0x80 | (c & 0x3f); - } - c = unicode[index++]; - } - out[out_index] = 0x00; - - return out; -} - -wchar_t *make_unicode_string(const unsigned char *utf8) -{ - int size = 0, index = 0, out_index = 0; - wchar_t *out; - unsigned char c; - - /* first calculate the size of the target string */ - c = utf8[index++]; - while(c) { - if((c & 0x80) == 0) { - index += 0; - } else if((c & 0xe0) == 0xe0) { - index += 2; - } else { - index += 1; - } - size += 1; - c = utf8[index++]; - } - - out = (wchar_t *) malloc((size + 1) * sizeof(wchar_t)); - if (out == NULL) - return NULL; - index = 0; - - c = utf8[index++]; - while(c) - { - if((c & 0x80) == 0) { - out[out_index++] = c; - } else if((c & 0xe0) == 0xe0) { - out[out_index] = (c & 0x1F) << 12; - c = utf8[index++]; - out[out_index] |= (c & 0x3F) << 6; - c = utf8[index++]; - out[out_index++] |= (c & 0x3F); - } else { - out[out_index] = (c & 0x3F) << 6; - c = utf8[index++]; - out[out_index++] |= (c & 0x3F); - } - c = utf8[index++]; - } - out[out_index] = 0; - - return out; -} - -int utf8_encode(const char *from, char **to) -{ - wchar_t *unicode; - int wchars, err; - - wchars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from, strlen(from), NULL, 0); - - if(wchars == 0) - { -// fprintf(stderr, "Unicode translation error %d\n"), GetLastError(); - return -1; - } - - unicode = (wchar_t *) calloc(wchars + 1, sizeof(unsigned short)); - if(unicode == NULL) - { -// fprintf(stderr, "Out of memory processing string to UTF8\n"); - return -1; - } - - err = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from, strlen(from), unicode, wchars); - if(err != wchars) - { - free(unicode); -// fprintf(stderr, "Unicode translation error %d\n"), GetLastError(); - return -1; - } - - /* On NT-based windows systems, we could use WideCharToMultiByte(), but - * MS doesn't actually have a consistent API across win32. - */ - *to = (char *) make_utf8_string(unicode); - - free(unicode); - return 0; -} - -int utf8_decode(const char *from, char **to) -{ - wchar_t *unicode; - int chars, err; -// LPCPINFO lpCPInfo; - - /* On NT-based windows systems, we could use MultiByteToWideChar(CP_UTF8), but - * MS doesn't actually have a consistent API across win32. - */ - unicode = make_unicode_string( (const unsigned char *)from); - if(unicode == NULL) - { - fprintf(stderr, "Out of memory processing string from UTF8 to UNICODE16\n"); - return -1; - } - - //if(GetCPInfo(CP_ACP,lpCPInfo)) - { - - chars = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, NULL, 0, NULL, NULL); - } - /*else - { - chars = WideCharToMultiByte(GetConsoleCP(), WC_COMPOSITECHECK, unicode, -1, NULL, 0, NULL, NULL); - }*/ - - if(chars == 0) - { - fprintf(stderr, "Unicode translation error %ld\n", GetLastError()); - free(unicode); - return -1; - } - - *to = (char *) calloc(chars + 1, sizeof(unsigned char)); - if(*to == NULL) - { - fprintf(stderr, "Out of memory processing string to local charset\n"); - free(unicode); - return -1; - } - - //err = WideCharToMultiByte(GetConsoleCP(), WC_COMPOSITECHECK, unicode, -1, *to, chars, NULL, NULL); - err = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, *to, chars, NULL, NULL); - if(err != chars) - { - fprintf(stderr, "Unicode translation error %ld\n", GetLastError()); - free(unicode); - free(*to); - *to = NULL; - return -1; - } - - free(unicode); - return 0; -} - -#ifndef _UNICODE -char *make_tchar_string(const unsigned char *utf8) { - char *ret; - if (utf8_decode((const char*)utf8, &ret)==-1) return NULL; - return ret; -} -#endif - -#else /* End win32. Rest is for real operating systems */ - - -#ifdef HAVE_LANGINFO_CODESET -#include -#endif - -int iconvert(const char *fromcode, const char *tocode, - const char *from, size_t fromlen, - char **to, size_t *tolen); - -static char *current_charset = "BIG-5"; /* means "US-ASCII" */ - -void convert_set_charset(const char *charset) -{ - - if (!charset) - charset = getenv("CHARSET"); - -#ifdef HAVE_LANGINFO_CODESET - if (!charset) - charset = nl_langinfo(CODESET); -#endif - - free(current_charset); - current_charset = 0; - if (charset && *charset) - current_charset = _strdup(charset); -} - -static int convert_buffer(const char *fromcode, const char *tocode, - const char *from, size_t fromlen, - char **to, size_t *tolen) -{ - int ret = -1; - -#ifdef HAVE_ICONV - ret = iconvert(fromcode, tocode, from, fromlen, to, tolen); - if (ret != -1) - return ret; -#endif - -#ifndef HAVE_ICONV /* should be ifdef USE_CHARSET_CONVERT */ - ret = charset_convert(fromcode, tocode, from, fromlen, to, tolen); - if (ret != -1) - return ret; -#endif - - return ret; -} - -static int convert_string(const char *fromcode, const char *tocode, - const char *from, char **to, char replace) -{ - int ret; - size_t fromlen; - char *s; - - fromlen = lstrlen(from); - ret = convert_buffer(fromcode, tocode, from, fromlen, to, 0); - if (ret == -2) - return -1; - if (ret != -1) - return ret; - - s = malloc(fromlen + 1); - if (!s) - return -1; - lstrcpy(s, from); - *to = s; - for (; *s; s++) - if (*s & ~0x7f) - *s = replace; - return 3; -} - -int utf8_encode(const char *from, char **to) -{ - char *charset; - - if (!current_charset) - convert_set_charset(0); - charset = current_charset ? current_charset : "US-ASCII"; - return convert_string(charset, "UTF-8", from, to, '#'); -} - -int utf8_decode(const char *from, char **to) -{ - char *charset; - - if(*from == 0) { - *to = malloc(1); - **to = 0; - return 1; - } - - if (!current_charset) - convert_set_charset(0); - charset = current_charset ? current_charset : "US-ASCII"; - return convert_string("UTF-8", charset, from, to, '?'); -} - -#endif diff --git a/protocols/SkypeClassic/src/utf8.cpp b/protocols/SkypeClassic/src/utf8.cpp new file mode 100644 index 0000000000..8ae746e871 --- /dev/null +++ b/protocols/SkypeClassic/src/utf8.cpp @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2001 Peter Harris + * Copyright (C) 2001 Edmund Grimley Evans + * + * 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 + */ + +/* + * Convert a string between UTF-8 and the locale's charset. + */ + +#include +#include + +#include "utf8.h" + +#ifdef _WIN32 + + /* Thanks to Peter Harris for this win32 + * code. + */ + +#include +#include + +unsigned char *make_utf8_string(const wchar_t *unicode) +{ + int size = 0, index = 0, out_index = 0; + unsigned char *out; + unsigned short c; + + /* first calculate the size of the target string */ + c = unicode[index++]; + while(c) { + if(c < 0x0080) { + size += 1; + } else if(c < 0x0800) { + size += 2; + } else { + size += 3; + } + c = unicode[index++]; + } + + out = (unsigned char *) malloc(size + 1); + if (out == NULL) + return NULL; + index = 0; + + c = unicode[index++]; + while(c) + { + if(c < 0x080) { + out[out_index++] = (unsigned char)c; + } else if(c < 0x800) { + #pragma warning (suppress: 4244) // conversion from 'int' to 'unsigned char', possible loss of data + out[out_index++] = 0xc0 | (c >> 6); + out[out_index++] = 0x80 | (c & 0x3f); + } else { + out[out_index++] = 0xe0 | (c >> 12); + out[out_index++] = 0x80 | ((c >> 6) & 0x3f); + out[out_index++] = 0x80 | (c & 0x3f); + } + c = unicode[index++]; + } + out[out_index] = 0x00; + + return out; +} + +wchar_t *make_unicode_string(const unsigned char *utf8) +{ + int size = 0, index = 0, out_index = 0; + wchar_t *out; + unsigned char c; + + /* first calculate the size of the target string */ + c = utf8[index++]; + while(c) { + if((c & 0x80) == 0) { + index += 0; + } else if((c & 0xe0) == 0xe0) { + index += 2; + } else { + index += 1; + } + size += 1; + c = utf8[index++]; + } + + out = (wchar_t *) malloc((size + 1) * sizeof(wchar_t)); + if (out == NULL) + return NULL; + index = 0; + + c = utf8[index++]; + while(c) + { + if((c & 0x80) == 0) { + out[out_index++] = c; + } else if((c & 0xe0) == 0xe0) { + out[out_index] = (c & 0x1F) << 12; + c = utf8[index++]; + out[out_index] |= (c & 0x3F) << 6; + c = utf8[index++]; + out[out_index++] |= (c & 0x3F); + } else { + out[out_index] = (c & 0x3F) << 6; + c = utf8[index++]; + out[out_index++] |= (c & 0x3F); + } + c = utf8[index++]; + } + out[out_index] = 0; + + return out; +} + +int utf8_encode(const char *from, char **to) +{ + wchar_t *unicode; + int wchars, err; + + wchars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from, strlen(from), NULL, 0); + + if(wchars == 0) + { +// fprintf(stderr, "Unicode translation error %d\n"), GetLastError(); + return -1; + } + + unicode = (wchar_t *) calloc(wchars + 1, sizeof(unsigned short)); + if(unicode == NULL) + { +// fprintf(stderr, "Out of memory processing string to UTF8\n"); + return -1; + } + + err = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from, strlen(from), unicode, wchars); + if(err != wchars) + { + free(unicode); +// fprintf(stderr, "Unicode translation error %d\n"), GetLastError(); + return -1; + } + + /* On NT-based windows systems, we could use WideCharToMultiByte(), but + * MS doesn't actually have a consistent API across win32. + */ + *to = (char *) make_utf8_string(unicode); + + free(unicode); + return 0; +} + +int utf8_decode(const char *from, char **to) +{ + wchar_t *unicode; + int chars, err; +// LPCPINFO lpCPInfo; + + /* On NT-based windows systems, we could use MultiByteToWideChar(CP_UTF8), but + * MS doesn't actually have a consistent API across win32. + */ + unicode = make_unicode_string( (const unsigned char *)from); + if(unicode == NULL) + { + fprintf(stderr, "Out of memory processing string from UTF8 to UNICODE16\n"); + return -1; + } + + //if(GetCPInfo(CP_ACP,lpCPInfo)) + { + + chars = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, NULL, 0, NULL, NULL); + } + /*else + { + chars = WideCharToMultiByte(GetConsoleCP(), WC_COMPOSITECHECK, unicode, -1, NULL, 0, NULL, NULL); + }*/ + + if(chars == 0) + { + fprintf(stderr, "Unicode translation error %ld\n", GetLastError()); + free(unicode); + return -1; + } + + *to = (char *) calloc(chars + 1, sizeof(unsigned char)); + if(*to == NULL) + { + fprintf(stderr, "Out of memory processing string to local charset\n"); + free(unicode); + return -1; + } + + //err = WideCharToMultiByte(GetConsoleCP(), WC_COMPOSITECHECK, unicode, -1, *to, chars, NULL, NULL); + err = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, *to, chars, NULL, NULL); + if(err != chars) + { + fprintf(stderr, "Unicode translation error %ld\n", GetLastError()); + free(unicode); + free(*to); + *to = NULL; + return -1; + } + + free(unicode); + return 0; +} + +#ifndef _UNICODE +char *make_tchar_string(const unsigned char *utf8) { + char *ret; + if (utf8_decode((const char*)utf8, &ret)==-1) return NULL; + return ret; +} +#endif + +#else /* End win32. Rest is for real operating systems */ + + +#ifdef HAVE_LANGINFO_CODESET +#include +#endif + +int iconvert(const char *fromcode, const char *tocode, + const char *from, size_t fromlen, + char **to, size_t *tolen); + +static char *current_charset = "BIG-5"; /* means "US-ASCII" */ + +void convert_set_charset(const char *charset) +{ + + if (!charset) + charset = getenv("CHARSET"); + +#ifdef HAVE_LANGINFO_CODESET + if (!charset) + charset = nl_langinfo(CODESET); +#endif + + free(current_charset); + current_charset = 0; + if (charset && *charset) + current_charset = _strdup(charset); +} + +static int convert_buffer(const char *fromcode, const char *tocode, + const char *from, size_t fromlen, + char **to, size_t *tolen) +{ + int ret = -1; + +#ifdef HAVE_ICONV + ret = iconvert(fromcode, tocode, from, fromlen, to, tolen); + if (ret != -1) + return ret; +#endif + +#ifndef HAVE_ICONV /* should be ifdef USE_CHARSET_CONVERT */ + ret = charset_convert(fromcode, tocode, from, fromlen, to, tolen); + if (ret != -1) + return ret; +#endif + + return ret; +} + +static int convert_string(const char *fromcode, const char *tocode, + const char *from, char **to, char replace) +{ + int ret; + size_t fromlen; + char *s; + + fromlen = lstrlen(from); + ret = convert_buffer(fromcode, tocode, from, fromlen, to, 0); + if (ret == -2) + return -1; + if (ret != -1) + return ret; + + s = malloc(fromlen + 1); + if (!s) + return -1; + lstrcpy(s, from); + *to = s; + for (; *s; s++) + if (*s & ~0x7f) + *s = replace; + return 3; +} + +int utf8_encode(const char *from, char **to) +{ + char *charset; + + if (!current_charset) + convert_set_charset(0); + charset = current_charset ? current_charset : "US-ASCII"; + return convert_string(charset, "UTF-8", from, to, '#'); +} + +int utf8_decode(const char *from, char **to) +{ + char *charset; + + if(*from == 0) { + *to = malloc(1); + **to = 0; + return 1; + } + + if (!current_charset) + convert_set_charset(0); + charset = current_charset ? current_charset : "US-ASCII"; + return convert_string("UTF-8", charset, from, to, '?'); +} + +#endif diff --git a/protocols/SkypeClassic/src/util.c b/protocols/SkypeClassic/src/util.c deleted file mode 100644 index ce5ad9c756..0000000000 --- a/protocols/SkypeClassic/src/util.c +++ /dev/null @@ -1,57 +0,0 @@ -#include - -char * __cdecl strtok_r ( - char * string, - const char * control, - char **nextoken - ) -{ - unsigned char *str; - const unsigned char *ctrl = (const unsigned char*)control; - - unsigned char map[32]; - int count; - - /* Clear control map */ - for (count = 0; count < 32; count++) - map[count] = 0; - - /* Set bits in delimiter table */ - do { - map[*ctrl >> 3] |= (1 << (*ctrl & 7)); - } while (*ctrl++); - - /* Initialize str. If string is NULL, set str to the saved - * pointer (i.e., continue breaking tokens out of the string - * from the last strtok call) */ - if (string) - str = (unsigned char*)string; - else - str = (unsigned char*)(*nextoken); - - /* Find beginning of token (skip over leading delimiters). Note that - * there is no token iff this loop sets str to point to the terminal - * null (*str == '\0') */ - while ( (map[*str >> 3] & (1 << (*str & 7))) && *str ) - str++; - - string = (char*)str; - - /* Find the end of the token. If it is not the end of the string, - * put a null there. */ - for ( ; *str ; str++ ) - if ( map[*str >> 3] & (1 << (*str & 7)) ) { - *str++ = '\0'; - break; - } - - /* Update nextoken (or the corresponding field in the per-thread data - * structure */ - *nextoken = (char*)str; - - /* Determine if a token has been found. */ - if ( string == (char*)str ) - return NULL; - else - return string; -} diff --git a/protocols/SkypeClassic/src/util.cpp b/protocols/SkypeClassic/src/util.cpp new file mode 100644 index 0000000000..ce5ad9c756 --- /dev/null +++ b/protocols/SkypeClassic/src/util.cpp @@ -0,0 +1,57 @@ +#include + +char * __cdecl strtok_r ( + char * string, + const char * control, + char **nextoken + ) +{ + unsigned char *str; + const unsigned char *ctrl = (const unsigned char*)control; + + unsigned char map[32]; + int count; + + /* Clear control map */ + for (count = 0; count < 32; count++) + map[count] = 0; + + /* Set bits in delimiter table */ + do { + map[*ctrl >> 3] |= (1 << (*ctrl & 7)); + } while (*ctrl++); + + /* Initialize str. If string is NULL, set str to the saved + * pointer (i.e., continue breaking tokens out of the string + * from the last strtok call) */ + if (string) + str = (unsigned char*)string; + else + str = (unsigned char*)(*nextoken); + + /* Find beginning of token (skip over leading delimiters). Note that + * there is no token iff this loop sets str to point to the terminal + * null (*str == '\0') */ + while ( (map[*str >> 3] & (1 << (*str & 7))) && *str ) + str++; + + string = (char*)str; + + /* Find the end of the token. If it is not the end of the string, + * put a null there. */ + for ( ; *str ; str++ ) + if ( map[*str >> 3] & (1 << (*str & 7)) ) { + *str++ = '\0'; + break; + } + + /* Update nextoken (or the corresponding field in the per-thread data + * structure */ + *nextoken = (char*)str; + + /* Determine if a token has been found. */ + if ( string == (char*)str ) + return NULL; + else + return string; +} diff --git a/protocols/SkypeClassic/src/voiceservice.c b/protocols/SkypeClassic/src/voiceservice.c deleted file mode 100644 index 2223d1cbf0..0000000000 --- a/protocols/SkypeClassic/src/voiceservice.c +++ /dev/null @@ -1,169 +0,0 @@ -#include "skype.h" -#include "skypeapi.h" -#include "skypesvc.h" -#include "voiceservice.h" -#ifdef IS_MIRANDAIM -#include "sdk/m_voiceservice.h" -#endif - -#pragma warning (push) -#pragma warning (disable: 4100) // unreferenced formal parameter -#include "m_utils.h" -#pragma warning (pop) - -HANDLE hVoiceNotify = NULL; -BOOL has_voice_service = FALSE; - -extern char g_szProtoName[]; - - -BOOL HasVoiceService() -{ - return has_voice_service; -} - -void NofifyVoiceService(MCONTACT hContact, char *callId, int state) -{ -#ifdef IS_MIRANDAIM - VOICE_CALL vc = {0}; - vc.cbSize = sizeof(vc); - vc.szModule = SKYPE_PROTONAME; - vc.id = callId; - vc.flags = VOICE_CALL_CONTACT; - vc.state = state; - vc.hContact = hContact; - NotifyEventHooks(hVoiceNotify, (WPARAM) &vc, 0); -#endif -} - -#ifdef IS_MIRANDAIM -static INT_PTR VoiceGetInfo(WPARAM wParam, LPARAM lParam) -{ - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(lParam); - - return VOICE_SUPPORTED | VOICE_CALL_CONTACT | VOICE_CAN_HOLD; -} - -static HANDLE FindContactByCallId(char *callId) -{ - HANDLE hContact; - int iCmpRes; - for (hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); - hContact != NULL; - hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0)) - { - char *szProto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); - - DBVARIANT dbv; - if (szProto != NULL - && !strcmp(szProto, SKYPE_PROTONAME) - && DBGetContactSettingByte(hContact, SKYPE_PROTONAME, "ChatRoom", 0) == 0 - && !DBGetContactSettingString(hContact, SKYPE_PROTONAME, "CallId", &dbv)) - { - iCmpRes = strcmp(callId, dbv.pszVal); - DBFreeVariant(&dbv); - if (iCmpRes == 0) return hContact; - } - } - - return NULL; -} - -static INT_PTR VoiceCall(WPARAM wParam, LPARAM lParam) -{ - DBVARIANT dbv; - - UNREFERENCED_PARAMETER(lParam); - - if (!wParam) return -1; - - if (DBGetContactSettingString((HANDLE)wParam, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) - return -1; - - SkypeSend("CALL %s", dbv.pszVal); - DBFreeVariant (&dbv); - - return 0; -} - -static INT_PTR VoiceAnswer(WPARAM wParam, LPARAM lParam) -{ - char *callId = (char *) wParam; - - UNREFERENCED_PARAMETER(lParam); - - if (!wParam) return -1; - - if (FindContactByCallId(callId) == NULL) - return -1; - - SkypeSend("SET %s STATUS INPROGRESS", callId); - testfor("ERROR", 200); - - return 0; -} - -static INT_PTR VoiceDrop(WPARAM wParam, LPARAM lParam) -{ - char *callId = (char *) wParam; - - UNREFERENCED_PARAMETER(lParam); - - if (!wParam) return -1; - - if (FindContactByCallId(callId) == NULL) - return -1; - - SkypeSend("SET %s STATUS FINISHED", callId); - - return 0; -} - -static INT_PTR VoiceHold(WPARAM wParam, LPARAM lParam) -{ - char *callId = (char *) wParam; - - UNREFERENCED_PARAMETER(lParam); - - if (!wParam) return -1; - - if (FindContactByCallId(callId) == NULL) - return -1; - - SkypeSend("SET %s STATUS ONHOLD", callId); - - return 0; -} -#endif - -void VoiceServiceInit() -{ -#ifdef IS_MIRANDAIM - // leecher, 26.03.2011: Did this ever work in the old versions?? - char szEvent[MAXMODULELABELLENGTH]; - - _snprintf (szEvent, sizeof(szEvent), "%s%s", SKYPE_PROTONAME, PE_VOICE_CALL_STATE); - hVoiceNotify = CreateHookableEvent( szEvent ); - CreateProtoService( PS_VOICE_GETINFO, VoiceGetInfo ); - CreateProtoService( PS_VOICE_CALL, VoiceCall ); - CreateProtoService( PS_VOICE_ANSWERCALL, VoiceAnswer ); - CreateProtoService( PS_VOICE_DROPCALL, VoiceDrop ); - CreateProtoService( PS_VOICE_HOLDCALL, VoiceHold ); -#endif -} - -void VoiceServiceExit() -{ -#ifdef IS_MIRANDAIM - DestroyHookableEvent(hVoiceNotify); -#endif -} - -void VoiceServiceModulesLoaded() -{ -#ifdef IS_MIRANDAIM - has_voice_service = ServiceExists(MS_VOICESERVICE_REGISTER); -#endif -} - diff --git a/protocols/SkypeClassic/src/voiceservice.cpp b/protocols/SkypeClassic/src/voiceservice.cpp new file mode 100644 index 0000000000..80d4cf7b51 --- /dev/null +++ b/protocols/SkypeClassic/src/voiceservice.cpp @@ -0,0 +1,169 @@ +#include "skype.h" +#include "skypeapi.h" +#include "skypesvc.h" +#include "voiceservice.h" +#ifdef IS_MIRANDAIM +#include "sdk/m_voiceservice.h" +#endif + +#pragma warning (push) +#pragma warning (disable: 4100) // unreferenced formal parameter +#include "m_utils.h" +#pragma warning (pop) + +HANDLE hVoiceNotify = NULL; +BOOL has_voice_service = FALSE; + +extern char g_szProtoName[]; + + +BOOL HasVoiceService() +{ + return has_voice_service; +} + +void NofifyVoiceService(HANDLE hContact, char *callId, int state) +{ +#ifdef IS_MIRANDAIM + VOICE_CALL vc = {0}; + vc.cbSize = sizeof(vc); + vc.szModule = SKYPE_PROTONAME; + vc.id = callId; + vc.flags = VOICE_CALL_CONTACT; + vc.state = state; + vc.hContact = hContact; + NotifyEventHooks(hVoiceNotify, (WPARAM) &vc, 0); +#endif +} + +#ifdef IS_MIRANDAIM +static INT_PTR VoiceGetInfo(WPARAM wParam, LPARAM lParam) +{ + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + + return VOICE_SUPPORTED | VOICE_CALL_CONTACT | VOICE_CAN_HOLD; +} + +static HANDLE FindContactByCallId(char *callId) +{ + HANDLE hContact; + int iCmpRes; + for (hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + hContact != NULL; + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0)) + { + char *szProto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + + DBVARIANT dbv; + if (szProto != NULL + && !strcmp(szProto, SKYPE_PROTONAME) + && DBGetContactSettingByte(hContact, SKYPE_PROTONAME, "ChatRoom", 0) == 0 + && !DBGetContactSettingString(hContact, SKYPE_PROTONAME, "CallId", &dbv)) + { + iCmpRes = strcmp(callId, dbv.pszVal); + DBFreeVariant(&dbv); + if (iCmpRes == 0) return hContact; + } + } + + return NULL; +} + +static INT_PTR VoiceCall(WPARAM wParam, LPARAM lParam) +{ + DBVARIANT dbv; + + UNREFERENCED_PARAMETER(lParam); + + if (!wParam) return -1; + + if (DBGetContactSettingString((HANDLE)wParam, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) + return -1; + + SkypeSend("CALL %s", dbv.pszVal); + DBFreeVariant (&dbv); + + return 0; +} + +static INT_PTR VoiceAnswer(WPARAM wParam, LPARAM lParam) +{ + char *callId = (char *) wParam; + + UNREFERENCED_PARAMETER(lParam); + + if (!wParam) return -1; + + if (FindContactByCallId(callId) == NULL) + return -1; + + SkypeSend("SET %s STATUS INPROGRESS", callId); + testfor("ERROR", 200); + + return 0; +} + +static INT_PTR VoiceDrop(WPARAM wParam, LPARAM lParam) +{ + char *callId = (char *) wParam; + + UNREFERENCED_PARAMETER(lParam); + + if (!wParam) return -1; + + if (FindContactByCallId(callId) == NULL) + return -1; + + SkypeSend("SET %s STATUS FINISHED", callId); + + return 0; +} + +static INT_PTR VoiceHold(WPARAM wParam, LPARAM lParam) +{ + char *callId = (char *) wParam; + + UNREFERENCED_PARAMETER(lParam); + + if (!wParam) return -1; + + if (FindContactByCallId(callId) == NULL) + return -1; + + SkypeSend("SET %s STATUS ONHOLD", callId); + + return 0; +} +#endif + +void VoiceServiceInit() +{ +#ifdef IS_MIRANDAIM + // leecher, 26.03.2011: Did this ever work in the old versions?? + char szEvent[MAXMODULELABELLENGTH]; + + _snprintf (szEvent, sizeof(szEvent), "%s%s", SKYPE_PROTONAME, PE_VOICE_CALL_STATE); + hVoiceNotify = CreateHookableEvent( szEvent ); + CreateProtoService( PS_VOICE_GETINFO, VoiceGetInfo ); + CreateProtoService( PS_VOICE_CALL, VoiceCall ); + CreateProtoService( PS_VOICE_ANSWERCALL, VoiceAnswer ); + CreateProtoService( PS_VOICE_DROPCALL, VoiceDrop ); + CreateProtoService( PS_VOICE_HOLDCALL, VoiceHold ); +#endif +} + +void VoiceServiceExit() +{ +#ifdef IS_MIRANDAIM + DestroyHookableEvent(hVoiceNotify); +#endif +} + +void VoiceServiceModulesLoaded() +{ +#ifdef IS_MIRANDAIM + has_voice_service = ServiceExists(MS_VOICESERVICE_REGISTER); +#endif +} + diff --git a/protocols/SkypeClassic/src/voiceservice.h b/protocols/SkypeClassic/src/voiceservice.h index b638fbd2ae..6665fcaa5c 100644 --- a/protocols/SkypeClassic/src/voiceservice.h +++ b/protocols/SkypeClassic/src/voiceservice.h @@ -1,18 +1,18 @@ -#ifndef _VOICESERVICE_H_ -#define _VOICESERVICE_H_ - -#pragma warning (push) -#pragma warning (disable: 4201) // nonstandard extension used : nameless struct/union -#include "sdk/m_voice.h" -#pragma warning (pop) - -BOOL HasVoiceService(); -void VoiceServiceInit(); -void VoiceServiceExit(); -void VoiceServiceModulesLoaded(); -void NofifyVoiceService(MCONTACT hContact, char *callId, int state) ; - - - -#endif // _VOICESERVICE_H_ - +#ifndef _VOICESERVICE_H_ +#define _VOICESERVICE_H_ + +#pragma warning (push) +#pragma warning (disable: 4201) // nonstandard extension used : nameless struct/union + +#pragma warning (pop) + +BOOL HasVoiceService(); +void VoiceServiceInit(); +void VoiceServiceExit(); +void VoiceServiceModulesLoaded(); +void NofifyVoiceService(HANDLE hContact, char *callId, int state) ; + + + +#endif // _VOICESERVICE_H_ + -- cgit v1.2.3