diff options
Diffstat (limited to 'plugins/FavContacts/src')
| -rw-r--r-- | plugins/FavContacts/src/Version.h | 2 | ||||
| -rw-r--r-- | plugins/FavContacts/src/cserver.cpp | 68 | ||||
| -rw-r--r-- | plugins/FavContacts/src/cserver.h | 42 | ||||
| -rw-r--r-- | plugins/FavContacts/src/csocket.cpp | 21 | ||||
| -rw-r--r-- | plugins/FavContacts/src/csocket.h | 16 | ||||
| -rw-r--r-- | plugins/FavContacts/src/http_api.cpp | 165 | ||||
| -rw-r--r-- | plugins/FavContacts/src/http_api.h | 7 | ||||
| -rw-r--r-- | plugins/FavContacts/src/main.cpp | 5 | 
8 files changed, 325 insertions, 1 deletions
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 <stdver.h>
 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<class XCHAR>
 +	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);
  | 
