Changeset - bd4b3bcd1d4e
CMakeLists.txt
Show inline comments
 
@@ -242,6 +242,7 @@ ADD_SUBDIRECTORY(spectrum)
 
ADD_SUBDIRECTORY(backends)
 
if (NOT WIN32)
 
	ADD_SUBDIRECTORY(spectrum_manager)
 
#	ADD_SUBDIRECTORY(spectrum2_send_message)
 
endif()
 

	
 
if (CPPUNIT_FOUND)
ChangeLog
Show inline comments
 
Version 2.0.0-beta2 (2012-XX-XX):
 
	General:
 
	* Fixed bug when Roster Item Exchange and subscribe stanzas were sent
 
	  repeatedly.
 
	* Backends related logs now contain the backend PID.
 
	* Fixed username_mask setting.
 
	* Added new fields into statistics (backends_crashed, messages related
 
	  stats).
 

	
 
	libpurple:
 
	* Added support for MUC for prpl-jabber protocol.
 

	
 
	Skype:
 
	* Memory usage statistic now includes the Skype client.
 
	* Fixed logging issue when the logs were not stored in the proper instance
 
	  directory.
 
	* Skype backend includes also Skype client memory usage into the account.
 
	* Working buddies adding/removing.
 
	* Information about missed call is now forwarded to XMPP user.
 

	
 
Version 2.0.0-beta (2012-02-28):
 
	General:
 
	* Added PostreSQL support (thanks to Jadestorm).
backends/libcommuni/main.cpp
Show inline comments
 
@@ -10,6 +10,7 @@
 

	
 
#include "transport/config.h"
 
#include "transport/networkplugin.h"
 
#include "transport/logging.h"
 
#include "session.h"
 
#include <QtCore>
 
#include <QtNetwork>
 
@@ -83,30 +84,7 @@ int main (int argc, char* argv[]) {
 
	}
 
	QCoreApplication app(argc, argv);
 

	
 
	if (CONFIG_STRING(&config, "logging.backend_config").empty()) {
 
		LoggerPtr root = log4cxx::Logger::getRootLogger();
 
#ifndef _MSC_VER
 
		root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n")));
 
#else
 
		root->addAppender(new ConsoleAppender(new PatternLayout(L"%d %-5p %c: %m%n")));
 
#endif
 
	}
 
	else {
 
		log4cxx::helpers::Properties p;
 
		log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(&config, "logging.backend_config"));
 
		p.load(istream);
 
		LogString pid, jid;
 
		log4cxx::helpers::Transcoder::decode(boost::lexical_cast<std::string>(getpid()), pid);
 
		log4cxx::helpers::Transcoder::decode(CONFIG_STRING(&config, "service.jid"), jid);
 
#ifdef _MSC_VER
 
		p.setProperty(L"pid", pid);
 
		p.setProperty(L"jid", jid);
 
#else
 
		p.setProperty("pid", pid);
 
		p.setProperty("jid", jid);
 
#endif
 
		log4cxx::PropertyConfigurator::configure(p);
 
	}
 
	Logging::initBackendLogging(&config);
 

	
 
	Swift::QtEventLoop eventLoop;
 

	
backends/libpurple/main.cpp
Show inline comments
 
#include "utils.h"
 

	
 
#include "glib.h"
 
#include "purple.h"
 
#include <algorithm>
 
@@ -12,25 +14,7 @@
 
#include "log4cxx/helpers/properties.h"
 
#include "log4cxx/helpers/fileinputstream.h"
 
#include "log4cxx/helpers/transcoder.h"
 
#ifndef WIN32 
 
#include "sys/wait.h"
 
#include "sys/signal.h"
 
#include <netinet/if_ether.h>
 
#include <netinet/ip.h>
 
#include <netinet/ip6.h>
 
#include <netinet/udp.h>
 
#include <netinet/tcp.h>
 
#include <netinet/ether.h>
 
#include "sys/socket.h"
 
#include <netdb.h>
 
#include <unistd.h>
 
#include <fcntl.h>
 
#else 
 
#include <process.h>
 
#define getpid _getpid 
 
#define ssize_t SSIZE_T
 
#include "win32/win32dep.h"
 
#endif
 

	
 
// #include "valgrind/memcheck.h"
 
#include "malloc.h"
 
#include <algorithm>
 
@@ -40,11 +24,18 @@
 
#include <event.h>
 
#endif
 

	
 
#ifdef WIN32
 
#include "win32/win32dep.h"
 
#define ssize_t SSIZE_T
 
#include <process.h>
 
#define getpid _getpid
 
#endif
 

	
 
using namespace log4cxx;
 

	
 
static LoggerPtr logger_libpurple = log4cxx::Logger::getLogger("libpurple");
 
static LoggerPtr logger = log4cxx::Logger::getLogger("backend");
 
int m_sock;
 
int main_socket;
 
static int writeInput;
 

	
 
using namespace Transport;
 
