From dd3d0e59dcd34beb222fcf612a51d3fee82c0e43 Mon Sep 17 00:00:00 2001 From: Alexander Lantsev Date: Tue, 17 Mar 2015 20:33:47 +0000 Subject: SkypeWeb: initial commit git-svn-id: http://svn.miranda-ng.org/main/trunk@12424 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/SkypeWeb/SkypeWeb_12.vcxproj | 241 +++++++++++++++++++++++++ protocols/SkypeWeb/SkypeWeb_12.vcxproj.filters | 103 +++++++++++ protocols/SkypeWeb/res/Icons/skype.ico | Bin 0 -> 5430 bytes protocols/SkypeWeb/res/resource.rc | 180 ++++++++++++++++++ protocols/SkypeWeb/res/version.rc | 38 ++++ protocols/SkypeWeb/src/common.h | 60 ++++++ protocols/SkypeWeb/src/http_request.h | 83 +++++++++ protocols/SkypeWeb/src/main.cpp | 62 +++++++ protocols/SkypeWeb/src/request_queue.cpp | 88 +++++++++ protocols/SkypeWeb/src/request_queue.h | 50 +++++ protocols/SkypeWeb/src/requests/login.h | 44 +++++ protocols/SkypeWeb/src/requests/logout.h | 13 ++ protocols/SkypeWeb/src/resource.h | 23 +++ protocols/SkypeWeb/src/skype_accounts.cpp | 51 ++++++ protocols/SkypeWeb/src/skype_contacts.cpp | 103 +++++++++++ protocols/SkypeWeb/src/skype_events.cpp | 93 ++++++++++ protocols/SkypeWeb/src/skype_icons.cpp | 63 +++++++ protocols/SkypeWeb/src/skype_icons.h | 12 ++ protocols/SkypeWeb/src/skype_menus.cpp | 97 ++++++++++ protocols/SkypeWeb/src/skype_menus.h | 11 ++ protocols/SkypeWeb/src/skype_messages.cpp | 29 +++ protocols/SkypeWeb/src/skype_options.cpp | 96 ++++++++++ protocols/SkypeWeb/src/skype_proto.cpp | 174 ++++++++++++++++++ protocols/SkypeWeb/src/skype_proto.h | 180 ++++++++++++++++++ protocols/SkypeWeb/src/skype_utils.cpp | 40 ++++ protocols/SkypeWeb/src/stdafx.cpp | 18 ++ protocols/SkypeWeb/src/version.h | 14 ++ 27 files changed, 1966 insertions(+) create mode 100644 protocols/SkypeWeb/SkypeWeb_12.vcxproj create mode 100644 protocols/SkypeWeb/SkypeWeb_12.vcxproj.filters create mode 100644 protocols/SkypeWeb/res/Icons/skype.ico create mode 100644 protocols/SkypeWeb/res/resource.rc create mode 100644 protocols/SkypeWeb/res/version.rc create mode 100644 protocols/SkypeWeb/src/common.h create mode 100644 protocols/SkypeWeb/src/http_request.h create mode 100644 protocols/SkypeWeb/src/main.cpp create mode 100644 protocols/SkypeWeb/src/request_queue.cpp create mode 100644 protocols/SkypeWeb/src/request_queue.h create mode 100644 protocols/SkypeWeb/src/requests/login.h create mode 100644 protocols/SkypeWeb/src/requests/logout.h create mode 100644 protocols/SkypeWeb/src/resource.h create mode 100644 protocols/SkypeWeb/src/skype_accounts.cpp create mode 100644 protocols/SkypeWeb/src/skype_contacts.cpp create mode 100644 protocols/SkypeWeb/src/skype_events.cpp create mode 100644 protocols/SkypeWeb/src/skype_icons.cpp create mode 100644 protocols/SkypeWeb/src/skype_icons.h create mode 100644 protocols/SkypeWeb/src/skype_menus.cpp create mode 100644 protocols/SkypeWeb/src/skype_menus.h create mode 100644 protocols/SkypeWeb/src/skype_messages.cpp create mode 100644 protocols/SkypeWeb/src/skype_options.cpp create mode 100644 protocols/SkypeWeb/src/skype_proto.cpp create mode 100644 protocols/SkypeWeb/src/skype_proto.h create mode 100644 protocols/SkypeWeb/src/skype_utils.cpp create mode 100644 protocols/SkypeWeb/src/stdafx.cpp create mode 100644 protocols/SkypeWeb/src/version.h (limited to 'protocols') diff --git a/protocols/SkypeWeb/SkypeWeb_12.vcxproj b/protocols/SkypeWeb/SkypeWeb_12.vcxproj new file mode 100644 index 0000000000..824dd30c22 --- /dev/null +++ b/protocols/SkypeWeb/SkypeWeb_12.vcxproj @@ -0,0 +1,241 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {66A9BDEB-150F-45DC-B20F-9892C0B43834} + SkypeWeb + + + + DynamicLibrary + true + Unicode + v120_xp + + + DynamicLibrary + true + Unicode + v120_xp + + + DynamicLibrary + false + true + Unicode + v120_xp + + + DynamicLibrary + false + true + Unicode + v120_xp + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)\Plugins\ + $(SolutionDir)$(Configuration)64\Plugins\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)\Plugins\ + $(SolutionDir)$(Configuration)64\Plugins\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + true + + + + Level4 + Disabled + _DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + include;..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories) + false + true + 4996;%(DisableSpecificWarnings) + MultiThreadedDebugDLL + common.h + Use + + + Windows + true + $(ProfileDir)..\..\bin12\lib + $(IntDir)$(TargetName).lib + false + false + comctl32.lib;%(AdditionalDependencies) + + + _DEBUG;%(PreprocessorDefinitions) + ..\..\include\msapi + + + + + + + + + Level4 + Disabled + _DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + include;..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories) + false + true + 4996;%(DisableSpecificWarnings) + MultiThreadedDebugDLL + Use + common.h + + + Windows + true + $(ProfileDir)..\..\bin12\lib + $(IntDir)$(TargetName).lib + comctl32.lib;%(AdditionalDependencies) + false + + + _DEBUG;%(PreprocessorDefinitions) + ..\..\include\msapi + + + + + + + + + Level4 + Full + true + true + NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + include;..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories) + 4996;%(DisableSpecificWarnings) + Use + common.h + + + Windows + true + true + true + false + $(ProfileDir)..\..\bin12\lib + $(IntDir)$(TargetName).lib + comctl32.lib;%(AdditionalDependencies) + + + NDEBUG;%(PreprocessorDefinitions) + ..\..\include\msapi + + + + + + + + + Level4 + Full + true + true + NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + include;..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories) + 4996;%(DisableSpecificWarnings) + Use + common.h + + + Windows + true + true + true + false + comctl32.lib;%(AdditionalDependencies) + $(ProfileDir)..\..\bin12\lib + $(IntDir)$(TargetName).lib + + + NDEBUG;%(PreprocessorDefinitions) + ..\..\include\msapi + + + + + + + + + + + + + + + + + + + + + + + Create + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/protocols/SkypeWeb/SkypeWeb_12.vcxproj.filters b/protocols/SkypeWeb/SkypeWeb_12.vcxproj.filters new file mode 100644 index 0000000000..3e97d03543 --- /dev/null +++ b/protocols/SkypeWeb/SkypeWeb_12.vcxproj.filters @@ -0,0 +1,103 @@ + + + + + {86de5614-9de5-4ffc-bd34-21d9c671e172} + + + {ea03e4bb-b8dd-4b5b-b409-2513240d2511} + + + {b818611d-200d-4eb8-be7a-f15b396ae26d} + + + {5ce796e5-1f0d-4bb7-bdab-9de0e5513528} + + + {957f1f93-0eaa-46b2-8f18-5df27d47239e} + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files\requests + + + Header Files\requests + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Resource Files + + + Resource Files + + + + + Resource Files\Icons + + + \ No newline at end of file diff --git a/protocols/SkypeWeb/res/Icons/skype.ico b/protocols/SkypeWeb/res/Icons/skype.ico new file mode 100644 index 0000000000..e69f22e023 Binary files /dev/null and b/protocols/SkypeWeb/res/Icons/skype.ico differ diff --git a/protocols/SkypeWeb/res/resource.rc b/protocols/SkypeWeb/res/resource.rc new file mode 100644 index 0000000000..6e79cc7696 --- /dev/null +++ b/protocols/SkypeWeb/res/resource.rc @@ -0,0 +1,180 @@ +// Microsoft Visual C++ generated resource script. +// +#include "..\src\resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral (Default) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUD) +LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT +#pragma code_page(1251) + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_SKYPE ICON "icons\\skype.ico" +#endif // Neutral (Default) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Russian (Russia) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS) +LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT +#pragma code_page(1251) + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON "Icons\\skype.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "..\\src\\resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Russian (Russia) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL +#pragma code_page(1252) + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ACCOUNT_MANAGER DIALOGEX 0, 0, 186, 119 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + EDITTEXT IDC_PASSWORD,49,16,135,12,ES_PASSWORD | ES_AUTOHSCROLL + LTEXT "Login:",IDC_STATIC,0,2,49,12 + EDITTEXT IDC_LOGIN,49,0,135,12,ES_AUTOHSCROLL + LTEXT "Password:",IDC_STATIC,0,18,49,12 + LTEXT "Default group:",IDC_STATIC,0,34,49,12 + EDITTEXT IDC_GROUP,49,32,135,12,ES_AUTOHSCROLL +END + +IDD_OPTIONS_MAIN DIALOGEX 0, 0, 310, 230 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + GROUPBOX "Account",IDC_STATIC,7,7,296,63,NOT WS_VISIBLE + LTEXT "Name:",IDC_STATIC,12,19,69,11 + EDITTEXT IDC_LOGIN,81,17,217,12,ES_AUTOHSCROLL + LTEXT "Password:",IDC_STATIC,12,34,69,8 + EDITTEXT IDC_PASSWORD,81,33,217,12,ES_PASSWORD | ES_AUTOHSCROLL + LTEXT "Default group:",IDC_STATIC,12,51,69,12 + EDITTEXT IDC_GROUP,81,49,217,12,ES_AUTOHSCROLL +END + +IDD_PASSWORD_EDITOR DIALOGEX 0, 0, 209, 75 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_TOOLWINDOW | WS_EX_APPWINDOW +CAPTION "Enter password" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + EDITTEXT IDC_PASSWORD,7,24,197,12,ES_PASSWORD | ES_AUTOHSCROLL + CONTROL "Save password",IDC_SAVEPERMANENTLY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,40,197,12 + DEFPUSHBUTTON "OK",IDOK,101,56,50,14 + PUSHBUTTON "Cancel",IDCANCEL,154,56,50,14 + LTEXT "Enter the password to continue.",IDC_STATIC,7,5,197,18 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_ACCOUNT_MANAGER, DIALOG + BEGIN + VERTGUIDE, 49 + BOTTOMMARGIN, 112 + END + + IDD_OPTIONS_MAIN, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 303 + VERTGUIDE, 12 + VERTGUIDE, 81 + VERTGUIDE, 298 + TOPMARGIN, 7 + BOTTOMMARGIN, 228 + END + + IDD_PASSWORD, DIALOG + BEGIN + RIGHTMARGIN, 204 + VERTGUIDE, 7 + BOTTOMMARGIN, 70 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/protocols/SkypeWeb/res/version.rc b/protocols/SkypeWeb/res/version.rc new file mode 100644 index 0000000000..5bfbab4754 --- /dev/null +++ b/protocols/SkypeWeb/res/version.rc @@ -0,0 +1,38 @@ +// Microsoft Visual C++ generated resource script. +// +#ifdef APSTUDIO_INVOKED +#error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + +#include "afxres.h" +#include "..\src\version.h" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION __FILEVERSION_STRING + PRODUCTVERSION __FILEVERSION_STRING + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x0L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "FileDescription", __DESCRIPTION + VALUE "InternalName", __PLUGIN_NAME + VALUE "LegalCopyright", __COPYRIGHT + VALUE "OriginalFilename", __FILENAME + VALUE "ProductName", __PLUGIN_NAME + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END diff --git a/protocols/SkypeWeb/src/common.h b/protocols/SkypeWeb/src/common.h new file mode 100644 index 0000000000..511fafb404 --- /dev/null +++ b/protocols/SkypeWeb/src/common.h @@ -0,0 +1,60 @@ +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct CSkypeProto; + +#include "version.h" +#include "resource.h" +#include "skype_icons.h" +#include "skype_menus.h" +#include "http_request.h" +#include "requests\login.h" +#include "requests\logout.h" +#include "request_queue.h" +#include "skype_proto.h" + +extern HINSTANCE g_hInstance; + +#define MODULE "SKYPE" + +#define SKYPE_SETTINGS_ID "Login" +#define SKYPE_SETTINGS_PASSWORD "Password" +#define SKYPE_SETTINGS_GROUP "DefaultGroup" + + +#endif //_COMMON_H_ \ No newline at end of file diff --git a/protocols/SkypeWeb/src/http_request.h b/protocols/SkypeWeb/src/http_request.h new file mode 100644 index 0000000000..40edf6895d --- /dev/null +++ b/protocols/SkypeWeb/src/http_request.h @@ -0,0 +1,83 @@ +#ifndef _HTTP_REQUEST_H_ +#define _HTTP_REQUEST_H_ + +class HttpRequest : protected NETLIBHTTPREQUEST, public MZeroedObject +{ +protected: + CMStringA url; + + HttpRequest() + { + cbSize = sizeof(NETLIBHTTPREQUEST); + } + + HttpRequest(int httpMethod, LPCSTR urlFormat, va_list args) + { + this->HttpRequest::HttpRequest(); + + requestType = httpMethod; + flags = NLHRF_HTTP11 | NLHRF_NODUMPSEND | NLHRF_DUMPASTEXT; + + url.AppendFormatV(urlFormat, args); + szUrl = url.GetBuffer(); + } + + void AddHeader(LPCSTR szName, LPCSTR szValue) + { + headers = (NETLIBHTTPHEADER*)mir_realloc(headers, sizeof(NETLIBHTTPHEADER)*(headersCount + 1)); + headers[headersCount].szName = mir_strdup(szName); + headers[headersCount].szValue = mir_strdup(szValue); + headersCount++; + } + + void SetData(const char *data, size_t size) + { + if (pData != NULL) + mir_free(pData); + + dataLength = (int)size; + pData = (char*)mir_alloc(size + 1); + memcpy(pData, data, size); + pData[size] = 0; + } + +public: + HttpRequest(int type, LPCSTR urlFormat, ...) + { + va_list args; + va_start(args, urlFormat); + this->HttpRequest::HttpRequest(type, urlFormat, args); + va_end(args); + } + + ~HttpRequest() + { + for (int i = 0; i < headersCount; i++) + { + mir_free(headers[i].szName); + mir_free(headers[i].szValue); + } + mir_free(headers); + mir_free(pData); + } + + void SetCookie(LPCSTR szValue) + { + AddHeader("Set-Cookie", szValue); + } + + NETLIBHTTPREQUEST * Send(HANDLE hConnection) + { + if (url.Find("http", 0) != 0) + url.Insert(0, flags & NLHRF_SSL ? "https://" : "http://"); + szUrl = url.GetBuffer(); + + char message[1024]; + mir_snprintf(message, SIZEOF(message), "Send request to %s", szUrl); + CallService(MS_NETLIB_LOG, (WPARAM)hConnection, (LPARAM)&message); + + return (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hConnection, (LPARAM)this); + } +}; + +#endif //_HTTP_REQUEST_H_ \ No newline at end of file diff --git a/protocols/SkypeWeb/src/main.cpp b/protocols/SkypeWeb/src/main.cpp new file mode 100644 index 0000000000..6d64d7b58a --- /dev/null +++ b/protocols/SkypeWeb/src/main.cpp @@ -0,0 +1,62 @@ +#include "common.h" + +int hLangpack; +TIME_API tmi = { 0 }; +HINSTANCE g_hInstance; + +PLUGININFOEX pluginInfo = +{ + sizeof(PLUGININFOEX), + __PLUGIN_NAME, + PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), + __DESCRIPTION, + __AUTHOR, + __AUTHOREMAIL, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + // {57E90AC6-1067-423B-8CA3-70A39D200D4F} + { 0x57e90ac6, 0x1067, 0x423b, {0x8c, 0xa3, 0x70, 0xa3, 0x9d, 0x20, 0xd, 0x4f}} +}; + +DWORD WINAPI DllMain(HINSTANCE hInstance, DWORD, LPVOID) +{ + g_hInstance = hInstance; + + return TRUE; +} + +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD) +{ + return &pluginInfo; +} + +extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_PROTOCOL, MIID_LAST}; + +extern "C" int __declspec(dllexport) Load(void) +{ + mir_getTMI(&tmi); + mir_getLP(&pluginInfo); + + PROTOCOLDESCRIPTOR pd = { sizeof(pd) }; + pd.szName = MODULE; + pd.type = PROTOTYPE_PROTOCOL; + pd.fnInit = (pfnInitProto)CSkypeProto::InitAccount; + pd.fnUninit = (pfnUninitProto)CSkypeProto::UninitAccount; + CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd); + + CSkypeProto::InitIcons(); + CSkypeProto::InitMenus(); + + HookEvent(ME_SYSTEM_MODULESLOADED, &CSkypeProto::OnModulesLoaded); + + return 0; +} + +extern "C" int __declspec(dllexport) Unload(void) +{ + CSkypeProto::UninitIcons(); + CSkypeProto::UninitMenus(); + + return 0; +} \ No newline at end of file diff --git a/protocols/SkypeWeb/src/request_queue.cpp b/protocols/SkypeWeb/src/request_queue.cpp new file mode 100644 index 0000000000..6448186614 --- /dev/null +++ b/protocols/SkypeWeb/src/request_queue.cpp @@ -0,0 +1,88 @@ +#include "common.h" + +RequestQueue::RequestQueue(HANDLE hConnection) : + hConnection(hConnection), requests(1) +{ + hRequestQueueThread = NULL; + hRequestQueueEvent = CreateEvent(NULL, FALSE, FALSE, NULL); +} + +RequestQueue::~RequestQueue() +{ + requests.destroy(); + CloseHandle(hRequestQueueEvent); +} + +void RequestQueue::Start() +{ + if (!isTerminated) + return; + + isTerminated = false; + if (hRequestQueueThread == NULL) + { + hRequestQueueThread = mir_forkthread((pThreadFunc)&RequestQueue::WorkerThread, this); + } +} + +void RequestQueue::Stop() +{ + if (isTerminated) + return; + + isTerminated = true; + hRequestQueueThread = NULL; +} + +void RequestQueue::Push(HttpRequest *request, HttpResponseCallback response, void *arg) +{ + if (isTerminated) + return; + + RequestQueueItem *item = new RequestQueueItem(request, response, arg); + { + mir_cslock lock(requestQueueLock); + + requests.insert(item); + } + SetEvent(hRequestQueueEvent); +} + +void RequestQueue::Execute(RequestQueueItem *item) +{ + NETLIBHTTPREQUEST *response = item->request->Send(hConnection); + if (item->responseCallback != NULL) + { + item->responseCallback(response, item->arg); + } + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)response); + requests.remove(item); + delete item; +} + +unsigned int RequestQueue::WorkerThread(void* owner, void*) +{ + RequestQueue *that = (RequestQueue*)owner; + + while (!that->isTerminated) + { + WaitForSingleObject(that->hRequestQueueEvent, INFINITE); + while (true) + { + RequestQueueItem *item = NULL; + { + mir_cslock lock(that->requestQueueLock); + + if (that->requests.getCount() == 0) + break; + + item = that->requests[0]; + that->requests.remove(0); + } + if (item != NULL) + that->Execute(item); + } + } + + return 0; +} \ No newline at end of file diff --git a/protocols/SkypeWeb/src/request_queue.h b/protocols/SkypeWeb/src/request_queue.h new file mode 100644 index 0000000000..df9154882c --- /dev/null +++ b/protocols/SkypeWeb/src/request_queue.h @@ -0,0 +1,50 @@ +#ifndef _SKYPE_REQUEST_QUEUE_H_ +#define _SKYPE_REQUEST_QUEUE_H_ + +typedef void (*HttpResponseCallback)(const NETLIBHTTPREQUEST *response, void *arg); + +struct RequestQueueItem +{ + void *arg; + HttpRequest *request; + HttpResponseCallback responseCallback; + + RequestQueueItem(HttpRequest *request, void *arg) : + request(request), responseCallback(NULL), arg(arg) { } + + RequestQueueItem(HttpRequest *request, HttpResponseCallback response, void *arg) : + request(request), responseCallback(response), arg(arg) { } + + ~RequestQueueItem() + { + delete request; + request = NULL; + responseCallback = NULL; + } +}; + +class RequestQueue +{ +private: + bool isTerminated; + HANDLE hConnection; + mir_cs requestQueueLock; + LIST requests; + HANDLE hRequestQueueEvent, hRequestQueueThread; + + void Execute(RequestQueueItem *item); + + static unsigned int __cdecl WorkerThread(void*, void*); + +public: + RequestQueue(HANDLE hConnection); + ~RequestQueue(); + + void Start(); + void Stop(); + + void Push(HttpRequest *request, HttpResponseCallback response = NULL, void *arg = NULL); + +}; + +#endif //_SKYPE_REQUEST_QUEUE_H_ \ No newline at end of file diff --git a/protocols/SkypeWeb/src/requests/login.h b/protocols/SkypeWeb/src/requests/login.h new file mode 100644 index 0000000000..e1d94806b7 --- /dev/null +++ b/protocols/SkypeWeb/src/requests/login.h @@ -0,0 +1,44 @@ +#ifndef _SKYPE_REQUEST_LOGIN_H_ +#define _SKYPE_REQUEST_LOGIN_H_ + +class LoginRequest : public HttpRequest +{ +public: + LoginRequest() : + HttpRequest(REQUEST_POST, "login.skype.com/login") + { + flags |= NLHRF_SSL; + + url.Append("?client_id=578134&redirect_uri=https%3A%2F%2Fweb.skype.com"); + } + + LoginRequest(const char *username, const char *password, const char *pie, const char *etm) : + HttpRequest(REQUEST_POST, "login.skype.com/login") + { + flags |= NLHRF_SSL; + + url.Append("?client_id=578134&redirect_uri=https%3A%2F%2Fweb.skype.com"); + + LPTIME_ZONE_INFORMATION tzi = tmi.getTziByContact(NULL); + + char sign = tzi->Bias > 0 ? '-' : '+'; + int hours = tzi->Bias / -60; + int minutes = tzi->Bias % -60; + + CMStringA data = ""; + data.AppendFormat("username=%s&", username); + data.AppendFormat("password=%s&", password); + data.AppendFormat("pie=%s&", ptrA(mir_urlEncode(pie))); + data.AppendFormat("etm=%s&", ptrA(mir_urlEncode(etm))); + data.AppendFormat("timezone_field=%c%02d|%02d&", sign, hours, minutes); + data.AppendFormat("js_time=%d.00&", time(NULL)); + data.Append("client_id=578134&"); + data.Append("redirect_uri=https%3A%2F%2Fweb.skype.com"); + + SetData(data, data.GetLength()); + + AddHeader("Content-Type", "application/x-www-form-urlencoded"); + } +}; + +#endif //_SKYPE_REQUEST_LOGIN_H_ diff --git a/protocols/SkypeWeb/src/requests/logout.h b/protocols/SkypeWeb/src/requests/logout.h new file mode 100644 index 0000000000..60f30e639c --- /dev/null +++ b/protocols/SkypeWeb/src/requests/logout.h @@ -0,0 +1,13 @@ +#ifndef _SKYPE_REQUEST_LOGOUT_H_ +#define _SKYPE_REQUEST_LOGOUT_H_ + +class LogoutRequest : public HttpRequest +{ +public: + LogoutRequest() : HttpRequest(REQUEST_POST, "login.skype.com/logout") + { + flags |= NLHRF_SSL; + } +}; + +#endif //_SKYPE_REQUEST_LOGOUT_H_ diff --git a/protocols/SkypeWeb/src/resource.h b/protocols/SkypeWeb/src/resource.h new file mode 100644 index 0000000000..bbd89be4de --- /dev/null +++ b/protocols/SkypeWeb/src/resource.h @@ -0,0 +1,23 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by E:\Projects\C++\MirandaNG\protocols\SkypeWeb\res\resource.rc +// +#define IDC_LOGIN 101 +#define IDC_PASSWORD 102 +#define IDD_ACCOUNT_MANAGER 103 +#define IDD_OPTIONS_MAIN 104 +#define IDI_SKYPE 105 +#define IDC_GROUP 106 +#define IDD_PASSWORD_EDITOR 107 +#define IDC_SAVEPERMANENTLY 108 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 109 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1026 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/protocols/SkypeWeb/src/skype_accounts.cpp b/protocols/SkypeWeb/src/skype_accounts.cpp new file mode 100644 index 0000000000..4b1ae6d536 --- /dev/null +++ b/protocols/SkypeWeb/src/skype_accounts.cpp @@ -0,0 +1,51 @@ +#include "common.h" + +LIST CSkypeProto::Accounts(1, CSkypeProto::CompareAccounts); + +int CSkypeProto::CompareAccounts(const CSkypeProto *p1, const CSkypeProto *p2) +{ + return _tcscmp(p1->m_tszUserName, p2->m_tszUserName); +} + +CSkypeProto* CSkypeProto::InitAccount(const char *protoName, const wchar_t *userName) +{ + CSkypeProto *proto = new CSkypeProto(protoName, userName); + Accounts.insert(proto); + return proto; +} + +int CSkypeProto::UninitAccount(CSkypeProto *proto) +{ + Accounts.remove(proto); + delete proto; + return 0; +} + +CSkypeProto* CSkypeProto::GetContactAccount(MCONTACT hContact) +{ + for (int i = 0; i < Accounts.getCount(); i++) + { + if (mir_strcmpi(GetContactProto(hContact), Accounts[i]->m_szModuleName) == 0) + { + return Accounts[i]; + } + } + return NULL; +} + +int CSkypeProto::OnAccountLoaded(WPARAM, LPARAM) +{ + HookProtoEvent(ME_OPT_INITIALISE, &CSkypeProto::OnOptionsInit); + + return 0; +} + +INT_PTR CSkypeProto::OnAccountManagerInit(WPARAM, LPARAM lParam) +{ + return (INT_PTR)CreateDialogParam( + g_hInstance, + MAKEINTRESOURCE(IDD_ACCOUNT_MANAGER), + (HWND)lParam, + CSkypeProto::MainOptionsProc, + (LPARAM)this); +} \ No newline at end of file diff --git a/protocols/SkypeWeb/src/skype_contacts.cpp b/protocols/SkypeWeb/src/skype_contacts.cpp new file mode 100644 index 0000000000..c8aea263e5 --- /dev/null +++ b/protocols/SkypeWeb/src/skype_contacts.cpp @@ -0,0 +1,103 @@ +#include "common.h" + +WORD CSkypeProto::GetContactStatus(MCONTACT hContact) +{ + return getWord(hContact, "Status", ID_STATUS_OFFLINE); +} + +void CSkypeProto::SetContactStatus(MCONTACT hContact, WORD status) +{ + WORD oldStatus = GetContactStatus(hContact); + if (oldStatus != status) + { + setWord(hContact, "Status", status); + } +} + +void CSkypeProto::SetAllContactsStatus(WORD status) +{ + for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) + { + SetContactStatus(hContact, status); + } +} + +MCONTACT CSkypeProto::GetContactFromAuthEvent(MEVENT hEvent) +{ + DWORD body[3]; + DBEVENTINFO dbei = { sizeof(DBEVENTINFO) }; + dbei.cbBlob = sizeof(DWORD) * 2; + dbei.pBlob = (PBYTE)&body; + + if (db_event_get(hEvent, &dbei)) + return INVALID_CONTACT_ID; + + if (dbei.eventType != EVENTTYPE_AUTHREQUEST) + return INVALID_CONTACT_ID; + + if (strcmp(dbei.szModule, m_szModuleName) != 0) + return INVALID_CONTACT_ID; + + return DbGetAuthEventContact(&dbei); +} + +MCONTACT CSkypeProto::GetContact(const char *login) +{ + MCONTACT hContact = NULL; + for (hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) + { + ptrA contactLogin(getStringA(hContact, SKYPE_SETTINGS_ID)); + if (mir_strcmpi(login, contactLogin) == 0) + { + break; + } + } + return hContact; +} + +MCONTACT CSkypeProto::AddContact(const char *login, bool isTemporary) +{ + MCONTACT hContact = GetContact(login); + if (!hContact) + { + hContact = (MCONTACT)CallService(MS_DB_CONTACT_ADD, 0, 0); + CallService(MS_PROTO_ADDTOCONTACT, hContact, (LPARAM)m_szModuleName); + + setString(hContact, SKYPE_SETTINGS_ID, login); + + DBVARIANT dbv; + if (!getTString(SKYPE_SETTINGS_GROUP, &dbv)) + { + db_set_ts(hContact, "CList", "Group", dbv.ptszVal); + db_free(&dbv); + } + + setByte(hContact, "Auth", 1); + setByte(hContact, "Grant", 1); + + if (isTemporary) + { + db_set_b(hContact, "CList", "NotOnList", 1); + } + } + return hContact; +} + +void CSkypeProto::LoadFriendList(void*) +{ +} + +INT_PTR CSkypeProto::OnRequestAuth(WPARAM hContact, LPARAM lParam) +{ + return 0; +} + +INT_PTR CSkypeProto::OnGrantAuth(WPARAM hContact, LPARAM) +{ + return 0; +} + +int CSkypeProto::OnContactDeleted(MCONTACT hContact, LPARAM) +{ + return 0; +} \ No newline at end of file diff --git a/protocols/SkypeWeb/src/skype_events.cpp b/protocols/SkypeWeb/src/skype_events.cpp new file mode 100644 index 0000000000..c4655bd310 --- /dev/null +++ b/protocols/SkypeWeb/src/skype_events.cpp @@ -0,0 +1,93 @@ +#include "common.h" + +int CSkypeProto::OnModulesLoaded(WPARAM, LPARAM) +{ + return 0; +} + +void CSkypeProto::OnLoginFirst(const NETLIBHTTPREQUEST *response) +{ + if (response == NULL) + { + ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, (HANDLE)NULL, 1001); + SetStatus(ID_STATUS_OFFLINE); + return; + } + + std::regex regex; + std::smatch match; + + const std::string content = response->pData; + + regex = ""; + if (!std::regex_search(content, match, regex)) + { + SetStatus(ID_STATUS_OFFLINE); + return; + } + std::string pie = match[1]; + + regex = ""; + if (!std::regex_search(content, match, regex)) + { + ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, (HANDLE)NULL, 1001); + SetStatus(ID_STATUS_OFFLINE); + return; + } + std::string etm = match[1]; + + ptrA login(mir_utf8encodeT(ptrT(getTStringA(SKYPE_SETTINGS_ID)))); + ptrA password(mir_utf8encodeT(ptrT(getTStringA(SKYPE_SETTINGS_PASSWORD)))); + + requestQueue->Push(new LoginRequest(login, password, pie.c_str(), etm.c_str()), HttpResponse<&CSkypeProto::OnLoginSecond>, this); +} + +void CSkypeProto::OnLoginSecond(const NETLIBHTTPREQUEST *response) +{ + if (response == NULL) + { + ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, (HANDLE)NULL, 1001); + SetStatus(ID_STATUS_OFFLINE); + return; + } + + std::regex regex; + std::smatch match; + + std::string content = response->pData; + + regex = ""; + if (!std::regex_search(content, match, regex)) + { + ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, (HANDLE)NULL, 1001); + SetStatus(ID_STATUS_OFFLINE); + return; + } + std::string token = match[1]; + setString("TokenSecret", token.c_str()); + + regex = ""; + if (!std::regex_search(content, match, regex)) + { + ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, (HANDLE)NULL, 1001); + SetStatus(ID_STATUS_OFFLINE); + return; + } + std::string expiresIn = match[1]; + int seconds = atoi(expiresIn.c_str()); + setDword("TokenExpiresIn", time(NULL) + seconds); + + for (int i = 0; i < response->headersCount; i++) + { + if (mir_strcmpi(response->headers[i].szName, "Set-Cookie")) + continue; + + regex = "^(.+?)=(.+?);"; + content = response->headers[i].szValue; + + if (std::regex_search(content, match, regex)) + cookies[match[1]] = match[2]; + } + + ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, m_iStatus = m_iDesiredStatus); +} \ No newline at end of file diff --git a/protocols/SkypeWeb/src/skype_icons.cpp b/protocols/SkypeWeb/src/skype_icons.cpp new file mode 100644 index 0000000000..8f5fc273e1 --- /dev/null +++ b/protocols/SkypeWeb/src/skype_icons.cpp @@ -0,0 +1,63 @@ +#include "common.h" + +IconInfo CSkypeProto::Icons[] = +{ + { LPGENT("Protocol icon"), "main", IDI_SKYPE }, +}; + +void CSkypeProto::InitIcons() +{ + TCHAR szFile[MAX_PATH]; + GetModuleFileName(g_hInstance, szFile, MAX_PATH); + + char szSettingName[100]; + TCHAR szSectionName[100]; + + SKINICONDESC sid = { sizeof(SKINICONDESC) }; + sid.flags = SIDF_ALL_TCHAR; + sid.ptszDefaultFile = szFile; + sid.pszName = szSettingName; + sid.ptszSection = szSectionName; + + mir_sntprintf(szSectionName, SIZEOF(szSectionName), _T("%s/%s"), LPGENT("Protocols"), LPGENT(MODULE)); + for (int i = 0; i < SIZEOF(Icons); i++) + { + mir_snprintf(szSettingName, SIZEOF(szSettingName), "%s_%s", MODULE, Icons[i].Name); + + sid.ptszDescription = Icons[i].Description; + sid.iDefaultIndex = -Icons[i].IconId; + Icons[i].Handle = Skin_AddIcon(&sid); + } +} + +HANDLE CSkypeProto::GetIconHandle(const char *name) +{ + for (size_t i = 0; i < SIZEOF(Icons); i++) + { + if (mir_strcmpi(Icons[i].Name, name) == 0) + { + return Icons[i].Handle; + } + } + return 0; +} + +HANDLE CSkypeProto::GetSkinIconHandle(const char *name) +{ + char iconName[100]; + mir_snprintf(iconName, SIZEOF(iconName), "%s_%s", MODULE, name); + HANDLE hIcon = Skin_GetIconHandle(iconName); + if (hIcon == NULL) + { + hIcon = GetIconHandle(name); + } + return hIcon; +} + +void CSkypeProto::UninitIcons() +{ + for (size_t i = 0; i < SIZEOF(Icons); i++) + { + Skin_RemoveIcon(Icons[i].Name); + } +} \ No newline at end of file diff --git a/protocols/SkypeWeb/src/skype_icons.h b/protocols/SkypeWeb/src/skype_icons.h new file mode 100644 index 0000000000..f2bd6e0747 --- /dev/null +++ b/protocols/SkypeWeb/src/skype_icons.h @@ -0,0 +1,12 @@ +#ifndef _SKYPE_ICONS_H_ +#define _SKYPE_ICONS_H_ + +struct IconInfo +{ + TCHAR *Description; + char *Name; + int IconId; + HANDLE Handle; +}; + +#endif //_SKYPE_ICONS_H_ \ No newline at end of file diff --git a/protocols/SkypeWeb/src/skype_menus.cpp b/protocols/SkypeWeb/src/skype_menus.cpp new file mode 100644 index 0000000000..cd38b5a4c5 --- /dev/null +++ b/protocols/SkypeWeb/src/skype_menus.cpp @@ -0,0 +1,97 @@ +#include "common.h" + +HGENMENU CSkypeProto::ContactMenuItems[CMI_MAX]; + +int CSkypeProto::OnPrebuildContactMenu(WPARAM hContact, LPARAM) +{ + if (!hContact) + return 0; + + if (m_iStatus < ID_STATUS_ONLINE) + return 0; + + if (this->isChatRoom(hContact)) + return 0; + + bool isCtrlPressed = (GetKeyState(VK_CONTROL) & 0x8000) != 0; + bool isAuthNeed = getByte(hContact, "Auth", 0) > 0; + bool isGrantNeed = getByte(hContact, "Grant", 0) > 0; + + Menu_ShowItem(ContactMenuItems[CMI_AUTH_REQUEST], isCtrlPressed || isAuthNeed); + Menu_ShowItem(ContactMenuItems[CMI_AUTH_GRANT], isCtrlPressed || isGrantNeed); + + return 0; +} + +int CSkypeProto::PrebuildContactMenu(WPARAM hContact, LPARAM lParam) +{ + for (int i = 0; i < SIZEOF(ContactMenuItems); i++) + { + Menu_ShowItem(ContactMenuItems[i], false); + } + CSkypeProto *proto = CSkypeProto::GetContactAccount(hContact); + return proto ? proto->OnPrebuildContactMenu(hContact, lParam) : 0; +} + +void CSkypeProto::InitMenus() +{ + HookEvent(ME_CLIST_PREBUILDCONTACTMENU, &CSkypeProto::PrebuildContactMenu); + + //hChooserMenu = MO_CreateMenuObject("SkypeAccountChooser", LPGEN("Skype menu chooser"), 0, "Skype/MenuChoose"); + + CLISTMENUITEM mi = { sizeof(CLISTMENUITEM) }; + mi.flags = CMIF_TCHAR; + + // Request authorization + mi.pszService = MODULE"/RequestAuth"; + mi.ptszName = LPGENT("Request authorization"); + mi.position = CMI_POSITION + CMI_AUTH_REQUEST; + mi.icolibItem = LoadSkinnedIconHandle(SKINICON_AUTH_REQUEST); + ContactMenuItems[CMI_AUTH_REQUEST] = Menu_AddContactMenuItem(&mi); + CreateServiceFunction(mi.pszService, GlobalService<&CSkypeProto::OnRequestAuth>); + + // Grant authorization + mi.pszService = MODULE"/GrantAuth"; + mi.ptszName = LPGENT("Grant authorization"); + mi.position = CMI_POSITION + CMI_AUTH_GRANT; + mi.icolibItem = LoadSkinnedIconHandle(SKINICON_AUTH_GRANT); + ContactMenuItems[CMI_AUTH_GRANT] = Menu_AddContactMenuItem(&mi); + CreateServiceFunction(mi.pszService, GlobalService<&CSkypeProto::OnGrantAuth>); +} + +void CSkypeProto::UninitMenus() +{ +} + + +int CSkypeProto::OnInitStatusMenu() +{ + char text[MAX_PATH]; + mir_strcpy(text, m_szModuleName); + char *tDest = text + strlen(text); + + CLISTMENUITEM mi = { sizeof(mi) }; + mi.pszService = text; + + HGENMENU hStatusMunuRoot = MO_GetProtoRootMenu(m_szModuleName); + if (!hStatusMunuRoot) + { + mi.ptszName = m_tszUserName; + mi.position = -1999901006; + mi.hParentMenu = HGENMENU_ROOT; + mi.flags = CMIF_ROOTPOPUP | CMIF_TCHAR | CMIF_KEEPUNTRANSLATED; + mi.icolibItem = GetSkinIconHandle("main"); + hStatusMunuRoot = /*m_hMenuRoot = */Menu_AddProtoMenuItem(&mi); + } + /*else + { + if (m_hMenuRoot) + CallService(MO_REMOVEMENUITEM, (WPARAM)m_hMenuRoot, 0); + m_hMenuRoot = NULL; + }*/ + + mi.hParentMenu = hStatusMunuRoot; + mi.flags = CMIF_CHILDPOPUP | CMIF_TCHAR; + + return 0; +} \ No newline at end of file diff --git a/protocols/SkypeWeb/src/skype_menus.h b/protocols/SkypeWeb/src/skype_menus.h new file mode 100644 index 0000000000..6930ddeb2f --- /dev/null +++ b/protocols/SkypeWeb/src/skype_menus.h @@ -0,0 +1,11 @@ +#ifndef _SKYPE_MENUS_H_ +#define _SKYPE_MENUS_H_ + +#define CMI_POSITION -201001000 +#define CMI_AUTH_REQUEST 1 +#define CMI_AUTH_GRANT 2 +#define CMI_MAX 3 // this item shall be the last one + +#define SMI_POSITION 200000 + +#endif //_SKYPE_MENUS_H_ \ No newline at end of file diff --git a/protocols/SkypeWeb/src/skype_messages.cpp b/protocols/SkypeWeb/src/skype_messages.cpp new file mode 100644 index 0000000000..1fee5e1fa9 --- /dev/null +++ b/protocols/SkypeWeb/src/skype_messages.cpp @@ -0,0 +1,29 @@ +#include "common.h" + +/* MESSAGE RECEIVING */ + +// writing message/even into db +int CSkypeProto::OnReceiveMessage(MCONTACT hContact, PROTORECVEVENT *pre) +{ + //return Proto_RecvMessage(hContact, pre); + if (pre->szMessage == NULL) + return NULL; + + DBEVENTINFO dbei = { sizeof(dbei) }; + dbei.szModule = GetContactProto(hContact); + dbei.timestamp = pre->timestamp; + dbei.flags = DBEF_UTF; + dbei.eventType = pre->lParam; + dbei.cbBlob = (DWORD)strlen(pre->szMessage) + 1; + dbei.pBlob = (PBYTE)pre->szMessage; + + return (INT_PTR)db_event_add(hContact, &dbei); +} + +/* MESSAGE SENDING */ + +// outcoming message flow +int CSkypeProto::OnSendMessage(MCONTACT hContact, int flags, const char *szMessage) +{ + return 0; +} \ No newline at end of file diff --git a/protocols/SkypeWeb/src/skype_options.cpp b/protocols/SkypeWeb/src/skype_options.cpp new file mode 100644 index 0000000000..bf5c2901f3 --- /dev/null +++ b/protocols/SkypeWeb/src/skype_options.cpp @@ -0,0 +1,96 @@ +#include "common.h" + +INT_PTR CSkypeProto::MainOptionsProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + CSkypeProto *proto = (CSkypeProto*)GetWindowLongPtr(hwnd, GWLP_USERDATA); + + switch (uMsg) + { + case WM_INITDIALOG: + TranslateDialogDefault(hwnd); + { + proto = (CSkypeProto*)lParam; + SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam); + + ptrA login(proto->getStringA(SKYPE_SETTINGS_ID)); + SetDlgItemTextA(hwnd, IDC_LOGIN, login); + SendDlgItemMessage(hwnd, IDC_LOGIN, EM_LIMITTEXT, 32, 0); + + ptrA password(proto->getStringA("Password")); + SetDlgItemTextA(hwnd, IDC_PASSWORD, password); + SendDlgItemMessage(hwnd, IDC_PASSWORD, EM_LIMITTEXT, 20, 0); + + ptrT group(proto->getTStringA(SKYPE_SETTINGS_GROUP)); + SetDlgItemText(hwnd, IDC_GROUP, group ? group : _T("Skype")); + SendDlgItemMessage(hwnd, IDC_GROUP, EM_LIMITTEXT, 64, 0); + } + return TRUE; + + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case IDC_LOGIN: + case IDC_GROUP: + case IDC_PASSWORD: + if ((HWND)lParam == GetFocus()) + { + if (HIWORD(wParam) != EN_CHANGE) return 0; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + break; + } + } + break; + + case WM_NOTIFY: + if (((NMHDR*)lParam)->code == PSN_APPLY) + { + char login[32]; + GetDlgItemTextA(hwnd, IDC_LOGIN, login, SIZEOF(login)); + proto->setString(SKYPE_SETTINGS_ID, login); + + char password[20]; + GetDlgItemTextA(hwnd, IDC_PASSWORD, password, SIZEOF(password)); + proto->setString(SKYPE_SETTINGS_PASSWORD, password); + + TCHAR group[64]; + GetDlgItemText(hwnd, IDC_GROUP, group, SIZEOF(group)); + if (_tcslen(group) > 0) + { + proto->setTString(SKYPE_SETTINGS_GROUP, group); + Clist_CreateGroup(0, group); + } + else + { + proto->delSetting(NULL, SKYPE_SETTINGS_GROUP); + } + + return TRUE; + } + break; + } + + return FALSE; +} + +int CSkypeProto::OnOptionsInit(WPARAM wParam, LPARAM) +{ + char *title = mir_t2a(m_tszUserName); + + OPTIONSDIALOGPAGE odp = { sizeof(odp) }; + odp.hInstance = g_hInstance; + odp.pszTitle = title; + odp.dwInitParam = (LPARAM)this; + odp.flags = ODPF_BOLDGROUPS; + odp.pszGroup = LPGEN("Network"); + + odp.pszTab = LPGEN("Account"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS_MAIN); + odp.pfnDlgProc = MainOptionsProc; + Options_AddPage(wParam, &odp); + + mir_free(title); + + return 0; +} \ No newline at end of file diff --git a/protocols/SkypeWeb/src/skype_proto.cpp b/protocols/SkypeWeb/src/skype_proto.cpp new file mode 100644 index 0000000000..1eddc4c2b8 --- /dev/null +++ b/protocols/SkypeWeb/src/skype_proto.cpp @@ -0,0 +1,174 @@ +#include "common.h" + +CSkypeProto::CSkypeProto(const char* protoName, const TCHAR* userName) : + PROTO(protoName, userName), password(NULL) +{ + m_hProtoIcon = Icons[0].Handle; + SetAllContactsStatus(ID_STATUS_OFFLINE); + + wchar_t name[128]; + mir_sntprintf(name, SIZEOF(name), TranslateT("%s connection"), m_tszUserName); + NETLIBUSER nlu = { 0 }; + nlu.cbSize = sizeof(nlu); + nlu.flags = NUF_OUTGOING | NUF_INCOMING | NUF_HTTPCONNS | NUF_UNICODE; + nlu.ptszDescriptiveName = name; + nlu.szSettingsModule = m_szModuleName; + m_hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu); + requestQueue = new RequestQueue(m_hNetlibUser); + + CreateProtoService(PS_CREATEACCMGRUI, &CSkypeProto::OnAccountManagerInit); +} + +CSkypeProto::~CSkypeProto() +{ + delete requestQueue; + Netlib_CloseHandle(m_hNetlibUser); + m_hNetlibUser = NULL; +} + +DWORD_PTR CSkypeProto::GetCaps(int type, MCONTACT) +{ + switch (type) + { + case PFLAGNUM_1: + return 0; + case PFLAGNUM_2: + return PF2_ONLINE; + case PFLAGNUM_3: + return PF2_ONLINE; + case PFLAG_UNIQUEIDTEXT: + return (INT_PTR)"Login"; + case PFLAG_UNIQUEIDSETTING: + return (DWORD_PTR)SKYPE_SETTINGS_ID; + } + + return 0; +} + +MCONTACT CSkypeProto::AddToList(int flags, PROTOSEARCHRESULT *psr) { return 0; } + +MCONTACT CSkypeProto::AddToListByEvent(int, int, MEVENT) { return 0; } + +int CSkypeProto::Authorize(MEVENT hDbEvent) { return 0; } + +int CSkypeProto::AuthDeny(MEVENT, const PROTOCHAR*) { return 0; } + +int CSkypeProto::AuthRecv(MCONTACT, PROTORECVEVENT* pre) { return 0; } + +int CSkypeProto::AuthRequest(MCONTACT hContact, const PROTOCHAR *szMessage) { return 0; } + +HANDLE CSkypeProto::ChangeInfo(int, void*) { return 0; } + +HANDLE CSkypeProto::FileAllow(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* tszPath) { return 0; } + +int CSkypeProto::FileCancel(MCONTACT hContact, HANDLE hTransfer) { return 0; } + +int CSkypeProto::FileDeny(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* tszReason) { return 0; } + +int CSkypeProto::FileResume(HANDLE hTransfer, int* action, const PROTOCHAR** tszFilename) { return 0; } + +int CSkypeProto::GetInfo(MCONTACT, int) { return 0; } + +HANDLE CSkypeProto::SearchBasic(const PROTOCHAR*) { return 0; } + +HANDLE CSkypeProto::SearchByEmail(const PROTOCHAR*) { return 0; } + +HANDLE CSkypeProto::SearchByName(const PROTOCHAR*, const PROTOCHAR*, const PROTOCHAR*) { return 0; } + +HWND CSkypeProto::SearchAdvanced(HWND owner) { return 0; } + +HWND CSkypeProto::CreateExtendedSearchUI(HWND owner) { return 0; } + +int CSkypeProto::RecvContacts(MCONTACT, PROTORECVEVENT*) { return 0; } + +int CSkypeProto::RecvFile(MCONTACT hContact, PROTOFILEEVENT *pre) { return 0; } + +int CSkypeProto::RecvMsg(MCONTACT hContact, PROTORECVEVENT *pre) { return 0; } + +int CSkypeProto::RecvUrl(MCONTACT, PROTORECVEVENT*) { return 0; } + +int CSkypeProto::SendContacts(MCONTACT, int, int, MCONTACT*) { return 0; } + +HANDLE CSkypeProto::SendFile(MCONTACT hContact, const PROTOCHAR *szDescription, PROTOCHAR **ppszFiles) { return 0; } + +int CSkypeProto::SendMsg(MCONTACT hContact, int flags, const char *msg) { return 0; } + +int CSkypeProto::SendUrl(MCONTACT, int, const char*) { return 0; } + +int CSkypeProto::SetApparentMode(MCONTACT, int) { return 0; } + +int CSkypeProto::SetStatus(int iNewStatus) +{ + if (iNewStatus == m_iDesiredStatus) + { + return 0; + } + + debugLogA(__FUNCTION__ ": changing status from %i to %i", m_iStatus, iNewStatus); + + int old_status = m_iStatus; + m_iDesiredStatus = iNewStatus; + + if (iNewStatus == ID_STATUS_OFFLINE) + { + // logout + PushRequest(new LogoutRequest()); + requestQueue->Stop(); + + if (!Miranda_Terminated()) + { + SetAllContactsStatus(ID_STATUS_OFFLINE); + } + + m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE; + } + else + { + if (old_status == ID_STATUS_CONNECTING) + { + return 0; + } + + if (old_status == ID_STATUS_OFFLINE && m_iStatus == ID_STATUS_OFFLINE) + { + // login + m_iStatus = ID_STATUS_CONNECTING; + + requestQueue->Start(); + PushRequest(new LoginRequest(), HttpResponse<&CSkypeProto::OnLoginFirst>, this); + } + else + { + // set status + m_iStatus = iNewStatus; + } + } + + ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus); + return 0; +} + +HANDLE CSkypeProto::GetAwayMsg(MCONTACT) { return 0; } + +int CSkypeProto::RecvAwayMsg(MCONTACT, int, PROTORECVEVENT*) { return 0; } + +int CSkypeProto::SetAwayMsg(int, const PROTOCHAR *msg) { return 0; } + +int CSkypeProto::UserIsTyping(MCONTACT hContact, int type) { return 0; } + +int CSkypeProto::OnEvent(PROTOEVENTTYPE iEventType, WPARAM wParam, LPARAM lParam) +{ + switch (iEventType) + { + case EV_PROTO_ONLOAD: + return OnAccountLoaded(wParam, lParam); + + case EV_PROTO_ONCONTACTDELETED: + return OnContactDeleted(wParam, lParam); + + case EV_PROTO_ONMENU: + return OnInitStatusMenu(); + } + + return 1; +} \ No newline at end of file diff --git a/protocols/SkypeWeb/src/skype_proto.h b/protocols/SkypeWeb/src/skype_proto.h new file mode 100644 index 0000000000..b704bd4133 --- /dev/null +++ b/protocols/SkypeWeb/src/skype_proto.h @@ -0,0 +1,180 @@ +#ifndef _TOX_PROTO_H_ +#define _TOX_PROTO_H_ + +class RequestQueueItem; + +struct CSkypeProto : public PROTO < CSkypeProto > +{ +public: + + ////////////////////////////////////////////////////////////////////////////////////// + //Ctors + + CSkypeProto(const char *protoName, const wchar_t *userName); + ~CSkypeProto(); + + ////////////////////////////////////////////////////////////////////////////////////// + // Virtual functions + + virtual MCONTACT __cdecl AddToList(int flags, PROTOSEARCHRESULT* psr); + virtual MCONTACT __cdecl AddToListByEvent(int flags, int iContact, MEVENT hDbEvent); + + virtual int __cdecl Authorize(MEVENT hDbEvent); + virtual int __cdecl AuthDeny(MEVENT hDbEvent, const PROTOCHAR* szReason); + virtual int __cdecl AuthRecv(MCONTACT hContact, PROTORECVEVENT*); + virtual int __cdecl AuthRequest(MCONTACT hContact, const PROTOCHAR* szMessage); + + virtual HANDLE __cdecl ChangeInfo(int iInfoType, void* pInfoData); + + virtual HANDLE __cdecl FileAllow(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* tszPath); + virtual int __cdecl FileCancel(MCONTACT hContact, HANDLE hTransfer); + virtual int __cdecl FileDeny(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* tszReason); + virtual int __cdecl FileResume(HANDLE hTransfer, int* action, const PROTOCHAR** tszFilename); + + virtual DWORD_PTR __cdecl GetCaps(int type, MCONTACT hContact = NULL); + virtual int __cdecl GetInfo(MCONTACT hContact, int infoType); + + virtual HANDLE __cdecl SearchBasic(const PROTOCHAR* id); + virtual HANDLE __cdecl SearchByEmail(const PROTOCHAR* email); + virtual HANDLE __cdecl SearchByName(const PROTOCHAR* nick, const PROTOCHAR* firstName, const PROTOCHAR* lastName); + virtual HWND __cdecl SearchAdvanced(HWND owner); + virtual HWND __cdecl CreateExtendedSearchUI(HWND owner); + + virtual int __cdecl RecvContacts(MCONTACT hContact, PROTORECVEVENT*); + virtual int __cdecl RecvFile(MCONTACT hContact, PROTOFILEEVENT*); + virtual int __cdecl RecvMsg(MCONTACT hContact, PROTORECVEVENT*); + virtual int __cdecl RecvUrl(MCONTACT hContact, PROTORECVEVENT*); + + virtual int __cdecl SendContacts(MCONTACT hContact, int flags, int nContacts, MCONTACT *hContactsList); + virtual HANDLE __cdecl SendFile(MCONTACT hContact, const PROTOCHAR *szDescription, PROTOCHAR **ppszFiles); + virtual int __cdecl SendMsg(MCONTACT hContact, int flags, const char* msg); + virtual int __cdecl SendUrl(MCONTACT hContact, int flags, const char* url); + + virtual int __cdecl SetApparentMode(MCONTACT hContact, int mode); + virtual int __cdecl SetStatus(int iNewStatus); + + virtual HANDLE __cdecl GetAwayMsg(MCONTACT hContact); + virtual int __cdecl RecvAwayMsg(MCONTACT hContact, int mode, PROTORECVEVENT* evt); + virtual int __cdecl SetAwayMsg(int iStatus, const PROTOCHAR* msg); + + virtual int __cdecl UserIsTyping(MCONTACT hContact, int type); + + virtual int __cdecl OnEvent(PROTOEVENTTYPE iEventType, WPARAM wParam, LPARAM lParam); + + // accounts + static CSkypeProto* InitAccount(const char *protoName, const TCHAR *userName); + static int UninitAccount(CSkypeProto *proto); + + // icons + static void InitIcons(); + static void UninitIcons(); + + // menus + static void InitMenus(); + static void UninitMenus(); + + // events + static int OnModulesLoaded(WPARAM, LPARAM); + +private: + char *password; + RequestQueue *requestQueue; + std::map cookies; + + static INT_PTR CALLBACK PasswordEditorProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + + // accounts + static LIST Accounts; + static int CompareAccounts(const CSkypeProto *p1, const CSkypeProto *p2); + + static CSkypeProto* GetContactAccount(MCONTACT hContact); + + int __cdecl OnAccountLoaded(WPARAM, LPARAM); + + INT_PTR __cdecl OnAccountManagerInit(WPARAM, LPARAM); + + // api response wrappers + template + static void HttpResponse(const NETLIBHTTPREQUEST *response, void *arg) + { + (((CSkypeProto*)arg)->*ResponseCallback)(response); + } + + template + static void JsonResponse(const NETLIBHTTPREQUEST *response, void *arg) + { + JSONROOT root(response->pData); + (((CSkypeProto*)arg)->*ResponseCallback)(root); + } + + void PushRequest(HttpRequest *request, HttpResponseCallback response = NULL, void *arg = NULL) + { + if (!cookies.empty()) + { + CMStringA allCookies; + for (std::map::iterator cookie = cookies.begin(); cookie != cookies.end(); ++cookie) + allCookies.AppendFormat("%s=%s; ", cookie->first.c_str(), cookie->second.c_str()); + request->SetCookie(allCookies); + } + requestQueue->Push(request, response, arg); + } + + // icons + static IconInfo Icons[]; + static HANDLE GetIconHandle(const char *name); + static HANDLE GetSkinIconHandle(const char *name); + + // menus + static HGENMENU ContactMenuItems[CMI_MAX]; + int OnPrebuildContactMenu(WPARAM hContact, LPARAM); + static int PrebuildContactMenu(WPARAM hContact, LPARAM lParam); + + int OnInitStatusMenu(); + + // options + static INT_PTR CALLBACK MainOptionsProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + + int __cdecl OnOptionsInit(WPARAM wParam, LPARAM lParam); + + // events + void OnLoginFirst(const NETLIBHTTPREQUEST *response); + + void OnLoginSecond(const NETLIBHTTPREQUEST *response); + + // contacts + WORD GetContactStatus(MCONTACT hContact); + void SetContactStatus(MCONTACT hContact, WORD status); + void SetAllContactsStatus(WORD status); + + MCONTACT GetContact(const char *login); + + MCONTACT AddContact(const char *login, bool isTemporary = false); + + MCONTACT GetContactFromAuthEvent(MEVENT hEvent); + + void __cdecl LoadFriendList(void*); + + INT_PTR __cdecl OnRequestAuth(WPARAM hContact, LPARAM lParam); + INT_PTR __cdecl OnGrantAuth(WPARAM hContact, LPARAM); + + int __cdecl OnContactDeleted(MCONTACT, LPARAM); + + // messages + int OnReceiveMessage(MCONTACT hContact, PROTORECVEVENT *pre); + int OnSendMessage(MCONTACT hContact, int flags, const char *message); + + // utils + static void ShowNotification(const TCHAR *message, int flags = 0, MCONTACT hContact = NULL); + static void ShowNotification(const TCHAR *caption, const TCHAR *message, int flags = 0, MCONTACT hContact = NULL); + + static bool IsFileExists(std::tstring path); + + template + static INT_PTR __cdecl GlobalService(WPARAM wParam, LPARAM lParam) + { + CSkypeProto *proto = CSkypeProto::GetContactAccount((MCONTACT)wParam); + return proto ? (proto->*Service)(wParam, lParam) : 0; + } +}; + +#endif //_TOX_PROTO_H_ \ No newline at end of file diff --git a/protocols/SkypeWeb/src/skype_utils.cpp b/protocols/SkypeWeb/src/skype_utils.cpp new file mode 100644 index 0000000000..5ce367f768 --- /dev/null +++ b/protocols/SkypeWeb/src/skype_utils.cpp @@ -0,0 +1,40 @@ +#include "common.h" + +void CSkypeProto::ShowNotification(const TCHAR *caption, const TCHAR *message, int flags, MCONTACT hContact) +{ + if (Miranda_Terminated()) + { + return; + } + + if (ServiceExists(MS_POPUP_ADDPOPUPT) && db_get_b(NULL, "Popup", "ModuleIsEnabled", 1)) + { + POPUPDATAT ppd = { 0 }; + ppd.lchContact = hContact; + wcsncpy(ppd.lpwzContactName, caption, MAX_CONTACTNAME); + wcsncpy(ppd.lpwzText, message, MAX_SECONDLINE); + ppd.lchIcon = Skin_GetIcon("Skype_main"); + + if (!PUAddPopupT(&ppd)) + return; + } + + MessageBox(NULL, message, caption, MB_OK | flags); +} + +void CSkypeProto::ShowNotification(const TCHAR *message, int flags, MCONTACT hContact) +{ + ShowNotification(_T(MODULE), message, flags, hContact); +} + +bool CSkypeProto::IsFileExists(std::tstring path) +{ + WIN32_FIND_DATA wfd; + HANDLE hFind = FindFirstFile(path.c_str(), &wfd); + if (INVALID_HANDLE_VALUE != hFind) + { + FindClose(hFind); + return true; + } + return false; +} \ No newline at end of file diff --git a/protocols/SkypeWeb/src/stdafx.cpp b/protocols/SkypeWeb/src/stdafx.cpp new file mode 100644 index 0000000000..c5fe5abaad --- /dev/null +++ b/protocols/SkypeWeb/src/stdafx.cpp @@ -0,0 +1,18 @@ +/* +Copyright (C) 2012-15 Miranda NG project (http://miranda-ng.org) + +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 version 2 +of the License. + +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, see . +*/ + +#include "common.h" \ No newline at end of file diff --git a/protocols/SkypeWeb/src/version.h b/protocols/SkypeWeb/src/version.h new file mode 100644 index 0000000000..95bac7ffe5 --- /dev/null +++ b/protocols/SkypeWeb/src/version.h @@ -0,0 +1,14 @@ +#define __MAJOR_VERSION 0 +#define __MINOR_VERSION 11 +#define __RELEASE_NUM 0 +#define __BUILD_NUM 0 + +#include + +#define __PLUGIN_NAME "Skype protocol (Web)" +#define __FILENAME "SkypeWeb.dll" +#define __DESCRIPTION "Skype protocol support for Miranda NG. Based on new Skype for Web API." +#define __AUTHOR "Miranda NG Team" +#define __AUTHOREMAIL "" +#define __AUTHORWEB "http://miranda-ng.org/p/SkypeWeb/" +#define __COPYRIGHT "© 2015 Miranda NG Team" -- cgit v1.2.3