From 91d312baa652df4977bf1195053e28480970e20f Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sun, 20 Jul 2014 14:54:37 +0000 Subject: support for the FavContacts's gadget git-svn-id: http://svn.miranda-ng.org/main/trunk@9891 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/FavContacts/favcontacts_10.vcxproj | 6 + plugins/FavContacts/favcontacts_10.vcxproj.filters | 18 +++ plugins/FavContacts/favcontacts_12.vcxproj | 6 + plugins/FavContacts/favcontacts_12.vcxproj.filters | 18 +++ plugins/FavContacts/src/Version.h | 2 +- plugins/FavContacts/src/cserver.cpp | 68 +++++++++ plugins/FavContacts/src/cserver.h | 42 ++++++ plugins/FavContacts/src/csocket.cpp | 21 +++ plugins/FavContacts/src/csocket.h | 16 ++ plugins/FavContacts/src/http_api.cpp | 165 +++++++++++++++++++++ plugins/FavContacts/src/http_api.h | 7 + plugins/FavContacts/src/main.cpp | 5 + 12 files changed, 373 insertions(+), 1 deletion(-) create mode 100644 plugins/FavContacts/src/cserver.cpp create mode 100644 plugins/FavContacts/src/cserver.h create mode 100644 plugins/FavContacts/src/csocket.cpp create mode 100644 plugins/FavContacts/src/csocket.h create mode 100644 plugins/FavContacts/src/http_api.cpp create mode 100644 plugins/FavContacts/src/http_api.h diff --git a/plugins/FavContacts/favcontacts_10.vcxproj b/plugins/FavContacts/favcontacts_10.vcxproj index a43efec15f..1e9a259df4 100644 --- a/plugins/FavContacts/favcontacts_10.vcxproj +++ b/plugins/FavContacts/favcontacts_10.vcxproj @@ -179,6 +179,9 @@ + + + @@ -189,8 +192,11 @@ + + + diff --git a/plugins/FavContacts/favcontacts_10.vcxproj.filters b/plugins/FavContacts/favcontacts_10.vcxproj.filters index 87c0bb1dc3..60d8eb3689 100644 --- a/plugins/FavContacts/favcontacts_10.vcxproj.filters +++ b/plugins/FavContacts/favcontacts_10.vcxproj.filters @@ -33,6 +33,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + @@ -50,6 +59,15 @@ Header Files + + Header Files + + + Header Files + + + Header Files + diff --git a/plugins/FavContacts/favcontacts_12.vcxproj b/plugins/FavContacts/favcontacts_12.vcxproj index 7c12a92107..5e362e62f9 100644 --- a/plugins/FavContacts/favcontacts_12.vcxproj +++ b/plugins/FavContacts/favcontacts_12.vcxproj @@ -182,6 +182,9 @@ + + + @@ -192,8 +195,11 @@ + + + diff --git a/plugins/FavContacts/favcontacts_12.vcxproj.filters b/plugins/FavContacts/favcontacts_12.vcxproj.filters index e82f9659cd..c6327a32f9 100644 --- a/plugins/FavContacts/favcontacts_12.vcxproj.filters +++ b/plugins/FavContacts/favcontacts_12.vcxproj.filters @@ -33,6 +33,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + @@ -50,6 +59,15 @@ Header Files + + Header Files + + + Header Files + + + Header Files + diff --git a/plugins/FavContacts/src/Version.h b/plugins/FavContacts/src/Version.h index 4b36aad0ac..3c3e44aeb3 100644 --- a/plugins/FavContacts/src/Version.h +++ b/plugins/FavContacts/src/Version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 1 #define __RELEASE_NUM 0 -#define __BUILD_NUM 2 +#define __BUILD_NUM 3 #include diff --git a/plugins/FavContacts/src/cserver.cpp b/plugins/FavContacts/src/cserver.cpp new file mode 100644 index 0000000000..d3a7ff5a0a --- /dev/null +++ b/plugins/FavContacts/src/cserver.cpp @@ -0,0 +1,68 @@ +#include "headers.h" + +#include "csocket.h" +#include "cserver.h" + +void CServer::Start(int port, IConnectionProcessorFactory *connectionProcessorFactory, bool background) +{ + m_socket = socket(AF_INET, SOCK_STREAM, 0); + if (m_socket == INVALID_SOCKET) return; + + sockaddr_in addr = { 0 }; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr.sin_port = htons((WORD)port); + if (bind(m_socket, (sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR) { + closesocket(m_socket); + m_socket = INVALID_SOCKET; + return; + } + + listen(m_socket, SOMAXCONN); + + m_connectionProcessorFactory = connectionProcessorFactory; + + if (background) + mir_forkthread(GlobalConnectionAcceptThread, this); + else + ConnectionAcceptThread(); +} + +void CServer::Stop() +{ + shutdown(m_socket, SD_BOTH); + closesocket(m_socket); +} + +DWORD CServer::ConnectionAcceptThread() +{ + while (1) { + SOCKET s = accept(m_socket, NULL, NULL); + if (s == INVALID_SOCKET) break; + + mir_forkthread(GlobalConnectionProcessThread, new GlobalConnectionProcessThreadArgs(this, s)); + } + return 0; +} + +DWORD CServer::ConnectionProcessThread(SOCKET s) +{ + CSocket sock(s); + IConnectionProcessor *processor = m_connectionProcessorFactory->Create(&sock); + processor->ProcessConnection(); + delete processor; + return 0; +} + +void CServer::GlobalConnectionAcceptThread(void *arg) +{ + CServer *server = (CServer *)arg; + server->ConnectionAcceptThread(); +} + +void CServer::GlobalConnectionProcessThread(void *arg) +{ + GlobalConnectionProcessThreadArgs *args = (GlobalConnectionProcessThreadArgs *)arg; + args->m_server->ConnectionProcessThread(args->m_socket); + delete args; +} diff --git a/plugins/FavContacts/src/cserver.h b/plugins/FavContacts/src/cserver.h new file mode 100644 index 0000000000..f96c87b2c1 --- /dev/null +++ b/plugins/FavContacts/src/cserver.h @@ -0,0 +1,42 @@ +#ifndef cserver_h__ +#define cserver_h__ + +class IConnectionProcessor +{ +public: + virtual ~IConnectionProcessor() {} + virtual void ProcessConnection() = 0; +}; + +class IConnectionProcessorFactory +{ +public: + virtual IConnectionProcessor *Create(CSocket *s) = 0; +}; + +class CServer +{ +private: + SOCKET m_socket; + IConnectionProcessorFactory *m_connectionProcessorFactory; + + DWORD ConnectionAcceptThread(); + DWORD ConnectionProcessThread(SOCKET s); + + static void GlobalConnectionAcceptThread(void *arg); + + struct GlobalConnectionProcessThreadArgs + { + CServer *m_server; + SOCKET m_socket; + + GlobalConnectionProcessThreadArgs(CServer *server, SOCKET s): m_server(server), m_socket(s) {} + }; + static void GlobalConnectionProcessThread(void *arg); + +public: + void Start(int port, IConnectionProcessorFactory *connectionProcessorFactory, bool background); + void Stop(); +}; + +#endif // cserver_h__ diff --git a/plugins/FavContacts/src/csocket.cpp b/plugins/FavContacts/src/csocket.cpp new file mode 100644 index 0000000000..8b31467c61 --- /dev/null +++ b/plugins/FavContacts/src/csocket.cpp @@ -0,0 +1,21 @@ +#include "headers.h" + +#include "csocket.h" + +int CSocket::Recv(char *buf, int count) +{ + return recv(m_socket, buf, count, 0); +} + +int CSocket::Send(char *buf, int count) +{ + if (count < 0) + count = (int)strlen(buf); + return send(m_socket, buf, count, 0); +} + +void CSocket::Close() +{ + shutdown(m_socket, SD_BOTH); + closesocket(m_socket); +} diff --git a/plugins/FavContacts/src/csocket.h b/plugins/FavContacts/src/csocket.h new file mode 100644 index 0000000000..3fa1c87852 --- /dev/null +++ b/plugins/FavContacts/src/csocket.h @@ -0,0 +1,16 @@ +#ifndef csocket_h__ +#define csocket_h__ + +class CSocket +{ +protected: + SOCKET m_socket; + +public: + CSocket(SOCKET socket = INVALID_SOCKET): m_socket(socket) {} + int Recv(char *buf, int count); + int Send(char *buf, int count = -1); + void Close(); +}; + +#endif // csocket_h__ diff --git a/plugins/FavContacts/src/http_api.cpp b/plugins/FavContacts/src/http_api.cpp new file mode 100644 index 0000000000..bacc6b05b0 --- /dev/null +++ b/plugins/FavContacts/src/http_api.cpp @@ -0,0 +1,165 @@ +#include "headers.h" + +#include "csocket.h" +#include "cserver.h" +#include "http_api.h" + +#define MS_FAVCONTACTS_OPEN_CONTACT "FavContacts/OpenContact" + +class CHttpProcessor: public IConnectionProcessor +{ +private: + CSocket *m_socket; + + char *FetchURL(char *s) + { + char *p; + if (p = strstr(s, "\r\n")) *p = 0; + if (p = strrchr(s, ' ')) *p = 0; + if (p = strchr(s, ' ')) while (*p && *p == ' ') p++; + return mir_strdup(p); + } + +public: + CHttpProcessor(CSocket *s): m_socket(s) {} + + void ProcessConnection() + { + char buf[1024]; + int n = m_socket->Recv(buf, sizeof(buf)); + buf[n] = 0; + + char *s = FetchURL(buf); + + if (!strncmp(s, "/fav/list/", 10)) + { + SendList(); + } else + if (!strncmp(s, "/fav/open/", 10)) + { + OpenContact(s); + } + + mir_free(s); + m_socket->Close(); + } + + void OpenContact(char *s) + { + m_socket->Send("HTTP 200 OK\r\n\r\n"); + + int hContact; + sscanf(s, "/fav/open/%d", &hContact); + if (CallService(MS_DB_CONTACT_IS, hContact, 0)) + CallServiceSync(MS_FAVCONTACTS_OPEN_CONTACT, hContact, 0); + } + + void SendList() + { + TFavContacts favList; + favList.build(); + + m_socket->Send( + "HTTP 200 OK\r\n" + "Content-Type: text/javascript\r\n" + "\r\n"); + + Send("try {\r\n"); + Send("SetContactCount("); + Send(favList.getCount()); + Send(");\r\n"); + + for (int i = 0; i < favList.getCount(); ++i) + { + MCONTACT hContact = favList[i]->getHandle(); + TCHAR *name = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, hContact, GCDNF_TCHAR); + AVATARCACHEENTRY *avatar = (AVATARCACHEENTRY *)CallService(MS_AV_GETAVATARBITMAP, hContact, 0); + int status = db_get_w(hContact, GetContactProto(hContact), "Status", ID_STATUS_OFFLINE); + + Send("SetContact("); + Send(i); + Send(", "); + Send((int)hContact); + Send(", '"); + SendQuoted(name); + Send("', "); + Send(status); + Send(", '"); + SendQuoted(avatar ? avatar->szFilename : _T("")); + Send("');\r\n"); + } + Send("} catch(e) {}\r\n"); + } + + void Send(char *s) + { + m_socket->Send(s); + } + + + void Send(WCHAR *ws) + { + char *s = mir_utf8encodeW(ws); + m_socket->Send(s); + mir_free(s); + } + + + void Send(int i) + { + char buf[32]; + mir_snprintf(buf, SIZEOF(buf), "%d", i); + Send(buf); + } + + template + void SendQuoted(const XCHAR *s) + { + int length = 0; + const XCHAR *p; + for (p = s; *p; p++) + { + if (*p == '\'' || *p == '\\' || *p == '\"') + length++; + length++; + } + XCHAR *buf = (XCHAR *)mir_alloc(sizeof(XCHAR) * (length + 1)); + XCHAR *q = buf; + for (p = s; *p; p++) + { + if (*p == '\'' || *p == '\\' || *p == '\"') + { + *q = '\\'; + q++; + } + *q = *p; + q++; + } + *q = 0; + Send(buf); + mir_free(buf); + } +}; + +class CHttpProcessorFactory: public IConnectionProcessorFactory +{ +public: + IConnectionProcessor *Create(CSocket *s) + { + return new CHttpProcessor(s); + } +}; + +static CHttpProcessorFactory g_httpProcessorFactory; +static CServer g_httpServer; + +void LoadHttpApi() +{ + g_httpServer.Start(60888, &g_httpProcessorFactory, true); +} + +int UnloadHttpApi() +{ + g_httpServer.Stop(); + return 0; +} diff --git a/plugins/FavContacts/src/http_api.h b/plugins/FavContacts/src/http_api.h new file mode 100644 index 0000000000..599ba4c4d4 --- /dev/null +++ b/plugins/FavContacts/src/http_api.h @@ -0,0 +1,7 @@ +#ifndef http_api_h__ +#define http_api_h__ + +void LoadHttpApi(); +int UnloadHttpApi(); + +#endif // http_api_h__ diff --git a/plugins/FavContacts/src/main.cpp b/plugins/FavContacts/src/main.cpp index e9847b6821..6051d2ad7c 100644 --- a/plugins/FavContacts/src/main.cpp +++ b/plugins/FavContacts/src/main.cpp @@ -20,6 +20,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "headers.h" +#include "http_api.h" + CLIST_INTERFACE *pcli; HINSTANCE g_hInst; @@ -77,6 +79,8 @@ extern "C" __declspec(dllexport) int Load(void) ///////////////////////////////////////////////////////////////////////////////////// Icon_Register(g_hInst, LPGEN("Favorites"), iconList, SIZEOF(iconList)); + + LoadHttpApi(); return 0; } @@ -84,6 +88,7 @@ extern "C" __declspec(dllexport) int Unload(void) { UninitServices(); UninitMenu(); + UnloadHttpApi(); if (g_Options.hfntName) DeleteObject(g_Options.hfntName); if (g_Options.hfntSecond) DeleteObject(g_Options.hfntSecond); -- cgit v1.2.3