@@ -89,7 +80,7 @@ static std::string KEYFILE_STRING(const std::string &cat, const std::string &key
 
		return def;
 
	}
 
	std::string ret(str);
 
	free(str);
 
	g_free(str);
 

	
 
	if (ret.find("#") != std::string::npos) {
 
		ret = ret.substr(0, ret.find("#"));
 
@@ -107,13 +98,8 @@ static std::string KEYFILE_STRING(const std::string &cat, const std::string &key
 

	
 
#define KEYFILE_BOOL(CAT, KEY) g_key_file_get_boolean(keyfile, CAT, KEY, 0)
 

	
 
static gboolean nodaemon = FALSE;
 
static gchar *logfile = NULL;
 
static gchar *lock_file = NULL;
 
static gchar *host = NULL;
 
static int port = 10000;
 
static gboolean ver = FALSE;
 
static gboolean list_purple_settings = FALSE;
 

	
 
struct FTData {
 
	unsigned long id;
 
@@ -122,121 +108,12 @@ struct FTData {
 
};
 

	
 
static GOptionEntry options_entries[] = {
 
	{ "nodaemon", 'n', 0, G_OPTION_ARG_NONE, &nodaemon, "Disable background daemon mode", NULL },
 
	{ "logfile", 'l', 0, G_OPTION_ARG_STRING, &logfile, "Set file to log", NULL },
 
	{ "pidfile", 'p', 0, G_OPTION_ARG_STRING, &lock_file, "File where to write transport PID", NULL },
 
	{ "version", 'v', 0, G_OPTION_ARG_NONE, &ver, "Shows Spectrum version", NULL },
 
	{ "list-purple-settings", 's', 0, G_OPTION_ARG_NONE, &list_purple_settings, "Lists purple settings which can be used in config file", NULL },
 
	{ "host", 'h', 0, G_OPTION_ARG_STRING, &host, "Host to connect to", NULL },
 
	{ "port", 'p', 0, G_OPTION_ARG_INT, &port, "Port to connect to", NULL },
 
	{ NULL, 0, 0, G_OPTION_ARG_NONE, NULL, "", NULL }
 
};
 

	
 
static void *notify_user_info(PurpleConnection *gc, const char *who, PurpleNotifyUserInfo *user_info);
 
static GHashTable *ui_info = NULL;
 

	
 
static GHashTable *spectrum_ui_get_info(void)
 
{
 
	if(NULL == ui_info) {
 
		ui_info = g_hash_table_new(g_str_hash, g_str_equal);
 

	
 
		g_hash_table_insert(ui_info, g_strdup("name"), g_strdup("Spectrum"));
 
		g_hash_table_insert(ui_info, g_strdup("version"), g_strdup("0.5"));
 
		g_hash_table_insert(ui_info, g_strdup("website"), g_strdup("http://spectrum.im"));
 
		g_hash_table_insert(ui_info, g_strdup("dev_website"), g_strdup("http://spectrum.im"));
 
		g_hash_table_insert(ui_info, g_strdup("client_type"), g_strdup("pc"));
 

	
 
		/*
 
		 * This is the client key for "Pidgin."  It is owned by the AIM
 
		 * account "markdoliner."  Please don't use this key for other
 
		 * applications.  You can either not specify a client key, in
 
		 * which case the default "libpurple" key will be used, or you
 
		 * can register for your own client key at
 
		 * http://developer.aim.com/manageKeys.jsp
 
		 */
 
		g_hash_table_insert(ui_info, g_strdup("prpl-aim-clientkey"), g_strdup("ma1cSASNCKFtrdv9"));
 
		g_hash_table_insert(ui_info, g_strdup("prpl-icq-clientkey"), g_strdup("ma1cSASNCKFtrdv9"));
 

	
 
		/*
 
		 * This is the distid for Pidgin, given to us by AOL.  Please
 
		 * don't use this for other applications.  You can just not
 
		 * specify a distid and libpurple will use a default.
 
		 */
 
		g_hash_table_insert(ui_info, g_strdup("prpl-aim-distid"), GINT_TO_POINTER(1550));
 
		g_hash_table_insert(ui_info, g_strdup("prpl-icq-distid"), GINT_TO_POINTER(1550));
 
	}
 

	
 
	return ui_info;
 
}
 

	
 
static gboolean
 
badchar(char c)
 
{
 
	switch (c) {
 
	case ' ':
 
	case ',':
 
	case '\0':
 
	case '\n':
 
	case '\r':
 
	case '<':
 
	case '>':
 
	case '"':
 
		return TRUE;
 
	default:
 
		return FALSE;
 
	}
 
}
 

	
 
static gboolean
 
badentity(const char *c)
 
{
 
	if (!g_ascii_strncasecmp(c, "&lt;", 4) ||
 
		!g_ascii_strncasecmp(c, "&gt;", 4) ||
 
		!g_ascii_strncasecmp(c, "&quot;", 6)) {
 
		return TRUE;
 
	}
 
	return FALSE;
 
}
 

	
 
static const char *
 
process_link(GString *ret,
 
		const char *start, const char *c,
 
		int matchlen,
 
		const char *urlprefix,
 
		int inside_paren)
 
{
 
	char *url_buf;
 
	const char *t;
 

	
 
	for (t = c;; t++) {
 
		if (!badchar(*t) && !badentity(t))
 
			continue;
 

	
 
		if (t - c == matchlen)
 
			break;
 

	
 
		if (*t == ',' && *(t + 1) != ' ') {
 
			continue;
 
		}
 

	
 
		if (t > start && *(t - 1) == '.')
 
			t--;
 
		if (t > start && *(t - 1) == ')' && inside_paren > 0)
 
			t--;
 

	
 
		url_buf = g_strndup(c, t - c);
 
// 		tmpurlbuf = purple_unescape_html(url_buf);
 
// 		std::cout << url_buf << "\n";
 
		g_string_append_printf(ret, "<A HREF=\"%s%s\">%s</A>",
 
				urlprefix,
 
				url_buf, url_buf);
 
// 		g_free(tmpurlbuf);
 
		g_free(url_buf);
 
		return t;
 
	}
 

	
 
	return c;
 
}
 

	
 
static gboolean ft_ui_ready(void *data) {
 
	PurpleXfer *xfer = (PurpleXfer *) data;
 
@@ -246,184 +123,6 @@ static gboolean ft_ui_ready(void *data) {
 
	return FALSE;
 
}
 

	
 
static char *
 
spectrum_markup_linkify(const char *text)
 
{
 
	const char *c, *t, *q = NULL;
 
	char *tmpurlbuf, *url_buf;
 
	gunichar g;
 
	gboolean inside_html = FALSE;
 
	int inside_paren = 0;
 
	GString *ret;
 

	
 
	if (text == NULL)
 
		return NULL;
 

	
 
	ret = g_string_new("");
 

	
 
	c = text;
 
	while (*c) {
 

	
 
		if(*c == '(' && !inside_html) {
 
			inside_paren++;
 
			ret = g_string_append_c(ret, *c);
 
			c++;
 
		}
 

	
 
		if(inside_html) {
 
			if(*c == '>') {
 
				inside_html = FALSE;
 
			} else if(!q && (*c == '\"' || *c == '\'')) {
 
				q = c;
 
			} else if(q) {
 
				if(*c == *q)
 
					q = NULL;
 
			}
 
		} else if(*c == '<') {
 
			inside_html = TRUE;
 
			if (!g_ascii_strncasecmp(c, "<A", 2)) {
 
				while (1) {
 
					if (!g_ascii_strncasecmp(c, "/A>", 3)) {
 
						inside_html = FALSE;
 
						break;
 
					}
 
					ret = g_string_append_c(ret, *c);
 
					c++;
 
					if (!(*c))
 
						break;
 
				}
 
			}
 
		} else if (!g_ascii_strncasecmp(c, "http://", 7)) {
 
			c = process_link(ret, text, c, 7, "", inside_paren);
 
		} else if (!g_ascii_strncasecmp(c, "https://", 8)) {
 
			c = process_link(ret, text, c, 8, "", inside_paren);
 
		} else if (!g_ascii_strncasecmp(c, "ftp://", 6)) {
 
			c = process_link(ret, text, c, 6, "", inside_paren);
 
		} else if (!g_ascii_strncasecmp(c, "sftp://", 7)) {
 
			c = process_link(ret, text, c, 7, "", inside_paren);
 
		} else if (!g_ascii_strncasecmp(c, "file://", 7)) {
 
			c = process_link(ret, text, c, 7, "", inside_paren);
 
		} else if (!g_ascii_strncasecmp(c, "www.", 4) && c[4] != '.' && (c == text || badchar(c[-1]) || badentity(c-1))) {
 
			c = process_link(ret, text, c, 4, "http://", inside_paren);
 
		} else if (!g_ascii_strncasecmp(c, "ftp.", 4) && c[4] != '.' && (c == text || badchar(c[-1]) || badentity(c-1))) {
 
			c = process_link(ret, text, c, 4, "ftp://", inside_paren);
 
		} else if (!g_ascii_strncasecmp(c, "xmpp:", 5) && (c == text || badchar(c[-1]) || badentity(c-1))) {
 
			c = process_link(ret, text, c, 5, "", inside_paren);
 
		} else if (!g_ascii_strncasecmp(c, "mailto:", 7)) {
 
			t = c;
 
			while (1) {
 
				if (badchar(*t) || badentity(t)) {
 
					const char *d;
 
					if (t - c == 7) {
 
						break;
 
					}
 
					if (t > text && *(t - 1) == '.')
 
						t--;
 
					if ((d = strstr(c + 7, "?")) != NULL && d < t)
 
						url_buf = g_strndup(c + 7, d - c - 7);
 
					else
 
						url_buf = g_strndup(c + 7, t - c - 7);
 
					if (!purple_email_is_valid(url_buf)) {
 
						g_free(url_buf);
 
						break;
 
					}
 
					g_free(url_buf);
 
					url_buf = g_strndup(c, t - c);
 
// 					tmpurlbuf = purple_unescape_html(url_buf);
 
					g_string_append_printf(ret, "<A HREF=\"%s\">%s</A>",
 
							  url_buf, url_buf);
 
					g_free(url_buf);
 
// 					g_free(tmpurlbuf);
 
					c = t;
 
					break;
 
				}
 
				t++;
 
			}
 
		} else if (c != text && (*c == '@')) {
 
			int flag;
 
			GString *gurl_buf = NULL;
 
			const char illegal_chars[] = "!@#$%^&*()[]{}/|\\<>\":;\r\n \0";
 

	
 
			if (strchr(illegal_chars,*(c - 1)) || strchr(illegal_chars, *(c + 1)))
 
				flag = 0;
 
			else {
 
				flag = 1;
 
				gurl_buf = g_string_new("");
 
			}
 

	
 
			t = c;
 
			while (flag) {
 
				/* iterate backwards grabbing the local part of an email address */
 
				g = g_utf8_get_char(t);
 
				if (badchar(*t) || (g >= 127) || (*t == '(') ||
 
					((*t == ';') && ((t > (text+2) && (!g_ascii_strncasecmp(t - 3, "&lt;", 4) ||
 
				                                       !g_ascii_strncasecmp(t - 3, "&gt;", 4))) ||
 
				                     (t > (text+4) && (!g_ascii_strncasecmp(t - 5, "&quot;", 6)))))) {
 
					/* local part will already be part of ret, strip it out */
 
					ret = g_string_truncate(ret, ret->len - (c - t));
 
					ret = g_string_append_unichar(ret, g);
 
					break;
 
				} else {
 
					g_string_prepend_unichar(gurl_buf, g);
 
					t = g_utf8_find_prev_char(text, t);
 
					if (t < text) {
 
						ret = g_string_assign(ret, "");
 
						break;
 
					}
 
				}
 
			}
 

	
 
			t = g_utf8_find_next_char(c, NULL);
 

	
 
			while (flag) {
 
				/* iterate forwards grabbing the domain part of an email address */
 
				g = g_utf8_get_char(t);
 
				if (badchar(*t) || (g >= 127) || (*t == ')') || badentity(t)) {
 
					char *d;
 

	
 
					url_buf = g_string_free(gurl_buf, FALSE);
 

	
 
					/* strip off trailing periods */
 
					if (strlen(url_buf) > 0) {
 
						for (d = url_buf + strlen(url_buf) - 1; *d == '.'; d--, t--)
 
							*d = '\0';
 
					}
 

	
 
					tmpurlbuf = purple_unescape_html(url_buf);
 
					if (purple_email_is_valid(tmpurlbuf)) {
 
						g_string_append_printf(ret, "<A HREF=\"mailto:%s\">%s</A>",
 
								url_buf, url_buf);
 
					} else {
 
						g_string_append(ret, url_buf);
 
					}
 
					g_free(url_buf);
 
					g_free(tmpurlbuf);
 
					c = t;
 

	
 
					break;
 
				} else {
 
					g_string_append_unichar(gurl_buf, g);
 
					t = g_utf8_find_next_char(t, NULL);
 
				}
 
			}
 
		}
 

	
 
		if(*c == ')' && !inside_html) {
 
			inside_paren--;
 
			ret = g_string_append_c(ret, *c);
 
			c++;
 
		}
 

	
 
		if (*c == 0)
 
			break;
 

	
 
		ret = g_string_append_c(ret, *c);
 
		c++;
 

	
 
	}
 
	return g_string_free(ret, FALSE);
 
}
 

	
 
struct authRequest {
 
	PurpleAccountRequestAuthorizationCb authorize_cb;
 
	PurpleAccountRequestAuthorizationCb deny_cb;
 
@@ -509,13 +208,13 @@ static std::string getAlias(PurpleBuddy *m_buddy) {
 

	
 
class SpectrumNetworkPlugin : public NetworkPlugin {
 
	public:
 
		SpectrumNetworkPlugin(const std::string &host, int port) : NetworkPlugin() {
 
		SpectrumNetworkPlugin() : NetworkPlugin() {
 

	
 
		}
 

	
 
		void handleExitRequest() {
 
			LOG4CXX_INFO(logger, "Exiting...");
 
			exit(1);
 
			exit(0);
 
		}
 

	
 
		void getProtocolAndName(const std::string &legacyName, std::string &name, std::string &protocol) {
 
@@ -614,7 +313,6 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 
				return;
 
			}
 

	
 

	
 
			if (purple_accounts_find(name.c_str(), protocol.c_str()) != NULL) {
 
				LOG4CXX_INFO(logger, "Using previously created account with name '" << name.c_str() << "' and protocol '" << protocol << "'");
 
				account = purple_accounts_find(name.c_str(), protocol.c_str());
 
@@ -637,11 +335,13 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 

	
 
			setDefaultAccountOptions(account);
 

	
 
			// Enable account + privacy lists
 
			purple_account_set_enabled(account, "spectrum", TRUE);
 
			if (KEYFILE_BOOL("service", "enable_privacy_lists")) {
 
				purple_account_set_privacy_type(account, PURPLE_PRIVACY_DENY_USERS);
 
			}
 

	
 
			// Set the status
 
			const PurpleStatusType *status_type = purple_account_get_status_type_with_primitive(account, PURPLE_STATUS_AVAILABLE);
 
			if (status_type != NULL) {
 
				purple_account_set_status(account, purple_status_type_get_id(status_type), TRUE, NULL);
 
@@ -661,50 +361,6 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 
				m_accounts.erase(account);
 

	
 
				purple_accounts_delete(account);
 
// 
 
// 				// Remove conversations.
 
// 				// This has to be called before m_account->ui_data = NULL;, because it uses
 
// 				// ui_data to call SpectrumMessageHandler::purpleConversationDestroyed() callback.
 
// 				GList *iter;
 
// 				for (iter = purple_get_conversations(); iter; ) {
 
// 					PurpleConversation *conv = (PurpleConversation*) iter->data;
 
// 					iter = iter->next;
 
// 					if (purple_conversation_get_account(conv) == account)
 
// 						purple_conversation_destroy(conv);
 
// 				}
 
// 
 
// 				g_free(account->ui_data);
 
// 				account->ui_data = NULL;
 
// 				m_accounts.erase(account);
 
// 
 
// 				purple_notify_close_with_handle(account);
 
// 				purple_request_close_with_handle(account);
 
// 
 
// 				purple_accounts_remove(account);
 
// 
 
// 				GSList *buddies = purple_find_buddies(account, NULL);
 
// 				while(buddies) {
 
// 					PurpleBuddy *b = (PurpleBuddy *) buddies->data;
 
// 					purple_blist_remove_buddy(b);
 
// 					buddies = g_slist_delete_link(buddies, buddies);
 
// 				}
 
// 
 
// 				/* Remove any open conversation for this account */
 
// 				for (GList *it = purple_get_conversations(); it; ) {
 
// 					PurpleConversation *conv = (PurpleConversation *) it->data;
 
// 					it = it->next;
 
// 					if (purple_conversation_get_account(conv) == account)
 
// 						purple_conversation_destroy(conv);
 
// 				}
 
// 
 
// 				/* Remove this account's pounces */
 
// 					// purple_pounce_destroy_all_by_account(account);
 
// 
 
// 				/* This will cause the deletion of an old buddy icon. */
 
// 				purple_buddy_icons_set_account_icon(account, NULL, 0);
 
// 
 
// 				purple_account_destroy(account);
 
				// force returning of memory chunks allocated by libxml2 to kernel
 
#ifndef WIN32
 
				malloc_trim(0);
 
#endif
 
@@ -768,18 +424,31 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, legacyName.c_str(), account);
 
				PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, legacyName.c_str(), account);
 
				if (!conv) {
 
					conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, legacyName.c_str(), account);
 
					if (!conv) {
 
						conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, legacyName.c_str());
 
					}
 
				}
 
				if (xhtml.empty()) {
 
					gchar *_markup = purple_markup_escape_text(message.c_str(), -1);
 
					if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
 
						purple_conv_im_send(PURPLE_CONV_IM(conv), _markup);
 
					}
 
					else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
 
						purple_conv_chat_send(PURPLE_CONV_CHAT(conv), _markup);
 
					}
 
					g_free(_markup);
 
				}
 
				else {
 
					if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
 
						purple_conv_im_send(PURPLE_CONV_IM(conv), xhtml.c_str());
 
					}
 
					else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
 
						purple_conv_chat_send(PURPLE_CONV_CHAT(conv), xhtml.c_str());
 
					}
 
				}
 
			}
 
		}
 

	
 
@@ -989,9 +658,9 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 
		}
 

	
 
		void sendData(const std::string &string) {
 
			write(m_sock, string.c_str(), string.size());
 
			write(main_socket, string.c_str(), string.size());
 
			if (writeInput == 0)
 
				writeInput = purple_input_add(m_sock, PURPLE_INPUT_WRITE, &transportDataReceived, NULL);
 
				writeInput = purple_input_add(main_socket, PURPLE_INPUT_WRITE, &transportDataReceived, NULL);
 
		}
 

	
 
		void readyForData() {
 
@@ -1213,8 +882,9 @@ static PurpleBlistUiOps blistUiOps =
 

	
 
static void conv_write_im(PurpleConversation *conv, const char *who, const char *msg, PurpleMessageFlags flags, time_t mtime) {
 
	// Don't forwards our own messages.
 
	if (flags & PURPLE_MESSAGE_SEND || flags & PURPLE_MESSAGE_SYSTEM)
 
	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM && (flags & PURPLE_MESSAGE_SEND || flags & PURPLE_MESSAGE_SYSTEM)) {
 
		return;
 
	}
 
	PurpleAccount *account = purple_conversation_get_account(conv);
 

	
 
// 	char *striped = purple_markup_strip_html(message);
 
@@ -1253,19 +923,67 @@ static void conv_write_im(PurpleConversation *conv, const char *who, const char
 

	
 
// 	LOG4CXX_INFO(logger, "Received message body='" << message_ << "' xhtml='" << xhtml_ << "'");
 

	
 
	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
 
		np->handleMessage(np->m_accounts[account], w, message_, "", xhtml_);
 
	}
 
	else {
 
		LOG4CXX_INFO(logger, "Received message body='" << message_ << "' name='" << purple_conversation_get_name(conv) << "' " << w);
 
		np->handleMessage(np->m_accounts[account], purple_conversation_get_name(conv), message_, w, xhtml_);
 
	}
 
}
 

	
 
static void conv_chat_add_users(PurpleConversation *conv, GList *cbuddies, gboolean new_arrivals) {
 
	PurpleAccount *account = purple_conversation_get_account(conv);
 

	
 
	GList *l = cbuddies;
 
	while (l != NULL) {
 
		PurpleConvChatBuddy *cb = (PurpleConvChatBuddy *)l->data;
 
		std::string name(cb->name);
 
		int flags = GPOINTER_TO_INT(cb->flags);
 
		if (flags & PURPLE_CBFLAGS_OP || flags & PURPLE_CBFLAGS_HALFOP) {
 
// 			item->addAttribute("affiliation", "admin");
 
// 			item->addAttribute("role", "moderator");
 
			flags = 1;
 
		}
 
		else if (flags & PURPLE_CBFLAGS_FOUNDER) {
 
// 			item->addAttribute("affiliation", "owner");
 
// 			item->addAttribute("role", "moderator");
 
			flags = 1;
 
		}
 
		else {
 
			flags = 0;
 
// 			item->addAttribute("affiliation", "member");
 
// 			item->addAttribute("role", "participant");
 
		}
 

	
 
		np->handleParticipantChanged(np->m_accounts[account], name, purple_conversation_get_name(conv), (int) flags, pbnetwork::STATUS_ONLINE);
 

	
 
		l = l->next;
 
	}
 
}
 

	
 
static void conv_chat_remove_users(PurpleConversation *conv, GList *users) {
 
	PurpleAccount *account = purple_conversation_get_account(conv);
 

	
 
	GList *l = users;
 
	while (l != NULL) {
 
		std::string name((char *) l->data);
 
		np->handleParticipantChanged(np->m_accounts[account], name, purple_conversation_get_name(conv), 0, pbnetwork::STATUS_NONE);
 

	
 
		l = l->next;
 
	}
 
}
 

	
 
static PurpleConversationUiOps conversation_ui_ops =
 
{
 
	NULL,
 
	NULL,
 
	NULL,//conv_write_chat,                              /* write_chat           */
 
	conv_write_im,//conv_write_chat,                              /* write_chat           */
 
	conv_write_im,             /* write_im             */
 
	NULL,//conv_write_conv,           /* write_conv           */
 
	NULL,//conv_chat_add_users,       /* chat_add_users       */
 
	conv_chat_add_users,       /* chat_add_users       */
 
	NULL,//conv_chat_rename_user,     /* chat_rename_user     */
 
	NULL,//conv_chat_remove_users,    /* chat_remove_users    */
 
	conv_chat_remove_users,    /* chat_remove_users    */
 
	NULL,//pidgin_conv_chat_update_user,     /* chat_update_user     */
 
	NULL,//pidgin_conv_present_conversation, /* present              */
 
	NULL,//pidgin_conv_has_focus,            /* has_focus            */
 
@@ -1407,11 +1125,13 @@ static void *notify_user_info(PurpleConnection *gc, const char *who, PurpleNotif
 
			if (true) {
 
				gchar *data;
 
				gchar *path = purple_buddy_icon_get_full_path(icon);
 
				if (path) {
 
					if (g_file_get_contents(path, &data, &len, NULL)) {
 
						photo = std::string(data, len);
 
					free(data);
 
						g_free(data);
 
					}
 
					g_free(path);
 
				}
 
				free(path);
 
			}
 
			else {
 
				const gchar * data = (gchar*)purple_buddy_icon_get_data(icon, &len);
 
@@ -1800,7 +1520,6 @@ static bool initPurple() {
 
	remove("./accounts.xml");
 
	remove("./blist.xml");
 

	
 
// 	if (m_configuration.logAreas & LOG_AREA_PURPLE)
 
	purple_debug_set_ui_ops(&debugUiOps);
 
	purple_debug_set_verbose(true);
 

	
 
@@ -1866,50 +1585,7 @@ static bool initPurple() {
 
	}
 
	return ret;
 
}
 
#ifndef WIN32
 
static void spectrum_sigchld_handler(int sig)
 
{
 
	int status;
 
	pid_t pid;
 

	
 
	do {
 
		pid = waitpid(-1, &status, WNOHANG);
 
	} while (pid != 0 && pid != (pid_t)-1);
 

	
 
	if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
 
		char errmsg[BUFSIZ];
 
		snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
 
		perror(errmsg);
 
	}
 
}
 
#endif
 

	
 
static int create_socket(char *host, int portno) {
 
	struct sockaddr_in serv_addr;
 
	
 
	int m_sock = socket(AF_INET, SOCK_STREAM, 0);
 
	memset((char *) &serv_addr, 0, sizeof(serv_addr));
 
	serv_addr.sin_family = AF_INET;
 
	serv_addr.sin_port = htons(portno);
 

	
 
	hostent *hos;  // Resolve name
 
	if ((hos = gethostbyname(host)) == NULL) {
 
		// strerror() will not work for gethostbyname() and hstrerror() 
 
		// is supposedly obsolete
 
		exit(1);
 
	}
 
	serv_addr.sin_addr.s_addr = *((unsigned long *) hos->h_addr_list[0]);
 

	
 
	if (connect(m_sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
 
		close(m_sock);
 
		m_sock = 0;
 
	}
 

	
 
	int flags = fcntl(m_sock, F_GETFL);
 
	flags |= O_NONBLOCK;
 
	fcntl(m_sock, F_SETFL, flags);
 
	return m_sock;
 
}
 

	
 
static void transportDataReceived(gpointer data, gint source, PurpleInputCondition cond) {
 
	if (cond & PURPLE_INPUT_READ) {
 
@@ -1938,17 +1614,10 @@ int main(int argc, char **argv) {
 
	context = g_option_context_new("config_file_name or profile name");
 
	g_option_context_add_main_entries(context, options_entries, "");
 
	if (!g_option_context_parse (context, &argc, &argv, &error)) {
 
		std::cout << "option parsing failed: " << error->message << "\n";
 
		std::cerr << "option parsing failed: " << error->message << "\n";
 
		return -1;
 
	}
 

	
 
	if (ver) {
 
// 		std::cout << VERSION << "\n";
 
		std::cout << "verze\n";
 
		g_option_context_free(context);
 
		return 0;
 
	}
 

	
 
	if (argc != 2) {
 
#ifdef WIN32
 
		std::cout << "Usage: spectrum.exe <configuration_file.cfg>\n";
 
@@ -1972,27 +1641,6 @@ int main(int argc, char **argv) {
 
			g_option_context_free(context);
 
			return -1;
 
		}
 
// 
 
// 		if (signal(SIGINT, spectrum_sigint_handler) == SIG_ERR) {
 
// 			std::cout << "SIGINT handler can't be set\n";
 
// 			g_option_context_free(context);
 
// 			return -1;
 
// 		}
 
// 
 
// 		if (signal(SIGTERM, spectrum_sigterm_handler) == SIG_ERR) {
 
// 			std::cout << "SIGTERM handler can't be set\n";
 
// 			g_option_context_free(context);
 
// 			return -1;
 
// 		}
 
// 
 
// 		struct sigaction sa;
 
// 		memset(&sa, 0, sizeof(sa)); 
 
// 		sa.sa_handler = spectrum_sighup_handler;
 
// 		if (sigaction(SIGHUP, &sa, NULL)) {
 
// 			std::cout << "SIGHUP handler can't be set\n";
 
// 			g_option_context_free(context);
 
// 			return -1;
 
//		}
 
#endif
 
		keyfile = g_key_file_new ();
 
		if (!g_key_file_load_from_file (keyfile, argv[1], (GKeyFileFlags) 0, 0)) {
 
@@ -2027,12 +1675,11 @@ int main(int argc, char **argv) {
 

	
 
		initPurple();
 

	
 
		m_sock = create_socket(host, port);
 

	
 
		purple_input_add(m_sock, PURPLE_INPUT_READ, &transportDataReceived, NULL);
 
		main_socket = create_socket(host, port);
 
		purple_input_add(main_socket, PURPLE_INPUT_READ, &transportDataReceived, NULL);
 
		purple_timeout_add_seconds(30, pingTimeout, NULL);
 

	
 
		np = new SpectrumNetworkPlugin(host, port);
 
		np = new SpectrumNetworkPlugin();
 
		bool libev = KEYFILE_STRING("service", "eventloop") == "libev";
 

	
 
		GMainLoop *m_loop;
backends/libpurple/utils.cpp
Show inline comments
 
new file 100644
 
/**
 
 * libtransport -- C++ library for easy XMPP Transports development
 
 *
 
 * Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
 
 *
 
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#include "utils.h"
 

	
 
#include "glib.h"
 
#include "purple.h"
 
#include <algorithm>
 
#include <iostream>
 

	
 
#include "errno.h"
 

	
 
#ifndef WIN32 
 
#include "sys/wait.h"
 
#include "sys/signal.h"
 
#include <netinet/if_ether.h>
 
#include <netinet/ip.h>
 
#include <netinet/ip6.h>
 
#include <netinet/udp.h>
 
#include <netinet/tcp.h>
 
#include <netinet/ether.h>
 
#include "sys/socket.h"
 
#include <netdb.h>
 
#include <unistd.h>
 
#include <fcntl.h>
 
#else 
 
#include <process.h>
 
#define getpid _getpid 
 
#define ssize_t SSIZE_T
 
#include "win32/win32dep.h"
 
#endif
 

	
 
static GHashTable *ui_info = NULL;
 

	
 
GHashTable *spectrum_ui_get_info(void)
 
{
 
	if(NULL == ui_info) {
 
		ui_info = g_hash_table_new(g_str_hash, g_str_equal);
 

	
 
		g_hash_table_insert(ui_info, g_strdup("name"), g_strdup("Spectrum"));
 
		g_hash_table_insert(ui_info, g_strdup("version"), g_strdup("0.5"));
 
		g_hash_table_insert(ui_info, g_strdup("website"), g_strdup("http://spectrum.im"));
 
		g_hash_table_insert(ui_info, g_strdup("dev_website"), g_strdup("http://spectrum.im"));
 
		g_hash_table_insert(ui_info, g_strdup("client_type"), g_strdup("pc"));
 

	
 
		/*
 
		 * This is the client key for "Pidgin."  It is owned by the AIM
 
		 * account "markdoliner."  Please don't use this key for other
 
		 * applications.  You can either not specify a client key, in
 
		 * which case the default "libpurple" key will be used, or you
 
		 * can register for your own client key at
 
		 * http://developer.aim.com/manageKeys.jsp
 
		 */
 
		g_hash_table_insert(ui_info, g_strdup("prpl-aim-clientkey"), g_strdup("ma1cSASNCKFtrdv9"));
 
		g_hash_table_insert(ui_info, g_strdup("prpl-icq-clientkey"), g_strdup("ma1cSASNCKFtrdv9"));
 

	
 
		/*
 
		 * This is the distid for Pidgin, given to us by AOL.  Please
 
		 * don't use this for other applications.  You can just not
 
		 * specify a distid and libpurple will use a default.
 
		 */
 
		g_hash_table_insert(ui_info, g_strdup("prpl-aim-distid"), GINT_TO_POINTER(1550));
 
		g_hash_table_insert(ui_info, g_strdup("prpl-icq-distid"), GINT_TO_POINTER(1550));
 
	}
 

	
 
	return ui_info;
 
}
 

	
 
#ifndef WIN32
 
void spectrum_sigchld_handler(int sig)
 
{
 
	int status;
 
	pid_t pid;
 

	
 
	do {
 
		pid = waitpid(-1, &status, WNOHANG);
 
	} while (pid != 0 && pid != (pid_t)-1);
 

	
 
	if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
 
		char errmsg[BUFSIZ];
 
		snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
 
		perror(errmsg);
 
	}
 
}
 
#endif
 

	
 
int create_socket(char *host, int portno) {
 
	struct sockaddr_in serv_addr;
 
	
 
	int main_socket = socket(AF_INET, SOCK_STREAM, 0);
 
	memset((char *) &serv_addr, 0, sizeof(serv_addr));
 
	serv_addr.sin_family = AF_INET;
 
	serv_addr.sin_port = htons(portno);
 

	
 
	hostent *hos;  // Resolve name
 
	if ((hos = gethostbyname(host)) == NULL) {
 
		// strerror() will not work for gethostbyname() and hstrerror() 
 
		// is supposedly obsolete
 
		exit(1);
 
	}
 
	serv_addr.sin_addr.s_addr = *((unsigned long *) hos->h_addr_list[0]);
 

	
 
	if (connect(main_socket, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
 
		close(main_socket);
 
		main_socket = 0;
 
	}
 

	
 
	int flags = fcntl(main_socket, F_GETFL);
 
	flags |= O_NONBLOCK;
 
	fcntl(main_socket, F_SETFL, flags);
 
	return main_socket;
 
}
backends/libpurple/utils.h
Show inline comments
 
new file 100644
 
/**
 
 * libtransport -- C++ library for easy XMPP Transports development
 
 *
 
 * Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
 
 *
 
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#pragma once
 

	
 
#include "purple.h"
 

	
 
#ifndef WIN32
 
void spectrum_sigchld_handler(int sig);
 
#endif
 

	
 
int create_socket(char *host, int portno);
 
GHashTable *spectrum_ui_get_info(void);
 
\ No newline at end of file
backends/skype/main.cpp
Show inline comments
 
@@ -2,8 +2,10 @@
 
#include <iostream>
 

	
 
#include "transport/config.h"
 
#include "transport/logging.h"
 
#include "transport/transport.h"
 
#include "transport/usermanager.h"
 
#include "transport/memoryusage.h"
 
#include "transport/logger.h"
 
#include "transport/sqlite3backend.h"
 
#include "transport/userregistration.h"
 
@@ -34,6 +36,10 @@ using namespace Transport;
 

	
 
class SpectrumNetworkPlugin;
 

	
 
#define GET_RESPONSE_DATA(RESP, DATA) ((RESP.find(std::string(DATA) + " ") != std::string::npos) ? RESP.substr(RESP.find(DATA) + strlen(DATA) + 1) : "");
 
#define GET_PROPERTY(VAR, OBJ, WHICH, PROP) std::string VAR = sk->send_command(std::string("GET ") + OBJ + " " + WHICH + " " + PROP); \
 
					VAR = GET_RESPONSE_DATA(VAR, PROP);
 

	
 

	
 
SpectrumNetworkPlugin *np;
 

	
 
@@ -81,7 +87,7 @@ static pbnetwork::StatusType getStatus(const std::string &st) {
 
class Skype {
 
	public:
 
		Skype(const std::string &user, const std::string &username, const std::string &password);
 
		~Skype() { logout(); }
 
		~Skype() { LOG4CXX_INFO(logger, "Skype instance desctuctor"); logout(); }
 
		void login();
 
		void logout();
 
		std::string send_command(const std::string &message);
 
@@ -97,6 +103,10 @@ class Skype {
 
		bool createDBusProxy();
 
		bool loadSkypeBuddies();
 

	
 
		int getPid() {
 
			return (int) m_pid;
 
		}
 

	
 
	private:
 
		std::string m_username;
 
		std::string m_password;
 
@@ -124,7 +134,9 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 

	
 
		void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
 
			std::string name = legacyName;
 
			if (name.find("skype.") == 0 || name.find("prpl-skype.") == 0) {
 
				name = name.substr(name.find(".") + 1);
 
			}
 
			LOG4CXX_INFO(logger,  "Creating account with name '" << name << "'");
 

	
 
			Skype *skype = new Skype(user, name, password);
 
@@ -134,9 +146,25 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 
			skype->login();
 
		}
 

	
 
		void handleMemoryUsage(double &res, double &shared) {
 
			res = 0;
 
			shared = 0;
 
			for(std::map<std::string, Skype *>::const_iterator it = m_sessions.begin(); it != m_sessions.end(); it++) {
 
				Skype *skype = it->second;
 
				if (skype) {
 
					double r;
 
					double s;
 
					process_mem_usage(s, r, skype->getPid());
 
					res += r;
 
					shared += s;
 
				}
 
			}
 
		}
 

	
 
		void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
 
			Skype *skype = m_sessions[user];
 
			if (skype) {
 
				LOG4CXX_INFO(logger, "User wants to logout, logging out");
 
				skype->logout();
 
				exit(1);
 
			}
 
@@ -178,6 +206,21 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 
			}
 
		}
 

	
 
		void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
 
			Skype *skype = m_sessions[user];
 
			if (skype) {
 
				skype->send_command("SET USER " + buddyName + " BUDDYSTATUS 2 Please authorize me");
 
				skype->send_command("SET USER " + buddyName + " ISAUTHORIZED TRUE");
 
			}
 
		}
 

	
 
		void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
 
			Skype *skype = m_sessions[user];
 
			if (skype) {
 
				skype->send_command("SET USER " + buddyName + " BUDDYSTATUS 1");
 
			}
 
		}
 

	
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml) {
 
			Skype *skype = m_sessions[user];
 
			if (skype) {
 
@@ -253,7 +296,7 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 
				std::cout << skype->getUsername() << " " << name << "\n";
 
				if (skype->getUsername() == name) {
 
					alias = skype->send_command("GET PROFILE FULLNAME");
 
					alias = alias.substr(17);
 
					alias = GET_RESPONSE_DATA(alias, "FULLNAME")
 
				}
 
				handleVCard(user, id, legacyName, "", alias, photo);
 
			}
 
@@ -268,13 +311,6 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 
		void handleVCardUpdatedRequest(const std::string &user, const std::string &p, const std::string &nickname) {
 
		}
 

	
 
		void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
 
		}
 

	
 
		void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
 

	
 
		}
 

	
 
		void handleBuddyBlockToggled(const std::string &user, const std::string &buddyName, bool blocked) {
 

	
 
		}
 
@@ -331,7 +367,8 @@ bool Skype::createDBusProxy() {
 
			LOG4CXX_INFO(logger,  m_username << ":" << error->message);
 

	
 
			if (m_counter == 15) {
 
				np->handleDisconnected(m_user, 0, error->message);
 
				LOG4CXX_ERROR(logger, "Logging out, proxy couldn't be created");
 
				np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, error->message);
 
				logout();
 
				g_error_free(error);
 
				return FALSE;
 
@@ -360,6 +397,12 @@ static gboolean create_dbus_proxy(gpointer data) {
 
}
 

	
 
void Skype::login() {
 
	if (m_username.find("..") == 0 || m_username.find("/") != std::string::npos) {
 
		np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Invalid username");
 
		return;
 
	}
 
	boost::filesystem::remove_all(std::string("/tmp/skype/") + m_username);
 

	
 
	boost::filesystem::path	path(std::string("/tmp/skype/") + m_username);
 
	if (!boost::filesystem::exists(path)) {
 
		boost::filesystem::create_directories(path);
 
@@ -394,6 +437,7 @@ void Skype::login() {
 
							"</config>\n";
 
	g_file_set_contents(std::string(std::string("/tmp/skype/") + m_username + "/" + m_username +"/config.xml").c_str(), config_xml.c_str(), -1, NULL);
 

	
 
	sleep(1);
 
	std::string db_path = std::string("/tmp/skype/") + m_username;
 
	char *db = (char *) malloc(db_path.size() + 1);
 
	strcpy(db, db_path.c_str());
 
@@ -437,6 +481,7 @@ void Skype::login() {
 
		}
 
	}
 

	
 
	sleep(1);
 
	m_timer = g_timeout_add_seconds(1, create_dbus_proxy, this);
 
}
 

	
 
@@ -449,28 +494,35 @@ bool Skype::loadSkypeBuddies() {
 
	int bytes_read = read(fd_output, buffer, 1023);
 
	if (bytes_read > 0) {
 
		buffer[bytes_read] = 0;
 
		np->handleDisconnected(m_user, 0, buffer);
 
		std::string b(buffer);
 
		LOG4CXX_WARN(logger, "Skype wrote this on stdout '" << b << "'");
 
		if (b.find("Incorrect Password") != std::string::npos) {
 
			LOG4CXX_INFO(logger, "Incorrect password, logging out")
 
			np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_FAILED, "Incorrect password");
 
			close(fd_output);
 
			logout();
 
			return FALSE;
 
		}
 
	}
 

	
 
	std::string re = send_command("NAME Spectrum");
 
	if (m_counter++ > 15) {
 
		np->handleDisconnected(m_user, 0, "");
 
		LOG4CXX_ERROR(logger, "Logging out, because we tried to connect the Skype over DBUS 15 times without success");
 
		np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Skype is not ready. This issue have been logged and admins will check it and try to fix it soon.");
 
		close(fd_output);
 
		logout();
 
		return FALSE;
 
	}
 

	
 
	if (re.empty() || re == "CONNSTATUS OFFLINE") {
 
	if (re.empty() || re == "CONNSTATUS OFFLINE" || re == "ERROR 68") {
 
		return TRUE;
 
	}
 

	
 
	close(fd_output);
 

	
 
	if (send_command("PROTOCOL 7") != "PROTOCOL 7") {
 
		np->handleDisconnected(m_user, 0, "Skype is not ready");
 
		LOG4CXX_ERROR(logger, "PROTOCOL 7 failed, logging out");
 
		np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Skype is not ready. This issue have been logged and admins will check it and try to fix it soon.");
 
		logout();
 
		return FALSE;
 
	}
 
@@ -479,22 +531,29 @@ bool Skype::loadSkypeBuddies() {
 

	
 
	std::map<std::string, std::string> group_map;
 
	std::string groups = send_command("SEARCH GROUPS CUSTOM");
 
	if (groups.find(' ') != std::string::npos) {
 
		groups = groups.substr(groups.find(' ') + 1);
 
		std::vector<std::string> grps;
 
		boost::split(grps, groups, boost::is_any_of(","));
 
		BOOST_FOREACH(std::string grp, grps) {
 
			std::vector<std::string> data;
 
			std::string name = send_command("GET GROUP " + grp + " DISPLAYNAME");
 

	
 
			if (name.find("ERROR") == 0) {
 
				continue;
 
			}
 

	
 
			boost::split(data, name, boost::is_any_of(" "));
 
		name = name.substr(name.find("DISPLAYNAME") + 12);
 
			name = GET_RESPONSE_DATA(name, "DISPLAYNAME");
 

	
 
			std::string users = send_command("GET GROUP " + data[1] + " USERS");
 
		users = name.substr(name.find("USERS") + 6);
 
			users = GET_RESPONSE_DATA(users, "USERS");
 
			boost::split(data, users, boost::is_any_of(","));
 
			BOOST_FOREACH(std::string u, data) {
 
				group_map[u] = grp;
 
			}
 
		}
 
	}
 

	
 
	std::string friends = send_command("GET AUTH_CONTACTS_PROFILES");
 

	
 
@@ -565,6 +624,7 @@ std::string Skype::send_command(const std::string &message) {
 
// 			int message_num;
 
// 			gchar error_return[30];
 

	
 
	LOG4CXX_INFO(logger, "Sending: '" << message << "'");
 
	if (!dbus_g_proxy_call (m_proxy, "Invoke", &error, G_TYPE_STRING, message.c_str(), G_TYPE_INVALID,
 
						G_TYPE_STRING, &str, G_TYPE_INVALID))
 
	{
 
@@ -572,14 +632,16 @@ std::string Skype::send_command(const std::string &message) {
 
			{
 
			LOG4CXX_INFO(logger,  m_username << ": DBUS Error: " << error->message);
 
			g_error_free(error);
 
			return "";
 
		} else {
 
			LOG4CXX_INFO(logger,  m_username << ": DBUS no response");
 
			return "";
 
		}
 

	
 
	}
 
	if (str != NULL)
 
	{
 
		LOG4CXX_INFO(logger,  m_username << ": DBUS:" << str);
 
		LOG4CXX_INFO(logger,  m_username << ": DBUS:'" << str << "'");
 
	}
 
	return str ? std::string(str) : std::string();
 
}
 
@@ -599,70 +661,73 @@ static void handle_skype_message(std::string &message, Skype *sk) {
 
			}
 
			else {
 
				pbnetwork::StatusType status = getStatus(cmd[3]);
 
				std::string mood_text = sk->send_command("GET USER " + cmd[1] + " MOOD_TEXT");
 
				mood_text = mood_text.substr(mood_text.find("MOOD_TEXT") + 10);
 

	
 
				std::string alias = sk->send_command("GET USER " + cmd[1] + " FULLNAME");
 
				alias = alias.substr(alias.find("FULLNAME") + 9);
 
				GET_PROPERTY(mood_text, "USER", cmd[1], "MOOD_TEXT");
 
				GET_PROPERTY(alias, "USER", cmd[1], "FULLNAME");
 

	
 
				std::vector<std::string> groups;
 
				np->handleBuddyChanged(sk->getUser(), cmd[1], alias, groups, status, mood_text);
 
			}
 
		}
 
		else if (cmd[2] == "MOOD_TEXT") {
 
			std::string st = sk->send_command("GET USER " + cmd[1] + " ONLINESTATUS");
 
			st = st.substr(st.find("ONLINESTATUS") + 13);
 
			GET_PROPERTY(st, "USER", cmd[1], "ONLINESTATUS");
 
			pbnetwork::StatusType status = getStatus(st);
 

	
 
			std::string mood_text = message.substr(message.find("MOOD_TEXT") + 10);
 
			std::string mood_text = GET_RESPONSE_DATA(message, "MOOD_TEXT");
 

	
 
			std::vector<std::string> groups;
 
			np->handleBuddyChanged(sk->getUser(), cmd[1], "", groups, status, mood_text);
 
		}
 
		else if (cmd[2] == "BUDDYSTATUS" && cmd[3] == "3") {
 
			std::string st = sk->send_command("GET USER " + cmd[1] + " ONLINESTATUS");
 
			st = st.substr(st.find("ONLINESTATUS") + 13);
 
			GET_PROPERTY(mood_text, "USER", cmd[1], "MOOD_TEXT");
 
			GET_PROPERTY(st, "USER", cmd[1], "ONLINESTATUS");
 
			pbnetwork::StatusType status = getStatus(st);
 

	
 
			std::string mood_text = message.substr(message.find("MOOD_TEXT") + 10);
 

	
 
			std::vector<std::string> groups;
 
			np->handleBuddyChanged(sk->getUser(), cmd[1], "", groups, status, mood_text);
 
		}
 
		else if (cmd[2] == "FULLNAME") {
 
			std::string st = sk->send_command("GET USER " + cmd[1] + " ONLINESTATUS");
 
			st = st.substr(st.find("ONLINESTATUS") + 13);
 
			GET_PROPERTY(alias, "USER", cmd[1], "FULLNAME");
 
			GET_PROPERTY(mood_text, "USER", cmd[1], "MOOD_TEXT");
 
			GET_PROPERTY(st, "USER", cmd[1], "ONLINESTATUS");
 
			pbnetwork::StatusType status = getStatus(st);
 

	
 
			std::string mood_text = sk->send_command("GET USER " + cmd[1] + " MOOD_TEXT");
 
			mood_text = mood_text.substr(mood_text.find("MOOD_TEXT") + 10);
 

	
 
			std::string alias = message.substr(message.find("FULLNAME") + 9);
 

	
 
			std::vector<std::string> groups;
 
			np->handleBuddyChanged(sk->getUser(), cmd[1], alias, groups, status, mood_text);
 
		}
 
	}
 
	else if (cmd[0] == "CHATMESSAGE") {
 
		if (cmd[3] == "RECEIVED") {
 
			std::string body = sk->send_command("GET CHATMESSAGE " + cmd[1] + " BODY");
 
			body = body.substr(body.find("BODY") + 5);
 
			GET_PROPERTY(body, "CHATMESSAGE", cmd[1], "BODY");
 
			GET_PROPERTY(from_handle, "CHATMESSAGE", cmd[1], "FROM_HANDLE");
 

	
 
			std::string chatname = sk->send_command("GET CHATMESSAGE " + cmd[1] + " CHATNAME");
 
			size_t start = chatname.find("$") + 1;
 
			size_t len = chatname.find(";") - start;
 
			std::string from = chatname.substr(start, len);
 
			if (from_handle == sk->getUsername())
 
				return;
 

	
 
			std::string from_handle = sk->send_command("GET CHATMESSAGE " + cmd[1] + " FROM_HANDLE");
 
			from_handle = from_handle.substr(from_handle.find("FROM_HANDLE") + 12);
 
			np->handleMessage(sk->getUser(), from_handle, body);
 

	
 
// 			if (from_handle != sk->getUsername()) {
 
				from = from_handle;
 
// 			}
 
			if (from_handle == sk->getUsername())
 
			sk->send_command("SET CHATMESSAGE " + cmd[1] + " SEEN");
 
		}
 
	}
 
	else if (cmd[0] == "CALL") {
 
		// CALL 884 STATUS RINGING
 
		if (cmd[2] == "STATUS") {
 
			if (cmd[3] == "RINGING" || cmd[3] == "MISSED") {
 
				// handle only incoming calls
 
				GET_PROPERTY(type, "CALL", cmd[1], "TYPE");
 
				if (type.find("INCOMING") != 0) {
 
					return;
 
				}
 

	
 
				GET_PROPERTY(from, "CALL", cmd[1], "PARTNER_HANDLE");
 
				GET_PROPERTY(dispname, "CALL", cmd[1], "PARTNER_DISPNAME");
 

	
 
			np->handleMessage(sk->getUser(), from, body);
 
				if (cmd[3] == "RINGING") {
 
					np->handleMessage(sk->getUser(), from, "User " + dispname + " is calling you.");
 
				}
 
				else {
 
					np->handleMessage(sk->getUser(), from, "You have missed call from user " + dispname + ".");
 
				}
 
			}
 
		}
 
	}
 
}
 
@@ -825,18 +890,7 @@ int main(int argc, char **argv) {
 
			return 1;
 
		}
 

	
 
		if (CONFIG_STRING(&config, "logging.backend_config").empty()) {
 
			LoggerPtr root = log4cxx::Logger::getRootLogger();
 
			root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n")));
 
		}
 
		else {
 
			log4cxx::helpers::Properties p;
 
			log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(&config, "logging.backend_config"));
 

	
 
			p.load(istream);
 
			p.setProperty("pid", boost::lexical_cast<std::string>(getpid()));
 
			log4cxx::PropertyConfigurator::configure(p);
 
		}
 
		Logging::initBackendLogging(&config);
 

	
 
// 		initPurple(config);
 

	
backends/smstools3/main.cpp
Show inline comments
 
@@ -9,6 +9,7 @@
 
 */
 

	
 
#include "transport/config.h"
 
#include "transport/logging.h"
 
#include "transport/networkplugin.h"
 
#include "transport/sqlite3backend.h"
 
#include "transport/mysqlbackend.h"
 
@@ -312,81 +313,20 @@ int main (int argc, char* argv[]) {
 
		return 1;
 
	}
 

	
 
	if (CONFIG_STRING(&config, "logging.backend_config").empty()) {
 
		LoggerPtr root = log4cxx::Logger::getRootLogger();
 
#ifndef _MSC_VER
 
		root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n")));
 
#else
 
		root->addAppender(new ConsoleAppender(new PatternLayout(L"%d %-5p %c: %m%n")));
 
#endif
 
	}
 
	else {
 
		log4cxx::helpers::Properties p;
 
		log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(&config, "logging.backend_config"));
 
		p.load(istream);
 
		LogString pid, jid;
 
		log4cxx::helpers::Transcoder::decode(boost::lexical_cast<std::string>(getpid()), pid);
 
		log4cxx::helpers::Transcoder::decode(CONFIG_STRING(&config, "service.jid"), jid);
 
#ifdef _MSC_VER
 
		p.setProperty(L"pid", pid);
 
		p.setProperty(L"jid", jid);
 
#else
 
		p.setProperty("pid", pid);
 
		p.setProperty("jid", jid);
 
#endif
 
		log4cxx::PropertyConfigurator::configure(p);
 
	}
 

	
 
#ifdef WITH_SQLITE
 
	if (CONFIG_STRING(&config, "database.type") == "sqlite3") {
 
		storageBackend = new SQLite3Backend(&config);
 
		if (!storageBackend->connect()) {
 
			std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
 
			return -1;
 
		}
 
	}
 
#else
 
	if (CONFIG_STRING(&config, "database.type") == "sqlite3") {
 
		std::cerr << "Spectrum2 is not compiled with mysql backend.\n";
 
		return -2;
 
	}
 
#endif
 
	Logging::initBackendLogging(&config);
 

	
 
#ifdef WITH_MYSQL
 
	if (CONFIG_STRING(&config, "database.type") == "mysql") {
 
		storageBackend = new MySQLBackend(&config);
 
		if (!storageBackend->connect()) {
 
			std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
 
			return -1;
 
		}
 
	}
 
#else
 
	if (CONFIG_STRING(&config, "database.type") == "mysql") {
 
		std::cerr << "Spectrum2 is not compiled with mysql backend.\n";
 
	std::string error;
 
	StorageBackend *storageBackend = StorageBackend::createBackend(&config, error);
 
	if (storageBackend == NULL) {
 
		if (!error.empty()) {
 
			std::cerr << error << "\n";
 
			return -2;
 
		}
 
#endif
 

	
 
#ifdef WITH_PQXX
 
	if (CONFIG_STRING(&config, "database.type") == "pqxx") {
 
		storageBackend = new PQXXBackend(&config);
 
		if (!storageBackend->connect()) {
 
	}
 
	else if (!storageBackend->connect()) {
 
		std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
 
		return -1;
 
	}
 
	}
 
#else
 
	if (CONFIG_STRING(&config, "database.type") == "pqxx") {
 
		std::cerr << "Spectrum2 is not compiled with pqxx backend.\n";
 
		return -2;
 
	}
 
#endif
 

	
 
	if (CONFIG_STRING(&config, "database.type") != "mysql" && CONFIG_STRING(&config, "database.type") != "sqlite3"
 
		&& CONFIG_STRING(&config, "database.type") != "pqxx" && CONFIG_STRING(&config, "database.type") != "none") {
 
		std::cerr << "Unknown storage backend " << CONFIG_STRING(&config, "database.type") << "\n";
 
		return -2;
 
	}
 

	
 
	Swift::SimpleEventLoop eventLoop;
 
	loop_ = &eventLoop;
include/transport/buddy.h
Show inline comments
 
@@ -39,6 +39,9 @@ typedef enum { 	BUDDY_NO_FLAG = 0,
 
/// Represents one legacy network Buddy.
 
class Buddy {
 
	public:
 
		typedef enum { 	Ask,
 
						Both,
 
					} Subscription;
 
		/// Constructor.
 

	
 
		/// \param rosterManager RosterManager associated with this buddy.
 
@@ -93,12 +96,12 @@ class Buddy {
 
		/// Sets current subscription.
 

	
 
		/// \param subscription "to", "from", "both", "ask"
 
		void setSubscription(const std::string &subscription);
 
		void setSubscription(Subscription subscription);
 

	
 
		/// Returns current subscription
 

	
 
		/// \return subscription "to", "from", "both", "ask"
 
		const std::string getSubscription();
 
		Subscription getSubscription();
 

	
 
		/// Sets this buddy's flags.
 

	
 
@@ -172,6 +175,7 @@ class Buddy {
 
		Swift::JID m_jid;
 
		BuddyFlag m_flags;
 
		RosterManager *m_rosterManager;
 
		Subscription m_subscription;
 
};
 

	
 
}
include/transport/logging.h
Show inline comments
 
new file 100644
 
/**
 
 * libtransport -- C++ library for easy XMPP Transports development
 
 *
 
 * Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
 
 *
 
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#pragma once
 

	
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <vector>
 
#include <string>
 

	
 
namespace Transport {
 

	
 
class Config;
 

	
 
namespace Logging {
 

	
 
void initBackendLogging(Config *config);
 
void initMainLogging(Config *config);
 

	
 
}
 

	
 
}
include/transport/memoryusage.h
Show inline comments
 
@@ -22,10 +22,14 @@
 

	
 
#include <vector>
 

	
 
#ifndef WIN32
 
#include "signal.h"
 
#endif
 

	
 
namespace Transport {
 

	
 
#ifndef WIN32
 
	void process_mem_usage(double& shared, double& resident_set);
 
	void process_mem_usage(double& shared, double& resident_set, pid_t pid = 0);
 
#endif
 

	
 
}
 
\ No newline at end of file
include/transport/networkplugin.h
Show inline comments
 
@@ -211,6 +211,8 @@ class NetworkPlugin {
 
		virtual void handleFTPauseRequest(unsigned long ftID) {}
 
		virtual void handleFTContinueRequest(unsigned long ftID) {}
 

	
 
		virtual void handleMemoryUsage(double &res, double &shared) {res = 0; shared = 0;}
 

	
 
		virtual void handleExitRequest() { exit(1); }
 
		void handleDataRead(std::string &data);
 
		virtual void sendData(const std::string &string) {}
include/transport/networkpluginserver.h
Show inline comments
 
@@ -56,6 +56,7 @@ class NetworkPluginServer {
 
			bool acceptUsers;
 
			bool longRun;
 
			bool willDie;
 
			std::string id;
 
		};
 

	
 
		NetworkPluginServer(Component *component, Config *config, UserManager *userManager, FileTransferManager *ftManager);
 
@@ -70,6 +71,10 @@ class NetworkPluginServer {
 
			return m_clients;
 
		}
 

	
 
		const std::vector<std::string> &getCrashedBackends() {
 
			return m_crashedBackends;
 
		}
 

	
 
		void collectBackend();
 

	
 
		bool moveToLongRunBackend(User *user);
 
@@ -137,6 +142,7 @@ class NetworkPluginServer {
 
		bool m_isNextLongRun;
 
		std::map<unsigned long, FileTransferManager::Transfer> m_filetransfers;
 
		FileTransferManager *m_ftManager;
 
		std::vector<std::string> m_crashedBackends;
 
};
 

	
 
}
include/transport/protocol.proto
Show inline comments
 
@@ -106,6 +106,7 @@ message Stats {
 
	required int32 res = 1;
 
	required int32 init_res = 2;
 
	required int32 shared = 3;
 
	required string id = 4;
 
}
 

	
 
message File {
include/transport/storagebackend.h
Show inline comments
 
@@ -80,6 +80,8 @@ struct BuddyInfo {
 
	int flags;
 
};
 

	
 
class Config;
 

	
 
/// Abstract class defining storage backends.
 
class StorageBackend
 
{
 
@@ -87,6 +89,8 @@ class StorageBackend
 
		/// Virtual desctructor.
 
		virtual ~StorageBackend() {}
 

	
 
		static StorageBackend *createBackend(Config *config, std::string &error);
 

	
 
		/// connect
 
		virtual bool connect() = 0;
 

	
include/transport/usermanager.h
Show inline comments
 
@@ -116,6 +116,13 @@ class UserManager : public Swift::EntityCapsProvider {
 
		/// \param user JID of user.
 
		void disconnectUser(const Swift::JID &user);
 

	
 
		void messageToXMPPSent() { m_sentToXMPP++; }
 
		void messageToBackendSent() { m_sentToBackend++; }
 

	
 
		unsigned long getMessagesToXMPP() { return m_sentToXMPP; }
 
		unsigned long getMessagesToBackend() { return m_sentToBackend; }
 
		
 

	
 
	private:
 
		void handlePresence(Swift::Presence::ref presence);
 
		void handleMessageReceived(Swift::Message::ref message);
 
@@ -134,6 +141,8 @@ class UserManager : public Swift::EntityCapsProvider {
 
		StorageResponder *m_storageResponder;
 
		UserRegistry *m_userRegistry;
 
		Swift::Timer::ref m_removeTimer;
 
		unsigned long m_sentToXMPP;
 
		unsigned long m_sentToBackend;
 
		friend class RosterResponder;
 
};
 

	
plugin/CMakeLists.txt
Show inline comments
 
ADD_SUBDIRECTORY(src)
 
ADD_SUBDIRECTORY(cpp)
 
ADD_SUBDIRECTORY(python)
plugin/cpp/CMakeLists.txt
Show inline comments
 
file renamed from plugin/src/CMakeLists.txt to plugin/cpp/CMakeLists.txt
plugin/cpp/networkplugin.cpp
Show inline comments
 
file renamed from plugin/src/networkplugin.cpp to plugin/cpp/networkplugin.cpp
 
@@ -28,6 +28,8 @@
 
#else 
 
#include <winsock2.h>
 
#include <stdint.h>
 
#include <process.h>
 
#define getpid _getpid
 
#endif
 

	
 
using namespace log4cxx;
 
@@ -41,6 +43,12 @@ namespace Transport {
 
	wrap.set_payload(MESSAGE); \
 
	wrap.SerializeToString(&MESSAGE);
 

	
 
template <class T> std::string stringOf(T object) {
 
	std::ostringstream os;
 
	os << object;
 
	return (os.str());
 
}
 

	
 
NetworkPlugin::NetworkPlugin() {
 
	m_pingReceived = false;
 

	
 
@@ -587,13 +595,19 @@ void NetworkPlugin::sendMemoryUsage() {
 
	pbnetwork::Stats stats;
 

	
 
	stats.set_init_res(m_init_res);
 
	double res;
 
	double shared;
 
	double res = 0;
 
	double shared = 0;
 
#ifndef WIN32
 
	process_mem_usage(shared, res);
 
#endif
 
	stats.set_res(res);
 
	stats.set_shared(shared);
 

	
 
	double e_res;
 
	double e_shared;
 
	handleMemoryUsage(e_res, e_shared);
 

	
 
	stats.set_res(res + e_res);
 
	stats.set_shared(shared + e_shared);
 
	stats.set_id(stringOf(getpid()));
 

	
 
	std::string message;
 
	stats.SerializeToString(&message);
plugin/python/CMakeLists.txt
Show inline comments
 
new file 100644
 
cmake_minimum_required(VERSION 2.6)
 
 
if (PROTOBUF_FOUND)
 
    ADD_CUSTOM_COMMAND(
 
        OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/protocol_pb2.py
 
        COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --python_out  ${CMAKE_CURRENT_BINARY_DIR} --proto_path ${CMAKE_CURRENT_BINARY_DIR}/../../include/transport/ ${CMAKE_CURRENT_BINARY_DIR}/../../include/transport/protocol.proto
 
        COMMENT "Running Python protocol buffer compiler on protocol.proto"
 
        DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../../include/transport/protocol.proto
 
    )
 
    ADD_CUSTOM_TARGET(pb-python DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/protocol_pb2.py)
 
endif()
 
 
spectrum/src/main.cpp
Show inline comments
 
@@ -13,6 +13,7 @@
 
#include "transport/usersreconnecter.h"
 
#include "transport/util.h"
 
#include "transport/gatewayresponder.h"
 
#include "transport/logging.h"
 
#include "Swiften/EventLoop/SimpleEventLoop.h"
 
#include <boost/filesystem.hpp>
 
#include <boost/algorithm/string.hpp>
 
@@ -235,71 +236,7 @@ int main(int argc, char **argv)
 
    }
 
#endif
 

	
 
	if (CONFIG_STRING(&config, "logging.config").empty()) {
 
		LoggerPtr root = log4cxx::Logger::getRootLogger();
 
#ifdef WIN32
 
		root->addAppender(new ConsoleAppender(new PatternLayout(L"%d %-5p %c: %m%n")));
 
#else
 
		root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n")));
 
#endif
 
	}
 
	else {
 
		log4cxx::helpers::Properties p;
 
		log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(&config, "logging.config"));
 

	
 
		p.load(istream);
 
		LogString pid, jid;
 
		log4cxx::helpers::Transcoder::decode(boost::lexical_cast<std::string>(getpid()), pid);
 
		log4cxx::helpers::Transcoder::decode(CONFIG_STRING(&config, "service.jid"), jid);
 
#ifdef WIN32
 
		p.setProperty(L"pid", pid);
 
		p.setProperty(L"jid", jid);
 
#else
 
		p.setProperty("pid", pid);
 
		p.setProperty("jid", jid);
 
#endif
 

	
 
		std::string dir;
 
		BOOST_FOREACH(const log4cxx::LogString &prop, p.propertyNames()) {
 
			if (boost::ends_with(prop, ".File")) {
 
				log4cxx::helpers::Transcoder::encode(p.get(prop), dir);
 
				boost::replace_all(dir, "${jid}", jid);
 
				break;
 
			}
 
		}
 

	
 
		if (!dir.empty()) {
 
			// create directories
 
			try {
 
				boost::filesystem::create_directories(
 
					boost::filesystem::path(dir).parent_path().string()
 
				);
 
			}
 
			catch (...) {
 
				std::cerr << "Can't create logging directory directory " << boost::filesystem::path(dir).parent_path().string() << ".\n";
 
				return 1;
 
			}
 

	
 
#ifndef WIN32
 
			if (!CONFIG_STRING(&config, "service.group").empty() && !CONFIG_STRING(&config, "service.user").empty()) {
 
				struct group *gr;
 
				if ((gr = getgrnam(CONFIG_STRING(&config, "service.group").c_str())) == NULL) {
 
					std::cerr << "Invalid service.group name " << CONFIG_STRING(&config, "service.group") << "\n";
 
					return 1;
 
				}
 
				struct passwd *pw;
 
				if ((pw = getpwnam(CONFIG_STRING(&config, "service.user").c_str())) == NULL) {
 
					std::cerr << "Invalid service.user name " << CONFIG_STRING(&config, "service.user") << "\n";
 
					return 1;
 
				}
 
				chown(dir.c_str(), pw->pw_uid, gr->gr_gid);
 
			}
 

	
 
#endif
 
		}
 

	
 
		log4cxx::PropertyConfigurator::configure(p);
 
	}
 
	Logging::initMainLogging(&config);
 

	
 
#ifndef WIN32
 
	if (!CONFIG_STRING(&config, "service.group").empty() ||!CONFIG_STRING(&config, "service.user").empty() ) {
 
@@ -349,58 +286,18 @@ int main(int argc, char **argv)
 
	component_ = &transport;
 
// 	Logger logger(&transport);
 

	
 
	StorageBackend *storageBackend = NULL;
 

	
 
#ifdef WITH_SQLITE
 
	if (CONFIG_STRING(&config, "database.type") == "sqlite3") {
 
		storageBackend = new SQLite3Backend(&config);
 
		if (!storageBackend->connect()) {
 
			std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
 
			return -1;
 
		}
 
	}
 
#else
 
	if (CONFIG_STRING(&config, "database.type") == "sqlite3") {
 
		std::cerr << "Spectrum2 is not compiled with sqlite3 backend.\n";
 
	std::string error;
 
	StorageBackend *storageBackend = StorageBackend::createBackend(&config, error);
 
	if (storageBackend == NULL) {
 
		if (!error.empty()) {
 
			std::cerr << error << "\n";
 
			return -2;
 
		}
 
#endif
 

	
 
#ifdef WITH_MYSQL
 
	if (CONFIG_STRING(&config, "database.type") == "mysql") {
 
		storageBackend = new MySQLBackend(&config);
 
		if (!storageBackend->connect()) {
 
			std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
 
			return -1;
 
		}
 
	}
 
#else
 
	if (CONFIG_STRING(&config, "database.type") == "mysql") {
 
		std::cerr << "Spectrum2 is not compiled with mysql backend.\n";
 
		return -2;
 
	}
 
#endif
 

	
 
#ifdef WITH_PQXX
 
	if (CONFIG_STRING(&config, "database.type") == "pqxx") {
 
		storageBackend = new PQXXBackend(&config);
 
		if (!storageBackend->connect()) {
 
	else if (!storageBackend->connect()) {
 
		std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
 
		return -1;
 
	}
 
	}
 
#else
 
	if (CONFIG_STRING(&config, "database.type") == "pqxx") {
 
		std::cerr << "Spectrum2 is not compiled with pqxx backend.\n";
 
		return -2;
 
	}
 
#endif
 

	
 
	if (CONFIG_STRING(&config, "database.type") != "mysql" && CONFIG_STRING(&config, "database.type") != "sqlite3"
 
		&& CONFIG_STRING(&config, "database.type") != "pqxx" && CONFIG_STRING(&config, "database.type") != "none") {
 
		std::cerr << "Unknown storage backend " << CONFIG_STRING(&config, "database.type") << "\n";
 
		return -2;
 
	}
 

	
 
	UserManager userManager(&transport, &userRegistry, storageBackend);
 
	userManager_ = &userManager;
 
@@ -440,4 +337,5 @@ int main(int argc, char **argv)
 

	
 
	delete storageBackend;
 
	delete factories;
 
	return 0;
 
}
spectrum/src/sample.cfg
Show inline comments
 
@@ -7,27 +7,22 @@ server_mode = 1
 
backend_host=localhost
 
pidfile=./test.pid
 
# < this option doesn't work yet
 
backend_port=10001
 
admin_username=admin
 
#backend_port=10001
 
admin_jid=admin@localhost
 
admin_password=test
 
#cert=server.pfx #patch to PKCS#12 certificate
 
#cert_password=test #password to that certificate if any
 
users_per_backend=10
 
backend=/home/hanzz/code/libtransport/backends/libpurple/spectrum2_libpurple_backend
 
#backend=/home/hanzz/code/libtransport/backends/smstools3/spectrum2_smstools3_backend
 
#backend=/usr/bin/mono /home/hanzz/code/networkplugin-csharp/msnp-sharp-backend/bin/Debug/msnp-sharp-backend.exe
 
#backend=/home/hanzz/code/libtransport/backends/frotz/spectrum2_frotz_backend
 
#backend=/home/hanzz/code/libtransport/backends/libircclient-qt/spectrum2_libircclient-qt_backend
 
backend=../..//backends/libpurple/spectrum2_libpurple_backend
 
protocol=prpl-xmpp
 
#protocol=prpl-msn
 
protocol=any
 
#protocol=any
 
#protocol=prpl-icq
 
irc_server=irc.freenode.org
 
working_dir=./
 

	
 
[backend]
 
#default_avatar=catmelonhead.jpg
 
#no_vcard_fetch=true
 
incoming_dir=/var/spool/sms/incoming
 

	
 
[logging]
 
#config=logging.cfg # log4cxx/log4j logging configuration file
src/admininterface.cpp
Show inline comments
 
@@ -112,7 +112,7 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
 
		const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
 
		for (std::list <NetworkPluginServer::Backend *>::const_iterator b = backends.begin(); b != backends.end(); b++) {
 
			NetworkPluginServer::Backend *backend = *b;
 
			lst += "Backend " + boost::lexical_cast<std::string>(id);
 
			lst += "Backend " + boost::lexical_cast<std::string>(id) + " (ID=" + backend->id + ")";
 
			lst += backend->acceptUsers ? "" : " - not-accepting";
 
			lst += backend->longRun ? " - long-running" : "";
 
			lst += ":\n";
 
@@ -204,7 +204,7 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
 
		int id = 1;
 
		const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
 
		BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
 
			lst += "Backend " + boost::lexical_cast<std::string>(id) + ": " + boost::lexical_cast<std::string>(backend->res) + "\n";
 
			lst += "Backend " + boost::lexical_cast<std::string>(id) + " (ID=" + backend->id + "): " + boost::lexical_cast<std::string>(backend->res) + "\n";
 
			id++;
 
		}
 

	
 
@@ -215,7 +215,7 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
 
		int id = 1;
 
		const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
 
		BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
 
			lst += "Backend " + boost::lexical_cast<std::string>(id) + ": " + boost::lexical_cast<std::string>(backend->shared) + "\n";
 
			lst += "Backend " + boost::lexical_cast<std::string>(id)  + " (ID=" + backend->id + "): " + boost::lexical_cast<std::string>(backend->shared) + "\n";
 
			id++;
 
		}
 

	
 
@@ -226,7 +226,7 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
 
		int id = 1;
 
		const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
 
		BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
 
			lst += "Backend " + boost::lexical_cast<std::string>(id) + ": " + boost::lexical_cast<std::string>(backend->res - backend->shared) + "\n";
 
			lst += "Backend " + boost::lexical_cast<std::string>(id)  + " (ID=" + backend->id + "): " + boost::lexical_cast<std::string>(backend->res - backend->shared) + "\n";
 
			id++;
 
		}
 

	
 
@@ -238,10 +238,10 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
 
		const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
 
		BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
 
			if (backend->users.size() == 0) {
 
				lst += "Backend " + boost::lexical_cast<std::string>(id) + ": 0\n";
 
				lst += "Backend " + boost::lexical_cast<std::string>(id)  + " (ID=" + backend->id + "): 0\n";
 
			}
 
			else {
 
				lst += "Backend " + boost::lexical_cast<std::string>(id) + ": " + boost::lexical_cast<std::string>((backend->res - backend->init_res) / backend->users.size()) + "\n";
 
				lst += "Backend " + boost::lexical_cast<std::string>(id) + " (ID=" + backend->id + "): " + boost::lexical_cast<std::string>((backend->res - backend->init_res) / backend->users.size()) + "\n";
 
			}
 
			id++;
 
		}
 
@@ -251,6 +251,14 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
 
	else if (message->getBody() == "collect_backend") {
 
		m_server->collectBackend();
 
	}
 
	else if (message->getBody() == "crashed_backends") {
 
		std::string lst;
 
		const std::vector<std::string> &backends = m_server->getCrashedBackends();
 
		BOOST_FOREACH(const std::string &backend, backends) {
 
			lst += backend + "\n";
 
		}
 
		message->setBody(lst);
 
	}
 
	else if (message->getBody().find("help") == 0) {
 
		std::string help;
 
		help += "General:\n";
 
@@ -263,6 +271,7 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
 
		help += "    has_online_user <bare_JID> - returns 1 if user is online\n";
 
		help += "Backends:\n";
 
		help += "    backends_count - number of active backends\n";
 
		help += "    crashed_backends - returns IDs of crashed backends\n";
 
		help += "Memory:\n";
 
		help += "    res_memory - Total RESident memory spectrum2 and its backends use in KB\n";
 
		help += "    shr_memory - Total SHaRed memory spectrum2 backends share together in KB\n";
src/buddy.cpp
Show inline comments
 
@@ -26,7 +26,8 @@
 

	
 
namespace Transport {
 

	
 
Buddy::Buddy(RosterManager *rosterManager, long id) : m_id(id), m_flags(BUDDY_NO_FLAG), m_rosterManager(rosterManager){
 
Buddy::Buddy(RosterManager *rosterManager, long id) : m_id(id), m_flags(BUDDY_NO_FLAG), m_rosterManager(rosterManager),
 
	m_subscription(Ask) {
 
// 	m_rosterManager->setBuddy(this);
 
}
 

	
 
@@ -64,12 +65,12 @@ const Swift::JID &Buddy::getJID() {
 
	return m_jid;
 
}
 

	
 
void Buddy::setSubscription(const std::string &subscription) {
 
// 	m_subscription = subscription;
 
void Buddy::setSubscription(Subscription subscription) {
 
	m_subscription = subscription;
 
}
 

	
 
const std::string Buddy::getSubscription() {
 
	return "ask";
 
Buddy::Subscription Buddy::getSubscription() {
 
	return m_subscription;
 
}
 

	
 
Swift::Presence::ref Buddy::generatePresenceStanza(int features, bool only_new) {
src/logging.cpp
Show inline comments
 
new file 100644
 
/**
 
 * libtransport -- C++ library for easy XMPP Transports development
 
 *
 
 * Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
 
 *
 
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#include "transport/logging.h"
 
#include "transport/config.h"
 
#include <boost/foreach.hpp>
 
#include <iostream>
 
#include <iterator>
 
#include <algorithm>
 

	
 
#include "log4cxx/logger.h"
 
#include "log4cxx/consoleappender.h"
 
#include "log4cxx/patternlayout.h"
 
#include "log4cxx/propertyconfigurator.h"
 
#include "log4cxx/helpers/properties.h"
 
#include "log4cxx/helpers/fileinputstream.h"
 
#include "log4cxx/helpers/transcoder.h"
 
#include <boost/filesystem.hpp>
 
#include <boost/algorithm/string.hpp>
 

	
 
#ifndef WIN32
 
#include "sys/signal.h"
 
#include <pwd.h>
 
#include <grp.h>
 
#include <sys/resource.h>
 
#include "libgen.h"
 
#else
 
#include <windows.h>
 
#include <process.h>
 
#define getpid _getpid
 
#endif
 

	
 
using namespace boost::filesystem;
 
using namespace log4cxx;
 

	
 
namespace Transport {
 

	
 
namespace Logging {
 

	
 
static LoggerPtr root;
 

	
 
static void initLogging(Config *config, std::string key) {
 
	if (CONFIG_STRING(config, key).empty()) {
 
		root = log4cxx::Logger::getRootLogger();
 
#ifdef WIN32
 
		root->addAppender(new ConsoleAppender(new PatternLayout(L"%d %-5p %c: %m%n")));
 
#else
 
		root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n")));
 
#endif
 
	}
 
	else {
 
		log4cxx::helpers::Properties p;
 
		log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(config, key));
 

	
 
		p.load(istream);
 
		LogString pid, jid;
 
		log4cxx::helpers::Transcoder::decode(boost::lexical_cast<std::string>(getpid()), pid);
 
		log4cxx::helpers::Transcoder::decode(CONFIG_STRING(config, "service.jid"), jid);
 
#ifdef WIN32
 
		p.setProperty(L"pid", pid);
 
		p.setProperty(L"jid", jid);
 
#else
 
		p.setProperty("pid", pid);
 
		p.setProperty("jid", jid);
 
#endif
 

	
 
		std::string dir;
 
		BOOST_FOREACH(const log4cxx::LogString &prop, p.propertyNames()) {
 
			if (boost::ends_with(prop, ".File")) {
 
				log4cxx::helpers::Transcoder::encode(p.get(prop), dir);
 
				boost::replace_all(dir, "${jid}", jid);
 
				break;
 
			}
 
		}
 

	
 
		if (!dir.empty()) {
 
			// create directories
 
			try {
 
				boost::filesystem::create_directories(
 
					boost::filesystem::path(dir).parent_path().string()
 
				);
 
			}
 
			catch (...) {
 
				std::cerr << "Can't create logging directory directory " << boost::filesystem::path(dir).parent_path().string() << ".\n";
 
			}
 

	
 
#ifndef WIN32
 
			if (!CONFIG_STRING(config, "service.group").empty() && !CONFIG_STRING(config, "service.user").empty()) {
 
				struct group *gr;
 
				if ((gr = getgrnam(CONFIG_STRING(config, "service.group").c_str())) == NULL) {
 
					std::cerr << "Invalid service.group name " << CONFIG_STRING(config, "service.group") << "\n";
 
				}
 
				struct passwd *pw;
 
				if ((pw = getpwnam(CONFIG_STRING(config, "service.user").c_str())) == NULL) {
 
					std::cerr << "Invalid service.user name " << CONFIG_STRING(config, "service.user") << "\n";
 
				}
 
				chown(dir.c_str(), pw->pw_uid, gr->gr_gid);
 
			}
 

	
 
#endif
 
		}
 

	
 
		log4cxx::PropertyConfigurator::configure(p);
 
	}
 
}
 

	
 
void initBackendLogging(Config *config) {
 
	initLogging(config, "logging.backend_config");
 
}
 

	
 
void initMainLogging(Config *config) {
 
	initLogging(config, "logging.config");
 
}
 

	
 
}
 

	
 
}
src/memoryusage.cpp
Show inline comments
 
@@ -25,6 +25,7 @@
 
#include <sstream>
 
#include <fstream>
 
#include <algorithm>
 
#include <boost/lexical_cast.hpp>
 
#ifndef WIN32
 
#include <sys/param.h>
 
#endif
 
@@ -41,13 +42,18 @@ namespace Transport {
 

	
 
#ifndef WIN32
 
#ifdef BSD
 
void process_mem_usage(double& vm_usage, double& resident_set) {
 
void process_mem_usage(double& vm_usage, double& resident_set, pid_t pid) {
 
	int mib[4];
 
	size_t size;
 
	mib[0] = CTL_KERN;
 
	mib[1] = KERN_PROC;
 
	mib[2] = KERN_PROC_PID;
 
	if (pid == 0) {
 
		mib[3] = getpid();
 
	}
 
	else {
 
		mib[3] = pid;
 
	}
 
	struct kinfo_proc proc;
 

	
 
	size = sizeof(struct kinfo_proc);
 
@@ -75,7 +81,7 @@ void process_mem_usage(double& vm_usage, double& resident_set) {
 
	vm_usage = (double) proc.ki_size;
 
}
 
#else /* BSD */
 
void process_mem_usage(double& shared, double& resident_set) {
 
void process_mem_usage(double& shared, double& resident_set, pid_t pid) {
 
	using std::ios_base;
 
	using std::ifstream;
 
	using std::string;
 
@@ -84,8 +90,11 @@ void process_mem_usage(double& shared, double& resident_set) {
 
	resident_set = 0.0;
 

	
 
	// 'file' stat seems to give the most reliable results
 
	//
 
	ifstream stat_stream("/proc/self/statm",ios_base::in);
 
	std::string f = "/proc/self/statm";
 
	if (pid != 0) {
 
		f = "/proc/" + boost::lexical_cast<std::string>(pid) + "/statm";
 
	}
 
	ifstream stat_stream(f.c_str(), ios_base::in);
 
	if (!stat_stream.is_open()) {
 
		shared = 0;
 
		resident_set = 0;
 
@@ -94,7 +103,7 @@ void process_mem_usage(double& shared, double& resident_set) {
 

	
 
	// dummy vars for leading entries in stat that we don't care about
 
	//
 
	string pid, comm, state, ppid, pgrp, session, tty_nr;
 
	string pid1, comm, state, ppid, pgrp, session, tty_nr;
 
	string tpgid, flags, minflt, cminflt, majflt, cmajflt;
 
	string utime, stime, cutime, cstime, priority, nice;
 
	string O, itrealvalue, starttime;
src/networkpluginserver.cpp
Show inline comments
 
@@ -95,7 +95,12 @@ class NetworkFactory : public Factory {
 
			LocalBuddy *buddy = new LocalBuddy(rosterManager, buddyInfo.id);
 
			buddy->setAlias(buddyInfo.alias);
 
			buddy->setName(buddyInfo.legacyName);
 
			buddy->setSubscription(buddyInfo.subscription);
 
			if (buddyInfo.subscription == "both") {
 
				buddy->setSubscription(Buddy::Both);
 
			}
 
			else {
 
				buddy->setSubscription(Buddy::Ask);
 
			}
 
			buddy->setGroups(buddyInfo.groups);
 
			buddy->setFlags((BuddyFlag) (buddyInfo.flags));
 
			if (buddyInfo.settings.find("icon_hash") != buddyInfo.settings.end())
 
@@ -339,15 +344,19 @@ void NetworkPluginServer::handleNewClientConnection(boost::shared_ptr<Swift::Con
 
}
 

	
 
void NetworkPluginServer::handleSessionFinished(Backend *c) {
 
	LOG4CXX_INFO(logger, "Backend " << c << " disconnected. Current backend count=" << (m_clients.size() - 1));
 
	LOG4CXX_INFO(logger, "Backend " << c << " (ID=" << c->id << ") disconnected. Current backend count=" << (m_clients.size() - 1));
 

	
 
	// This backend will do, so we can't reconnect users to it in User::handleDisconnected call
 
	c->willDie = true;
 

	
 
	// If there are users associated with this backend, it must have crashed, so print error output
 
	// and disconnect users
 
	if (!c->users.empty()) {
 
		m_crashedBackends.push_back(c->id);
 
	}
 

	
 
	for (std::list<User *>::const_iterator it = c->users.begin(); it != c->users.end(); it++) {
 
		LOG4CXX_ERROR(logger, "Backend " << c << " disconnected (probably crashed) with active user " << (*it)->getJID().toString());
 
		LOG4CXX_ERROR(logger, "Backend " << c << " (ID=" << c->id << ") disconnected (probably crashed) with active user " << (*it)->getJID().toString());
 
		(*it)->setData(NULL);
 
		(*it)->handleDisconnected("Internal Server Error, please reconnect.");
 
	}
 
@@ -570,6 +579,7 @@ void NetworkPluginServer::handleConvMessagePayload(const std::string &data, bool
 

	
 
	// Forward it
 
	conv->handleMessage(msg, payload.nickname());
 
	m_userManager->messageToXMPPSent();
 
}
 

	
 
void NetworkPluginServer::handleAttentionPayload(const std::string &data) {
 
@@ -607,6 +617,7 @@ void NetworkPluginServer::handleStatsPayload(Backend *c, const std::string &data
 
	c->res = payload.res();
 
	c->init_res = payload.init_res();
 
	c->shared = payload.shared();
 
	c->id = payload.id();
 
}
 

	
 
void NetworkPluginServer::handleFTStartPayload(const std::string &data) {
 
@@ -853,12 +864,12 @@ void NetworkPluginServer::pingTimeout() {
 
			sendPing((*it));
 
		}
 
		else {
 
			LOG4CXX_INFO(logger, "Disconnecting backend " << (*it) << ". PING response not received.");
 
			LOG4CXX_INFO(logger, "Disconnecting backend " << (*it) << " (ID=" << (*it)->id << "). PING response not received.");
 
			toRemove.push_back(*it);
 
		}
 

	
 
		if ((*it)->users.size() == 0) {
 
			LOG4CXX_INFO(logger, "Disconnecting backend " << (*it) << ". There are no users.");
 
			LOG4CXX_INFO(logger, "Disconnecting backend " << (*it) << " (ID=" << (*it)->id << "). There are no users.");
 
			toRemove.push_back(*it);
 
		}
 
	}
 
@@ -887,7 +898,7 @@ void NetworkPluginServer::collectBackend() {
 
		if (m_collectTimer) {
 
			m_collectTimer->start();
 
		}
 
		LOG4CXX_INFO(logger, "Backend " << backend << "is set to die");
 
		LOG4CXX_INFO(logger, "Backend " << backend << " (ID=" << backend->id << ") is set to die");
 
		backend->acceptUsers = false;
 
	}
 
}
 
@@ -1355,7 +1366,7 @@ void NetworkPluginServer::sendPing(Backend *c) {
 
	wrap.SerializeToString(&message);
 

	
 
	if (c->connection) {
 
		LOG4CXX_INFO(logger, "PING to " << c);
 
		LOG4CXX_INFO(logger, "PING to " << c << " (ID=" << c->id << ")");
 
		send(c->connection, message);
 
		c->pongReceived = false;
 
	}
src/rostermanager.cpp
Show inline comments
 
@@ -137,6 +137,11 @@ void RosterManager::sendBuddyRosterPush(Buddy *buddy) {
 
		request->send();
 
		m_requests.push_back(request);
 
	}
 

	
 
	if (buddy->getSubscription() != Buddy::Both) {
 
		buddy->setSubscription(Buddy::Both);
 
		handleBuddyChanged(buddy);
 
	}
 
}
 

	
 
void RosterManager::sendBuddySubscribePresence(Buddy *buddy) {
 
@@ -165,6 +170,11 @@ void RosterManager::setBuddyCallback(Buddy *buddy) {
 
		sendBuddyRosterPush(buddy);
 
	}
 
	else {
 
		if (buddy->getSubscription() == Buddy::Both) {
 
			LOG4CXX_INFO(logger, m_user->getJID().toString() << ": Not forwarding this buddy, because subscription=both");
 
			return;
 
		}
 

	
 
		if (m_supportRemoteRoster) {
 
			sendBuddyRosterPush(buddy);
 
		}
 
@@ -331,8 +341,8 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) {
 
					response->setType(Swift::Presence::Subscribed);
 
					break;
 
				case Swift::Presence::Subscribed:
 
					onBuddyAdded(buddy);
 
					break;
 
// 					onBuddyAdded(buddy);
 
					return;
 
				// buddy is already there, so nothing to do, just answer
 
				case Swift::Presence::Unsubscribe:
 
					response->setType(Swift::Presence::Unsubscribed);
 
@@ -361,6 +371,10 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) {
 
						currentPresence->setTo(presence->getFrom());
 
						m_component->getStanzaChannel()->sendPresence(currentPresence);
 
					}
 
					if (buddy->getSubscription() != Buddy::Both) {
 
						buddy->setSubscription(Buddy::Both);
 
						handleBuddyChanged(buddy);
 
					}
 
					break;
 
				// remove buddy
 
				case Swift::Presence::Unsubscribe:
 
@@ -370,7 +384,20 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) {
 
				// just send response
 
				case Swift::Presence::Unsubscribed:
 
					response->setType(Swift::Presence::Unsubscribe);
 
					// We set both here, because this Unsubscribed can be response to
 
					// subscribe presence and we don't want that unsubscribe presence
 
					// to be send later again
 
					if (buddy->getSubscription() != Buddy::Both) {
 
						buddy->setSubscription(Buddy::Both);
 
						handleBuddyChanged(buddy);
 
					}
 
					break;
 
				case Swift::Presence::Subscribed:
 
					if (buddy->getSubscription() != Buddy::Both) {
 
						buddy->setSubscription(Buddy::Both);
 
						handleBuddyChanged(buddy);
 
					}
 
					return;
 
				default:
 
					return;
 
			}
 
@@ -394,7 +421,7 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) {
 
				// buddy is already there, so nothing to do, just answer
 
				case Swift::Presence::Unsubscribe:
 
					response->setType(Swift::Presence::Unsubscribed);
 
					onBuddyRemoved(buddy);
 
// 					onBuddyRemoved(buddy);
 
					break;
 
				// just send response
 
				case Swift::Presence::Unsubscribed:
src/rosterstorage.cpp
Show inline comments
 
@@ -103,7 +103,7 @@ bool RosterStorage::storeBuddies() {
 
		buddyInfo.alias = buddy->getAlias();
 
		buddyInfo.legacyName = buddy->getName();
 
		buddyInfo.groups = buddy->getGroups();
 
		buddyInfo.subscription = buddy->getSubscription();
 
		buddyInfo.subscription = buddy->getSubscription() == Buddy::Ask ? "ask" : "both";
 
		buddyInfo.id = buddy->getID();
 
		buddyInfo.flags = buddy->getFlags();
 
		buddyInfo.settings["icon_hash"].s = buddy->getIconHash();
src/statsresponder.cpp
Show inline comments
 
@@ -81,7 +81,10 @@ bool StatsResponder::handleGetRequest(const Swift::JID& from, const Swift::JID&
 
		response->addItem(StatsPayload::Item("users/online"));
 
		response->addItem(StatsPayload::Item("contacts/online"));
 
		response->addItem(StatsPayload::Item("contacts/total"));
 
		response->addItem(StatsPayload::Item("backends"));
 
		response->addItem(StatsPayload::Item("messages/from-xmpp"));
 
		response->addItem(StatsPayload::Item("messages/to-xmpp"));
 
		response->addItem(StatsPayload::Item("backends/running"));
 
		response->addItem(StatsPayload::Item("backends/crashed"));
 
		response->addItem(StatsPayload::Item("memory-usage"));
 
	}
 
	else {
 
@@ -115,8 +118,11 @@ bool StatsResponder::handleGetRequest(const Swift::JID& from, const Swift::JID&
 
			else if (item.getName() == "users/online") {
 
				response->addItem(StatsPayload::Item("users/online", "users", boost::lexical_cast<std::string>(m_userManager->getUserCount())));
 
			}
 
			else if (item.getName() == "backends") {
 
				response->addItem(StatsPayload::Item("backends", "backends", boost::lexical_cast<std::string>(m_server->getBackendCount())));
 
			else if (item.getName() == "backends/running") {
 
				response->addItem(StatsPayload::Item("backends/running", "backends", boost::lexical_cast<std::string>(m_server->getBackendCount())));
 
			}
 
			else if (item.getName() == "backends/crashed") {
 
				response->addItem(StatsPayload::Item("backends/crashed", "backends", boost::lexical_cast<std::string>(m_server->getCrashedBackends().size())));
 
			}
 
			else if (item.getName() == "memory-usage") {
 
				response->addItem(StatsPayload::Item("memory-usage", "KB", boost::lexical_cast<std::string>(usedMemory())));
 
@@ -127,6 +133,12 @@ bool StatsResponder::handleGetRequest(const Swift::JID& from, const Swift::JID&
 
			else if (item.getName() == "contacts/total") {
 
				response->addItem(StatsPayload::Item("contacts/total", "contacts", boost::lexical_cast<std::string>(contactsTotal)));
 
			}
 
			else if (item.getName() == "messages/from-xmpp") {
 
				response->addItem(StatsPayload::Item("messages/from-xmpp", "messages", boost::lexical_cast<std::string>(m_userManager->getMessagesToBackend())));
 
			}
 
			else if (item.getName() == "messages/to-xmpp") {
 
				response->addItem(StatsPayload::Item("messages/to-xmpp", "messages", boost::lexical_cast<std::string>(m_userManager->getMessagesToXMPP())));
 
			}
 
		}
 
	}
 

	
src/storagebackend.cpp
Show inline comments
 
new file 100644
 
#include "transport/storagebackend.h"
 
#include "transport/config.h"
 

	
 
#include "transport/sqlite3backend.h"
 
#include "transport/mysqlbackend.h"
 
#include "transport/pqxxbackend.h"
 

	
 
namespace Transport {
 

	
 
StorageBackend *StorageBackend::createBackend(Config *config, std::string &error) {
 
	StorageBackend *storageBackend = NULL;
 
#ifdef WITH_SQLITE
 
	if (CONFIG_STRING(config, "database.type") == "sqlite3") {
 
		storageBackend = new SQLite3Backend(config);
 
	}
 
#else
 
	if (CONFIG_STRING(config, "database.type") == "sqlite3") {
 
		error = "Libtransport is not compiled with sqlite3 backend support.";
 
	}
 
#endif
 

	
 
#ifdef WITH_MYSQL
 
	if (CONFIG_STRING(config, "database.type") == "mysql") {
 
		storageBackend = new MySQLBackend(config);
 
	}
 
#else
 
	if (CONFIG_STRING(config, "database.type") == "mysql") {
 
		error = "Spectrum2 is not compiled with mysql backend support.";
 
	}
 
#endif
 

	
 
#ifdef WITH_PQXX
 
	if (CONFIG_STRING(config, "database.type") == "pqxx") {
 
		storageBackend = new PQXXBackend(config);
 
	}
 
#else
 
	if (CONFIG_STRING(config, "database.type") == "pqxx") {
 
		error = "Spectrum2 is not compiled with pqxx backend support.";
 
	}
 
#endif
 

	
 
	if (CONFIG_STRING(config, "database.type") != "mysql" && CONFIG_STRING(config, "database.type") != "sqlite3"
 
		&& CONFIG_STRING(config, "database.type") != "pqxx" && CONFIG_STRING(config, "database.type") != "none") {
 
		error = "Unknown storage backend " + CONFIG_STRING(config, "database.type");
 
	}
 
	return storageBackend;
 
}
 

	
 
}
src/tests/basictest.h
Show inline comments
 
@@ -72,7 +72,7 @@ class TestingFactory : public Factory {
 
			LocalBuddy *buddy = new LocalBuddy(rosterManager, buddyInfo.id);
 
			buddy->setAlias(buddyInfo.alias);
 
			buddy->setName(buddyInfo.legacyName);
 
			buddy->setSubscription(buddyInfo.subscription);
 
			buddy->setSubscription(Buddy::Ask);
 
			buddy->setGroups(buddyInfo.groups);
 
			buddy->setFlags((BuddyFlag) buddyInfo.flags);
 
			if (buddyInfo.settings.find("icon_hash") != buddyInfo.settings.end())
src/user.cpp
Show inline comments
 
@@ -210,6 +210,7 @@ void User::handlePresence(Swift::Presence::ref presence) {
 
			}
 
		}
 
	}
 

	
 
	bool isMUC = presence->getPayload<Swift::MUCPayload>() != NULL || *presence->getTo().getNode().c_str() == '#';
 
	if (isMUC) {
 
		if (presence->getType() == Swift::Presence::Unavailable) {
 
@@ -328,7 +329,7 @@ void User::handleDisconnected(const std::string &error, Swift::SpectrumErrorPayl
 
	if (e == Swift::SpectrumErrorPayload::CONNECTION_ERROR_OTHER_ERROR || e == Swift::SpectrumErrorPayload::CONNECTION_ERROR_NETWORK_ERROR) {
 
		if (m_reconnectCounter < 3) {
 
			m_reconnectCounter++;
 
			LOG4CXX_INFO(logger, m_jid.toString() << ": Disconnecting from legacy network for, trying to reconnect automatically.");
 
			LOG4CXX_INFO(logger, m_jid.toString() << ": Disconnecting from legacy network " << error << ", trying to reconnect automatically.");
 
			// Simulate destruction/resurrection :)
 
			// TODO: If this stops working, create onReconnect signal
 
			m_userManager->onUserDestroyed(this);
src/usermanager.cpp
Show inline comments
 
@@ -42,6 +42,8 @@ static LoggerPtr logger = Logger::getLogger("UserManager");
 
UserManager::UserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend) {
 
	m_cachedUser = NULL;
 
	m_onlineBuddies = 0;
 
	m_sentToXMPP = 0;
 
	m_sentToBackend = 0;
 
	m_component = component;
 
	m_storageBackend = storageBackend;
 
	m_storageResponder = NULL;
 
@@ -150,6 +152,21 @@ void UserManager::handlePresence(Swift::Presence::ref presence) {
 
	if (!user) {
 
		// Admin user is not legacy network user, so do not create User class instance for him
 
		if (m_component->inServerMode() && CONFIG_STRING(m_component->getConfig(), "service.admin_jid") == presence->getFrom().toBare().toString()) {
 
			// Send admin contact to the user.
 
			Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload());
 
			Swift::RosterItemPayload item;
 
			item.setJID(m_component->getJID());
 
			item.setName("Admin");
 
			item.setSubscription(Swift::RosterItemPayload::Both);
 
			payload->addItem(item);
 

	
 
			Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, presence->getFrom(), m_component->getIQRouter());
 
			request->send();
 

	
 
			Swift::Presence::ref response = Swift::Presence::create();
 
			response->setTo(presence->getFrom());
 
			response->setFrom(m_component->getJID());
 
			m_component->getStanzaChannel()->sendPresence(response);
 
			return;
 
		}
 

	
 
@@ -266,6 +283,7 @@ void UserManager::handleMessageReceived(Swift::Message::ref message) {
 
	}
 

	
 
	user->getConversationManager()->handleMessageReceived(message);
 
	messageToBackendSent();
 
}
 

	
 
void UserManager::handleGeneralPresenceReceived(Swift::Presence::ref presence) {
src/userregistration.cpp
Show inline comments
 
@@ -453,7 +453,7 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID
 
// #endif
 
	if (!registered) {
 
		res.jid = barejid;
 
		res.uin = username;
 
		res.uin = newUsername;
 
		res.password = *payload->getPassword();
 
		res.language = language;
 
		res.encoding = encoding;
 
@@ -462,7 +462,7 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID
 
	}
 
	else {
 
		res.jid = barejid;
 
		res.uin = username;
 
		res.uin = newUsername;
 
		res.password = *payload->getPassword();
 
		res.language = language;
 
		res.encoding = encoding;
0 comments (0 inline, 0 general)