Changeset - 0a78acefef91
[Not reviewed]
backends/libpurple/main.cpp
Show inline comments
 
#include "utils.h"
 

	
 
#include "glib.h"
 

	
 
// win32/libc_interface.h defines its own socket(), read() and so on.
 
// We don't want to use it here.
 
#define _LIBC_INTERFACE_H_ 1
 

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

	
 
#include "transport/NetworkPlugin.h"
 
#include "transport/Logging.h"
 
#include "transport/Config.h"
 
#include "transport/StorageBackend.h"
 
#include "geventloop.h"
 
#include "Swiften/SwiftenCompat.h"
 

	
 
// #include "valgrind/memcheck.h"
 
#if !defined(__FreeBSD__) && !defined(__APPLE__)
 
#include "malloc.h"
 
#endif
 
#include "errno.h"
 
#include <boost/make_shared.hpp>
 
#include <boost/locale.hpp>
 
#include <boost/locale/conversion.hpp>
 
#include <boost/thread/mutex.hpp>
 

	
 
#ifdef WITH_LIBEVENT
 
#include <event.h>
 
#endif
 

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

	
 
#include "purple_defs.h"
 

	
 
DEFINE_LOGGER(logger_libpurple, "libpurple");
 
DEFINE_LOGGER(logger, "backend");
 

	
 
/* Additional PURPLE_MESSAGE_* flags as a hack to track the origin of the message. */
 
typedef enum {
 
    PURPLE_MESSAGE_SPECTRUM2_ORIGINATED = 0x80000000,
 
} PurpleMessageSpectrum2Flags;
 

	
 
int main_socket;
 
static int writeInput;
 
bool firstPing = true;
 

	
 
using namespace Transport;
 

	
 
template <class T> T fromString(const std::string &str) {
 
	T i;
 
	std::istringstream os(str);
 
	os >> i;
 
	return i;
 
}
 

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

	
 
static std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
 
    std::stringstream ss(s);
 
    std::string item;
 
    while(std::getline(ss, item, delim)) {
 
        elems.push_back(item);
 
    }
 
    return elems;
 
}
 

	
 

	
 
static std::vector<std::string> split(const std::string &s, char delim) {
 
    std::vector<std::string> elems;
 
    return split(s, delim, elems);
 
}
 

	
 
static void transportDataReceived(gpointer data, gint source, PurpleInputCondition cond);
 

	
 
class SpectrumNetworkPlugin;
 

	
 
SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Config> config;
 
SpectrumNetworkPlugin *np;
 
StorageBackend *storagebackend;
 

	
 
static std::string host;
 
static int port = 10000;
 

	
 
struct FTData {
 
	unsigned long id;
 
	unsigned long timer;
 
@@ -497,109 +502,109 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 
						st = PURPLE_STATUS_INVISIBLE;
 
						break;
 
					default:
 
						st = PURPLE_STATUS_AVAILABLE;
 
						break;
 
				}
 
				gchar *_markup = purple_markup_escape_text_wrapped(statusMessage.c_str(), -1);
 
				std::string markup(_markup);
 
				g_free(_markup);
 

	
 
				// we are already connected so we have to change status
 
				const PurpleStatusType *status_type = purple_account_get_status_type_with_primitive_wrapped(account, (PurpleStatusPrimitive) st);
 
				if (status_type != NULL) {
 
					// send presence to legacy network
 
					if (!markup.empty()) {
 
						purple_account_set_status_wrapped(account, purple_status_type_get_id_wrapped(status_type), TRUE, "message", markup.c_str(), NULL);
 
					}
 
					else {
 
						purple_account_set_status_wrapped(account, purple_status_type_get_id_wrapped(status_type), TRUE, NULL);
 
					}
 
				}
 
			}
 
		}
 

	
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml, const std::string &id) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				LOG4CXX_INFO(logger, "Sending message to '" << legacyName << "'");
 
				PurpleConversation *conv = purple_find_conversation_with_account_wrapped(PURPLE_CONV_TYPE_CHAT, LegacyNameToName(account, legacyName).c_str(), account);
 
				if (legacyName == adminLegacyName) {
 
					// expect OAuth code
 
					if (m_inputRequests.find(user) != m_inputRequests.end()) {
 
						LOG4CXX_INFO(logger, "Updating token for '" << user << "'");
 
						m_inputRequests[user]->ok_cb(m_inputRequests[user]->user_data, message.c_str());
 
						m_inputRequests.erase(user);
 
					}
 
					return;
 
				}
 

	
 
				if (!conv) {
 
					conv = purple_find_conversation_with_account_wrapped(PURPLE_CONV_TYPE_IM, LegacyNameToName(account, legacyName).c_str(), account);
 
					if (!conv) {
 
						conv = purple_conversation_new_wrapped(PURPLE_CONV_TYPE_IM, account, LegacyNameToName(account, legacyName).c_str());
 
					}
 
				}
 
				if (xhtml.empty()) {
 
					gchar *_markup = purple_markup_escape_text_wrapped(message.c_str(), -1);
 
					if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_IM) {
 
						purple_conv_im_send_wrapped(PURPLE_CONV_IM_WRAPPED(conv), _markup);
 
						purple_conv_im_send_with_flags_wrapped(PURPLE_CONV_IM_WRAPPED(conv), _markup, static_cast<PurpleMessageFlags>(PURPLE_MESSAGE_SPECTRUM2_ORIGINATED));
 
					}
 
					else if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_CHAT) {
 
						purple_conv_chat_send_wrapped(PURPLE_CONV_CHAT_WRAPPED(conv), _markup);
 
						purple_conv_chat_send_with_flags_wrapped(PURPLE_CONV_CHAT_WRAPPED(conv), _markup, static_cast<PurpleMessageFlags>(PURPLE_MESSAGE_SPECTRUM2_ORIGINATED));
 
					}
 
					g_free(_markup);
 
				}
 
				else {
 
					if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_IM) {
 
						purple_conv_im_send_wrapped(PURPLE_CONV_IM_WRAPPED(conv), xhtml.c_str());
 
						purple_conv_im_send_with_flags_wrapped(PURPLE_CONV_IM_WRAPPED(conv), xhtml.c_str(), static_cast<PurpleMessageFlags>(PURPLE_MESSAGE_SPECTRUM2_ORIGINATED));
 
					}
 
					else if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_CHAT) {
 
						purple_conv_chat_send_wrapped(PURPLE_CONV_CHAT_WRAPPED(conv), xhtml.c_str());
 
						purple_conv_chat_send_with_flags_wrapped(PURPLE_CONV_CHAT_WRAPPED(conv), xhtml.c_str(), static_cast<PurpleMessageFlags>(PURPLE_MESSAGE_SPECTRUM2_ORIGINATED));
 
					}
 
				}
 
			}
 
		}
 

	
 
		void handleRoomSubjectChangedRequest(const std::string &user, const std::string &legacyName, const std::string &message) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				PurpleConversation *conv = purple_find_conversation_with_account_wrapped(PURPLE_CONV_TYPE_CHAT, LegacyNameToName(account, legacyName).c_str(), account);
 
				if (!conv) {
 
					LOG4CXX_ERROR(logger, user << ": Cannot set room subject. There is now conversation " << legacyName);
 
					return;
 
				}
 

	
 
				PurplePlugin *prpl = purple_find_prpl_wrapped(purple_account_get_protocol_id_wrapped(account));
 
				PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
				bool support_set_chat_topic = prpl_info && prpl_info->set_chat_topic;
 
				if (support_set_chat_topic) {
 
					LOG4CXX_INFO(logger, user << ": Setting room subject for room " << legacyName);
 
					prpl_info->set_chat_topic(purple_account_get_connection_wrapped(account),
 
											  purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)),
 
											  message.c_str());
 
				}
 
			}
 
		}
 

	
 
		void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				std::string name = legacyName;
 
				if (CONFIG_STRING(config, "service.protocol") == "any" && legacyName.find("prpl-") == 0) {
 
					name = name.substr(name.find(".") + 1);
 
				}
 
				m_vcards[user + name] = id;
 

	
 
				PurplePlugin *prpl = purple_find_prpl_wrapped(purple_account_get_protocol_id_wrapped(account));
 
				PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
				bool support_get_info = prpl_info && prpl_info->get_info;
 

	
 
				if (!support_get_info || (CONFIG_BOOL(config, "backend.no_vcard_fetch") && name != purple_account_get_username_wrapped(account))) {
 
					PurpleNotifyUserInfo *user_info = purple_notify_user_info_new_wrapped();
 
					notify_user_info(purple_account_get_connection_wrapped(account), name.c_str(), user_info);
 
					purple_notify_user_info_destroy_wrapped(user_info);
 
				}
 
				else {
 
					serv_get_info_wrapped(purple_account_get_connection_wrapped(account), name.c_str());
 
				}
 
			}
 
@@ -1093,185 +1098,210 @@ static void buddyListUpdate(PurpleBuddyList *list, PurpleBlistNode *node) {
 
	if (!PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED(node))
 
		return;
 
	buddyListNewNode(node);
 
}
 

	
 
static void buddyPrivacyChanged(PurpleBlistNode *node, void *data) {
 
	if (!PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED(node))
 
		return;
 
	buddyListUpdate(NULL, node);
 
}
 

	
 
static void NodeRemoved(PurpleBlistNode *node, void *data) {
 
	if (!PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED(node))
 
		return;
 
// 	PurpleBuddy *buddy = (PurpleBuddy *) node;
 
}
 

	
 
static void buddyListSaveNode(PurpleBlistNode *node) {
 
	if (!PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED(node))
 
		return;
 
}
 

	
 
static void buddyListSaveAccount(PurpleAccount *account) {
 
}
 

	
 
static void buddyListRemoveNode(PurpleBlistNode *node) {
 
	if (!PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED(node))
 
		return;
 
}
 

	
 
static PurpleBlistUiOps blistUiOps =
 
{
 
	NULL,
 
	buddyListNewNode,
 
	NULL,
 
	buddyListUpdate,
 
	buddyNodeRemoved,
 
	NULL,
 
	NULL,
 
	NULL, // buddyListAddBuddy,
 
	NULL,
 
	NULL,
 
	buddyListSaveNode,
 
	buddyListRemoveNode,
 
	buddyListSaveAccount,
 
	NULL
 
};
 

	
 
static void conv_write_im(PurpleConversation *conv, const char *who, const char *msg, PurpleMessageFlags flags, time_t mtime);
 

	
 
static void conv_write(PurpleConversation *conv, const char *who, const char *alias, const char *msg, PurpleMessageFlags flags, time_t mtime) {
 
	LOG4CXX_INFO(logger, "conv_write()");
 

	
 
	if (flags & PURPLE_MESSAGE_SYSTEM && CONFIG_STRING(config, "service.protocol") == "prpl-telegram") {
 
		PurpleAccount *account = purple_conversation_get_account_wrapped(conv);
 

	
 
	// 	char *striped = purple_markup_strip_html_wrapped(message);
 
	// 	std::string msg = striped;
 
	// 	g_free(striped);
 

	
 

	
 
		// Escape HTML characters.
 
		char *newline = purple_strdup_withhtml_wrapped(msg);
 
		char *strip, *xhtml;
 
		purple_markup_html_to_xhtml_wrapped(newline, &xhtml, &strip);
 
	// 	xhtml_linkified = spectrum_markup_linkify(xhtml);
 
		std::string message_(strip);
 

	
 
		std::string xhtml_(xhtml);
 
		g_free(newline);
 
		g_free(xhtml);
 
	// 	g_free(xhtml_linkified);
 
		g_free(strip);
 

	
 
		// AIM and XMPP adds <body>...</body> here...
 
		if (xhtml_.find("<body>") == 0) {
 
			xhtml_ = xhtml_.substr(6);
 
			if (xhtml_.find("</body>") != std::string::npos) {
 
				xhtml_ = xhtml_.substr(0, xhtml_.find("</body>"));
 
			}
 
		}
 

	
 
		if (xhtml_ == message_) {
 
			xhtml_ = "";
 
		}
 

	
 
		std::string timestamp;
 
		if (mtime && (unsigned long) time(NULL)-10 > (unsigned long) mtime/* && (unsigned long) time(NULL) - 31536000 < (unsigned long) mtime*/) {
 
			char buf[80];
 
			strftime(buf, sizeof(buf), "%Y%m%dT%H%M%S", gmtime(&mtime));
 
			timestamp = buf;
 
		}
 

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

	
 
		if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_IM) {
 
			std::string w = purple_normalize_wrapped(account, who);
 
			size_t pos = w.find("/");
 
			if (pos != std::string::npos)
 
				w.erase((int) pos, w.length() - (int) pos);
 
			np->handleMessage(np->m_accounts[account], w, message_, "", xhtml_, timestamp);
 
		}
 
		else {
 
			std::string conversationName = purple_conversation_get_name_wrapped(conv);
 
			LOG4CXX_INFO(logger, "Received message body='" << message_ << "' name='" << conversationName << "' " << who);
 
			np->handleMessage(np->m_accounts[account], np->NameToLegacyName(account, conversationName), message_, who, xhtml_, timestamp);
 
		}
 
	}
 
	else {
 
	    //Handle all non-special cases by just passing them to conv_write_im
 
	    conv_write_im(conv, who, msg, flags, mtime);
 
	}
 
}
 

	
 
static char *calculate_data_hash(guchar *data, size_t len,
 
    const gchar *hash_algo)
 
{
 
	PurpleCipherContext *context;
 
	static gchar digest[129]; /* 512 bits hex + \0 */
 

	
 
	context = purple_cipher_context_new_by_name(hash_algo, NULL);
 
	if (context == NULL)
 
	{
 
		purple_debug_error("jabber", "Could not find %s cipher\n", hash_algo);
 
		g_return_val_if_reached(NULL);
 
	}
 

	
 
	/* Hash the data */
 
	purple_cipher_context_append(context, data, len);
 
	if (!purple_cipher_context_digest_to_str(context, sizeof(digest), digest, NULL))
 
	{
 
		purple_debug_error("jabber", "Failed to get digest for %s cipher.\n",
 
		    hash_algo);
 
		g_return_val_if_reached(NULL);
 
	}
 
	purple_cipher_context_destroy(context);
 

	
 
	return g_strdup(digest);
 
}
 

	
 
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 (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_IM && (flags & PURPLE_MESSAGE_SEND || flags & PURPLE_MESSAGE_SYSTEM)) {
 
	LOG4CXX_INFO(logger, "conv_write_im()");
 
	bool isCarbon = false;
 
	
 
	if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_IM) {
 
		//Don't forwards our own messages, but do forward messages "from=us" which originated elsewhere
 
		//(such as carbons of our messages from other legacy network clients)
 
		if (flags & PURPLE_MESSAGE_SPECTRUM2_ORIGINATED) {
 
			LOG4CXX_INFO(logger, "conv_write_im(): ignoring a message generated by us");
 
			return;
 
		}
 
		
 
		//If this is a carbon of a message from us, mark it as such
 
		if(flags & PURPLE_MESSAGE_SEND)
 
			isCarbon = true;
 
		
 
		//Originally the transport had this filter too, I'm leaving it in for now:
 
		if (flags & PURPLE_MESSAGE_SYSTEM) {
 
			LOG4CXX_INFO(logger, "conv_write_im(): ignoring a system message");
 
			return;
 
		}
 
	}
 
	PurpleAccount *account = purple_conversation_get_account_wrapped(conv);
 

	
 
	std::string message_;
 
	std::string xhtml_;
 

	
 
	if (flags & PURPLE_MESSAGE_IMAGES && !CONFIG_STRING(config, "service.web_directory").empty() && !CONFIG_STRING(config, "service.web_url").empty() ) {
 
		LOG4CXX_INFO(logger, "Received image body='" << msg << "'");
 
		std::string body = msg;
 
		std::string plain = msg;
 
		size_t i;
 
		while ((i = body.find("<img id=\"")) != std::string::npos) {
 
			int from = i + strlen("<img id=\"");
 
			int to = body.find("\"", from + 1);
 
			std::string id = body.substr(from, to - from);
 
			LOG4CXX_INFO(logger, "Image ID = '" << id << "' " << from << " " << to);
 

	
 
			PurpleStoredImage *image = purple_imgstore_find_by_id(atoi(id.c_str()));
 
			if (!image) {
 
				LOG4CXX_ERROR(logger, "Cannot find image with id " << id << ".");
 
				return;
 
			}
 

	
 
			std::string ext = "icon";
 
			std::string name;
 
			guchar * data = (guchar *) purple_imgstore_get_data_wrapped(image);
 
			size_t len = purple_imgstore_get_size_wrapped(image);
 
			if (len < 1000000 && data) {
 
				ext = purple_imgstore_get_extension(image);
 
				char *hash = calculate_data_hash(data, len, "sha1");
 
				if (!hash) {
 
					LOG4CXX_WARN(logger, "Cannot compute hash for the image.");
 
					return;
 
				}
 
				name = hash;
 
				g_free(hash);
 

	
 
				std::ofstream output;
 
				LOG4CXX_INFO(logger, "Storing image to " << std::string(CONFIG_STRING(config, "service.web_directory") + "/" + name + "." + ext));
 
				output.open(std::string(CONFIG_STRING(config, "service.web_directory") + "/" + name + "." + ext).c_str(), std::ios::out | std::ios::binary);
 
				if (output.fail()) {
 
					LOG4CXX_ERROR(logger, "Open file failure: " << strerror(errno));
 
					return;
 
				}
 
				output.write((char *)data, len);
 
				output.close();
 
			}
 
			else {
 
				LOG4CXX_WARN(logger, "Image bigger than 1MB.");
 
@@ -1291,102 +1321,102 @@ static void conv_write_im(PurpleConversation *conv, const char *who, const char
 
		message_ = strip;
 
		if (message_.empty()) {
 
			message_ = plain;
 
		}
 
		xhtml_ = xhtml;
 
		g_free(xhtml);
 
		g_free(strip);
 
	}
 
	else {
 
		// Escape HTML characters.
 
		char *newline = purple_strdup_withhtml_wrapped(msg);
 
		char *strip, *xhtml;
 
		purple_markup_html_to_xhtml_wrapped(newline, &xhtml, &strip);
 
		message_ = strip;
 
		xhtml_ = xhtml;
 
		g_free(newline);
 
		g_free(xhtml);
 
		g_free(strip);
 
	}
 

	
 
	// AIM and XMPP adds <body>...</body> here...
 
	if (xhtml_.find("<body>") == 0) {
 
		xhtml_ = xhtml_.substr(6);
 
		if (xhtml_.find("</body>") != std::string::npos) {
 
			xhtml_ = xhtml_.substr(0, xhtml_.find("</body>"));
 
		}
 
	}
 

	
 
	if (xhtml_ == message_) {
 
		xhtml_ = "";
 
	}
 

	
 
	std::string timestamp;
 
	if (mtime && (unsigned long) time(NULL)-10 > (unsigned long) mtime/* && (unsigned long) time(NULL) - 31536000 < (unsigned long) mtime*/) {
 
		char buf[80];
 
		strftime(buf, sizeof(buf), "%Y%m%dT%H%M%S", gmtime(&mtime));
 
		timestamp = buf;
 
	}
 

	
 
	if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_IM) {
 
		std::string w = purple_normalize_wrapped(account, who);
 
		std::string n;
 
		size_t pos = w.find("/");
 
		if (pos != std::string::npos) {
 
			n = w.substr((int) pos + 1, w.length() - (int) pos);
 
			w.erase((int) pos, w.length() - (int) pos);
 
		}
 
		LOG4CXX_INFO(logger, "Received message body='" << message_ << "' xhtml='" << xhtml_ << "' name='" << w << "'");
 
		np->handleMessage(np->m_accounts[account], w, message_, n, xhtml_, timestamp);
 
		np->handleMessage(np->m_accounts[account], w, message_, n, xhtml_, timestamp, false, false, isCarbon);
 
	}
 
	else {
 
		std::string conversationName = purple_conversation_get_name_wrapped(conv);
 
		LOG4CXX_INFO(logger, "Received message body='" << message_ << "' xhtml='" << xhtml_ << "' name='" << conversationName << "' " << who);
 
		np->handleMessage(np->m_accounts[account], np->NameToLegacyName(account, conversationName), message_, who, xhtml_, timestamp);
 
		np->handleMessage(np->m_accounts[account], np->NameToLegacyName(account, conversationName), message_, who, xhtml_, timestamp, false, false, isCarbon);
 
	}
 
}
 

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

	
 
	GList *l = cbuddies;
 
	while (l != NULL) {
 
		PurpleConvChatBuddy *cb = (PurpleConvChatBuddy *)l->data;
 
		std::string name(cb->name);
 
		std::string alias = cb->alias ? cb->alias : 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");
 
		}
 
		std::string conversationName = purple_conversation_get_name_wrapped(conv);
 
		np->handleParticipantChanged(np->m_accounts[account], name, np->NameToLegacyName(account, conversationName), (int) flags, pbnetwork::STATUS_ONLINE, "", "", alias);
 

	
 
		l = l->next;
 
	}
 
}
 

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

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

	
 
		l = l->next;
 
	}
 
}
 

	
 
static gboolean conv_has_focus(PurpleConversation *conv) {
backends/libpurple/purple_defs.cpp
Show inline comments
 
@@ -29,97 +29,99 @@ purple_account_add_buddy_wrapped_fnc purple_account_add_buddy_wrapped = NULL;
 
purple_account_get_name_for_display_wrapped_fnc purple_account_get_name_for_display_wrapped = NULL;
 
purple_accounts_set_ui_ops_wrapped_fnc purple_accounts_set_ui_ops_wrapped = NULL;
 
purple_account_option_get_type_wrapped_fnc purple_account_option_get_type_wrapped = NULL;
 
purple_account_option_get_setting_wrapped_fnc purple_account_option_get_setting_wrapped = NULL;
 
purple_blist_node_get_type_wrapped_fnc purple_blist_node_get_type_wrapped = NULL;
 
purple_buddy_get_alias_wrapped_fnc purple_buddy_get_alias_wrapped = NULL;
 
purple_buddy_get_server_alias_wrapped_fnc purple_buddy_get_server_alias_wrapped = NULL;
 
purple_find_buddy_wrapped_fnc purple_find_buddy_wrapped = NULL;
 
purple_buddy_get_group_wrapped_fnc purple_buddy_get_group_wrapped = NULL;
 
purple_blist_remove_buddy_wrapped_fnc purple_blist_remove_buddy_wrapped = NULL;
 
purple_blist_alias_buddy_wrapped_fnc purple_blist_alias_buddy_wrapped = NULL;
 
purple_blist_server_alias_buddy_wrapped_fnc purple_blist_server_alias_buddy_wrapped = NULL;
 
purple_find_group_wrapped_fnc purple_find_group_wrapped = NULL;
 
purple_group_new_wrapped_fnc purple_group_new_wrapped = NULL;
 
purple_blist_add_contact_wrapped_fnc purple_blist_add_contact_wrapped = NULL;
 
purple_buddy_get_contact_wrapped_fnc purple_buddy_get_contact_wrapped = NULL;
 
purple_buddy_new_wrapped_fnc purple_buddy_new_wrapped = NULL;
 
purple_blist_add_buddy_wrapped_fnc purple_blist_add_buddy_wrapped = NULL;
 
purple_blist_find_chat_wrapped_fnc purple_blist_find_chat_wrapped = NULL;
 
purple_chat_get_components_wrapped_fnc purple_chat_get_components_wrapped = NULL;
 
purple_buddy_get_presence_wrapped_fnc purple_buddy_get_presence_wrapped = NULL;
 
purple_buddy_get_account_wrapped_fnc purple_buddy_get_account_wrapped = NULL;
 
purple_buddy_get_name_wrapped_fnc purple_buddy_get_name_wrapped = NULL;
 
purple_find_buddies_wrapped_fnc purple_find_buddies_wrapped = NULL;
 
purple_group_get_name_wrapped_fnc purple_group_get_name_wrapped = NULL;
 
purple_blist_set_ui_ops_wrapped_fnc purple_blist_set_ui_ops_wrapped = NULL;
 
purple_set_blist_wrapped_fnc purple_set_blist_wrapped = NULL;
 
purple_blist_new_wrapped_fnc purple_blist_new_wrapped = NULL;
 
purple_blist_load_wrapped_fnc purple_blist_load_wrapped = NULL;
 
purple_blist_get_handle_wrapped_fnc purple_blist_get_handle_wrapped = NULL;
 
purple_buddy_icons_set_account_icon_wrapped_fnc purple_buddy_icons_set_account_icon_wrapped = NULL;
 
purple_buddy_icons_find_wrapped_fnc purple_buddy_icons_find_wrapped = NULL;
 
purple_buddy_icon_get_full_path_wrapped_fnc purple_buddy_icon_get_full_path_wrapped = NULL;
 
purple_buddy_icon_unref_wrapped_fnc purple_buddy_icon_unref_wrapped = NULL;
 
purple_buddy_icons_find_account_icon_wrapped_fnc purple_buddy_icons_find_account_icon_wrapped = NULL;
 
purple_buddy_icon_get_data_wrapped_fnc purple_buddy_icon_get_data_wrapped = NULL;
 
purple_certificate_add_ca_search_path_wrapped_fnc purple_certificate_add_ca_search_path_wrapped = NULL;
 
purple_connection_get_state_wrapped_fnc purple_connection_get_state_wrapped = NULL;
 
purple_connection_get_account_wrapped_fnc purple_connection_get_account_wrapped = NULL;
 
purple_connection_get_display_name_wrapped_fnc purple_connection_get_display_name_wrapped = NULL;
 
purple_connections_set_ui_ops_wrapped_fnc purple_connections_set_ui_ops_wrapped = NULL;
 
purple_connections_get_handle_wrapped_fnc purple_connections_get_handle_wrapped = NULL;
 
purple_conversation_get_im_data_wrapped_fnc purple_conversation_get_im_data_wrapped = NULL;
 
purple_conversation_get_chat_data_wrapped_fnc purple_conversation_get_chat_data_wrapped = NULL;
 
purple_find_conversation_with_account_wrapped_fnc purple_find_conversation_with_account_wrapped = NULL;
 
purple_conversation_new_wrapped_fnc purple_conversation_new_wrapped = NULL;
 
purple_conversation_get_type_wrapped_fnc purple_conversation_get_type_wrapped = NULL;
 
purple_conv_im_send_wrapped_fnc purple_conv_im_send_wrapped = NULL;
 
purple_conv_im_send_with_flags_wrapped_fnc purple_conv_im_send_with_flags_wrapped = NULL;
 
purple_conv_chat_send_wrapped_fnc purple_conv_chat_send_wrapped = NULL;
 
purple_conv_chat_send_with_flags_wrapped_fnc purple_conv_chat_send_with_flags_wrapped = NULL;
 
purple_conversation_destroy_wrapped_fnc purple_conversation_destroy_wrapped = NULL;
 
purple_conversation_get_account_wrapped_fnc purple_conversation_get_account_wrapped = NULL;
 
purple_conversation_get_name_wrapped_fnc purple_conversation_get_name_wrapped = NULL;
 
purple_conversations_set_ui_ops_wrapped_fnc purple_conversations_set_ui_ops_wrapped = NULL;
 
purple_conversations_get_handle_wrapped_fnc purple_conversations_get_handle_wrapped = NULL;
 
purple_core_set_ui_ops_wrapped_fnc purple_core_set_ui_ops_wrapped = NULL;
 
purple_core_init_wrapped_fnc purple_core_init_wrapped = NULL;
 
purple_debug_set_ui_ops_wrapped_fnc purple_debug_set_ui_ops_wrapped = NULL;
 
purple_debug_set_verbose_wrapped_fnc purple_debug_set_verbose_wrapped = NULL;
 
purple_dnsquery_set_ui_ops_wrapped_fnc purple_dnsquery_set_ui_ops_wrapped = NULL;
 
purple_timeout_remove_wrapped_fnc purple_timeout_remove_wrapped = NULL;
 
purple_input_add_wrapped_fnc purple_input_add_wrapped = NULL;
 
purple_timeout_add_wrapped_fnc purple_timeout_add_wrapped = NULL;
 
purple_timeout_add_seconds_wrapped_fnc purple_timeout_add_seconds_wrapped = NULL;
 
purple_eventloop_set_ui_ops_wrapped_fnc purple_eventloop_set_ui_ops_wrapped = NULL;
 
purple_input_remove_wrapped_fnc purple_input_remove_wrapped = NULL;
 
purple_xfer_ui_ready_wrapped_fnc purple_xfer_ui_ready_wrapped = NULL;
 
purple_xfer_request_accepted_wrapped_fnc purple_xfer_request_accepted_wrapped = NULL;
 
purple_xfer_request_denied_wrapped_fnc purple_xfer_request_denied_wrapped = NULL;
 
purple_xfer_get_account_wrapped_fnc purple_xfer_get_account_wrapped = NULL;
 
purple_xfer_get_filename_wrapped_fnc purple_xfer_get_filename_wrapped = NULL;
 
purple_xfer_get_size_wrapped_fnc purple_xfer_get_size_wrapped = NULL;
 
purple_xfer_unref_wrapped_fnc purple_xfer_unref_wrapped = NULL;
 
purple_xfer_ref_wrapped_fnc purple_xfer_ref_wrapped = NULL;
 
purple_xfers_set_ui_ops_wrapped_fnc purple_xfers_set_ui_ops_wrapped = NULL;
 
purple_xfers_get_handle_wrapped_fnc purple_xfers_get_handle_wrapped = NULL;
 
purple_roomlist_set_ui_ops_wrapped_fnc purple_roomlist_set_ui_ops_wrapped = NULL;
 
purple_roomlist_get_list_wrapped_fnc purple_roomlist_get_list_wrapped = NULL;
 
purple_imgstore_get_data_wrapped_fnc purple_imgstore_get_data_wrapped = NULL;
 
purple_imgstore_get_size_wrapped_fnc purple_imgstore_get_size_wrapped = NULL;
 
purple_imgstore_unref_wrapped_fnc purple_imgstore_unref_wrapped = NULL;
 
purple_notify_user_info_new_wrapped_fnc purple_notify_user_info_new_wrapped = NULL;
 
purple_notify_user_info_destroy_wrapped_fnc purple_notify_user_info_destroy_wrapped = NULL;
 
purple_notify_user_info_get_entries_wrapped_fnc purple_notify_user_info_get_entries_wrapped = NULL;
 
purple_notify_user_info_entry_get_label_wrapped_fnc purple_notify_user_info_entry_get_label_wrapped = NULL;
 
purple_notify_user_info_entry_get_value_wrapped_fnc purple_notify_user_info_entry_get_value_wrapped = NULL;
 
purple_notify_set_ui_ops_wrapped_fnc purple_notify_set_ui_ops_wrapped = NULL;
 
purple_plugins_add_search_path_wrapped_fnc purple_plugins_add_search_path_wrapped = NULL;
 
purple_plugin_action_free_wrapped_fnc purple_plugin_action_free_wrapped = NULL;
 
purple_prefs_load_wrapped_fnc purple_prefs_load_wrapped = NULL;
 
purple_prefs_set_bool_wrapped_fnc purple_prefs_set_bool_wrapped = NULL;
 
purple_prefs_set_string_wrapped_fnc purple_prefs_set_string_wrapped = NULL;
 
purple_privacy_deny_wrapped_fnc purple_privacy_deny_wrapped = NULL;
 
purple_privacy_allow_wrapped_fnc purple_privacy_allow_wrapped = NULL;
 
purple_privacy_check_wrapped_fnc purple_privacy_check_wrapped = NULL;
 
purple_proxy_info_new_wrapped_fnc purple_proxy_info_new_wrapped = NULL;
 
purple_proxy_info_set_type_wrapped_fnc purple_proxy_info_set_type_wrapped = NULL;
 
purple_proxy_info_set_host_wrapped_fnc purple_proxy_info_set_host_wrapped = NULL;
 
@@ -396,100 +398,108 @@ bool resolvePurpleFunctions() {
 
	purple_certificate_add_ca_search_path_wrapped = (purple_certificate_add_ca_search_path_wrapped_fnc)GetProcAddress(f_hPurple, "purple_certificate_add_ca_search_path");
 
	if (!purple_certificate_add_ca_search_path_wrapped)
 
		return false;
 

	
 
	purple_connection_get_state_wrapped = (purple_connection_get_state_wrapped_fnc)GetProcAddress(f_hPurple, "purple_connection_get_state");
 
	if (!purple_connection_get_state_wrapped)
 
		return false;
 

	
 
	purple_connection_get_account_wrapped = (purple_connection_get_account_wrapped_fnc)GetProcAddress(f_hPurple, "purple_connection_get_account");
 
	if (!purple_connection_get_account_wrapped)
 
		return false;
 

	
 
	purple_connection_get_display_name_wrapped = (purple_connection_get_display_name_wrapped_fnc)GetProcAddress(f_hPurple, "purple_connection_get_display_name");
 
	if (!purple_connection_get_display_name_wrapped)
 
		return false;
 

	
 
	purple_connections_set_ui_ops_wrapped = (purple_connections_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_connections_set_ui_ops");
 
	if (!purple_connections_set_ui_ops_wrapped)
 
		return false;
 

	
 
	purple_connections_get_handle_wrapped = (purple_connections_get_handle_wrapped_fnc)GetProcAddress(f_hPurple, "purple_connections_get_handle");
 
	if (!purple_connections_get_handle_wrapped)
 
		return false;
 

	
 
	purple_conversation_get_im_data_wrapped = (purple_conversation_get_im_data_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_get_im_data");
 
	if (!purple_conversation_get_im_data_wrapped)
 
		return false;
 

	
 
	purple_conversation_get_chat_data_wrapped = (purple_conversation_get_chat_data_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_get_chat_data");
 
	if (!purple_conversation_get_chat_data_wrapped)
 
		return false;
 

	
 
	purple_find_conversation_with_account_wrapped = (purple_find_conversation_with_account_wrapped_fnc)GetProcAddress(f_hPurple, "purple_find_conversation_with_account");
 
	if (!purple_find_conversation_with_account_wrapped)
 
		return false;
 

	
 
	purple_conversation_new_wrapped = (purple_conversation_new_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_new");
 
	if (!purple_conversation_new_wrapped)
 
		return false;
 

	
 
	purple_conversation_get_type_wrapped = (purple_conversation_get_type_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_get_type");
 
	if (!purple_conversation_get_type_wrapped)
 
		return false;
 

	
 
	purple_conv_im_send_wrapped = (purple_conv_im_send_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conv_im_send");
 
	if (!purple_conv_im_send_wrapped)
 
		return false;
 

	
 
	purple_conv_im_send_with_flags_wrapped = (purple_conv_im_send_with_flags_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conv_im_send_with_flags");
 
	if (!purple_conv_im_send_with_flags_wrapped)
 
		return false;
 

	
 
	purple_conv_chat_send_wrapped = (purple_conv_chat_send_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conv_chat_send");
 
	if (!purple_conv_chat_send_wrapped)
 
		return false;
 

	
 
	purple_conv_chat_send_with_flags_wrapped = (purple_conv_chat_send_with_flags_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conv_chat_send_with_flags");
 
	if (!purple_conv_chat_send_with_flags_wrapped)
 
		return false;
 

	
 
	purple_conversation_destroy_wrapped = (purple_conversation_destroy_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_destroy");
 
	if (!purple_conversation_destroy_wrapped)
 
		return false;
 

	
 
	purple_conversation_get_account_wrapped = (purple_conversation_get_account_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_get_account");
 
	if (!purple_conversation_get_account_wrapped)
 
		return false;
 

	
 
	purple_conversation_get_name_wrapped = (purple_conversation_get_name_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversation_get_name");
 
	if (!purple_conversation_get_name_wrapped)
 
		return false;
 

	
 
	purple_conversations_set_ui_ops_wrapped = (purple_conversations_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversations_set_ui_ops");
 
	if (!purple_conversations_set_ui_ops_wrapped)
 
		return false;
 

	
 
	purple_conversations_get_handle_wrapped = (purple_conversations_get_handle_wrapped_fnc)GetProcAddress(f_hPurple, "purple_conversations_get_handle");
 
	if (!purple_conversations_get_handle_wrapped)
 
		return false;
 

	
 
	purple_core_set_ui_ops_wrapped = (purple_core_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_core_set_ui_ops");
 
	if (!purple_core_set_ui_ops_wrapped)
 
		return false;
 

	
 
	purple_core_init_wrapped = (purple_core_init_wrapped_fnc)GetProcAddress(f_hPurple, "purple_core_init");
 
	if (!purple_core_init_wrapped)
 
		return false;
 

	
 
	purple_debug_set_ui_ops_wrapped = (purple_debug_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_debug_set_ui_ops");
 
	if (!purple_debug_set_ui_ops_wrapped)
 
		return false;
 

	
 
	purple_debug_set_verbose_wrapped = (purple_debug_set_verbose_wrapped_fnc)GetProcAddress(f_hPurple, "purple_debug_set_verbose");
 
	if (!purple_debug_set_verbose_wrapped)
 
		return false;
 

	
 
	purple_dnsquery_set_ui_ops_wrapped = (purple_dnsquery_set_ui_ops_wrapped_fnc)GetProcAddress(f_hPurple, "purple_dnsquery_set_ui_ops");
 
	if (!purple_dnsquery_set_ui_ops_wrapped)
 
		return false;
 

	
 
	purple_timeout_remove_wrapped = (purple_timeout_remove_wrapped_fnc)GetProcAddress(f_hPurple, "purple_timeout_remove");
 
	if (!purple_timeout_remove_wrapped)
 
		return false;
 

	
 
	purple_input_add_wrapped = (purple_input_add_wrapped_fnc)GetProcAddress(f_hPurple, "purple_input_add");
 
	if (!purple_input_add_wrapped)
 
		return false;
 

	
backends/libpurple/purple_defs.h
Show inline comments
 
@@ -191,99 +191,105 @@ extern purple_buddy_icon_unref_wrapped_fnc purple_buddy_icon_unref_wrapped;
 
typedef PurpleStoredImage * (_cdecl * purple_buddy_icons_find_account_icon_wrapped_fnc)(PurpleAccount *account);
 
extern purple_buddy_icons_find_account_icon_wrapped_fnc purple_buddy_icons_find_account_icon_wrapped;
 

	
 
typedef gconstpointer  (_cdecl * purple_buddy_icon_get_data_wrapped_fnc)(const PurpleBuddyIcon *icon, size_t *len);
 
extern purple_buddy_icon_get_data_wrapped_fnc purple_buddy_icon_get_data_wrapped;
 

	
 
typedef void  (_cdecl * purple_certificate_add_ca_search_path_wrapped_fnc)(const char *path);
 
extern purple_certificate_add_ca_search_path_wrapped_fnc purple_certificate_add_ca_search_path_wrapped;
 

	
 
typedef PurpleConnectionState  (_cdecl * purple_connection_get_state_wrapped_fnc)(const PurpleConnection *gc);
 
extern purple_connection_get_state_wrapped_fnc purple_connection_get_state_wrapped;
 

	
 
typedef PurpleAccount * (_cdecl * purple_connection_get_account_wrapped_fnc)(const PurpleConnection *gc);
 
extern purple_connection_get_account_wrapped_fnc purple_connection_get_account_wrapped;
 

	
 
typedef const char * (_cdecl * purple_connection_get_display_name_wrapped_fnc)(const PurpleConnection *gc);
 
extern purple_connection_get_display_name_wrapped_fnc purple_connection_get_display_name_wrapped;
 

	
 
typedef void  (_cdecl * purple_connections_set_ui_ops_wrapped_fnc)(PurpleConnectionUiOps *ops);
 
extern purple_connections_set_ui_ops_wrapped_fnc purple_connections_set_ui_ops_wrapped;
 

	
 
typedef void * (_cdecl * purple_connections_get_handle_wrapped_fnc)(void);
 
extern purple_connections_get_handle_wrapped_fnc purple_connections_get_handle_wrapped;
 

	
 
typedef PurpleConvIm * (_cdecl * purple_conversation_get_im_data_wrapped_fnc)(const PurpleConversation *conv);
 
extern purple_conversation_get_im_data_wrapped_fnc purple_conversation_get_im_data_wrapped;
 

	
 
typedef PurpleConvChat * (_cdecl * purple_conversation_get_chat_data_wrapped_fnc)(const PurpleConversation *conv);
 
extern purple_conversation_get_chat_data_wrapped_fnc purple_conversation_get_chat_data_wrapped;
 

	
 
typedef PurpleConversation * (_cdecl * purple_find_conversation_with_account_wrapped_fnc)( PurpleConversationType type, const char *name, const PurpleAccount *account);
 
extern purple_find_conversation_with_account_wrapped_fnc purple_find_conversation_with_account_wrapped;
 

	
 
typedef PurpleConversation * (_cdecl * purple_conversation_new_wrapped_fnc)(PurpleConversationType type, PurpleAccount *account, const char *name);
 
extern purple_conversation_new_wrapped_fnc purple_conversation_new_wrapped;
 

	
 
typedef PurpleConversationType  (_cdecl * purple_conversation_get_type_wrapped_fnc)(const PurpleConversation *conv);
 
extern purple_conversation_get_type_wrapped_fnc purple_conversation_get_type_wrapped;
 

	
 
typedef void (_cdecl * purple_conversation_set_data_wrapped_func)(const PurpleConversation *conv, const char *key, gpointer data); 
 
extern purple_conversation_set_data_wrapped_func purple_conversation_set_data_wrapped;
 

	
 
typedef void (_cdecl * purple_conversation_update_wrapped_func)(const PurpleConversation *conv, PurpleConversationUpdateType type); 
 
extern purple_conversation_update_wrapped_func purple_conversation_update_wrapped;
 

	
 
typedef void  (_cdecl * purple_conv_im_send_wrapped_fnc)(PurpleConvIm *im, const char *message);
 
extern purple_conv_im_send_wrapped_fnc purple_conv_im_send_wrapped;
 

	
 
typedef void  (_cdecl * purple_conv_im_send_with_flags_wrapped_fnc)(PurpleConvIm *im, const char *message, PurpleMessageFlags flags);
 
extern purple_conv_im_send_with_flags_wrapped_fnc purple_conv_im_send_with_flags_wrapped;
 

	
 
typedef void  (_cdecl * purple_conv_chat_send_wrapped_fnc)(PurpleConvChat *chat, const char *message);
 
extern purple_conv_chat_send_wrapped_fnc purple_conv_chat_send_wrapped;
 

	
 
typedef void  (_cdecl * purple_conv_chat_send_with_flags_wrapped_fnc)(PurpleConvChat *chat, const char *message, PurpleMessageFlags flags);
 
extern purple_conv_chat_send_with_flags_wrapped_fnc purple_conv_chat_send_with_flags_wrapped;
 

	
 
typedef void  (_cdecl * purple_conversation_destroy_wrapped_fnc)(PurpleConversation *conv);
 
extern purple_conversation_destroy_wrapped_fnc purple_conversation_destroy_wrapped;
 

	
 
typedef PurpleAccount * (_cdecl * purple_conversation_get_account_wrapped_fnc)(const PurpleConversation *conv);
 
extern purple_conversation_get_account_wrapped_fnc purple_conversation_get_account_wrapped;
 

	
 
typedef const char * (_cdecl * purple_conversation_get_name_wrapped_fnc)(const PurpleConversation *conv);
 
extern purple_conversation_get_name_wrapped_fnc purple_conversation_get_name_wrapped;
 

	
 
typedef void  (_cdecl * purple_conversations_set_ui_ops_wrapped_fnc)(PurpleConversationUiOps *ops);
 
extern purple_conversations_set_ui_ops_wrapped_fnc purple_conversations_set_ui_ops_wrapped;
 

	
 
typedef void * (_cdecl * purple_conversations_get_handle_wrapped_fnc)(void);
 
extern purple_conversations_get_handle_wrapped_fnc purple_conversations_get_handle_wrapped;
 

	
 
typedef void  (_cdecl * purple_core_set_ui_ops_wrapped_fnc)(PurpleCoreUiOps *ops);
 
extern purple_core_set_ui_ops_wrapped_fnc purple_core_set_ui_ops_wrapped;
 

	
 
typedef gboolean  (_cdecl * purple_core_init_wrapped_fnc)(const char *ui);
 
extern purple_core_init_wrapped_fnc purple_core_init_wrapped;
 

	
 
typedef void  (_cdecl * purple_debug_set_ui_ops_wrapped_fnc)(PurpleDebugUiOps *ops);
 
extern purple_debug_set_ui_ops_wrapped_fnc purple_debug_set_ui_ops_wrapped;
 

	
 
typedef void  (_cdecl * purple_debug_set_verbose_wrapped_fnc)(gboolean verbose);
 
extern purple_debug_set_verbose_wrapped_fnc purple_debug_set_verbose_wrapped;
 

	
 
typedef void  (_cdecl * purple_dnsquery_set_ui_ops_wrapped_fnc)(PurpleDnsQueryUiOps *ops);
 
extern purple_dnsquery_set_ui_ops_wrapped_fnc purple_dnsquery_set_ui_ops_wrapped;
 

	
 
typedef gboolean  (_cdecl * purple_timeout_remove_wrapped_fnc)(guint handle);
 
extern purple_timeout_remove_wrapped_fnc purple_timeout_remove_wrapped;
 

	
 
typedef guint  (_cdecl * purple_input_add_wrapped_fnc)(int fd, PurpleInputCondition cond, PurpleInputFunction func, gpointer user_data);
 
extern purple_input_add_wrapped_fnc purple_input_add_wrapped;
 

	
 
typedef guint  (_cdecl * purple_timeout_add_wrapped_fnc)(guint interval, GSourceFunc function, gpointer data);
 
extern purple_timeout_add_wrapped_fnc purple_timeout_add_wrapped;
 

	
 
typedef guint  (_cdecl * purple_timeout_add_seconds_wrapped_fnc)(guint interval, GSourceFunc function, gpointer data);
 
extern purple_timeout_add_seconds_wrapped_fnc purple_timeout_add_seconds_wrapped;
 

	
 
typedef void  (_cdecl * purple_eventloop_set_ui_ops_wrapped_fnc)(PurpleEventLoopUiOps *ops);
 
extern purple_eventloop_set_ui_ops_wrapped_fnc purple_eventloop_set_ui_ops_wrapped;
 

	
 
typedef gboolean  (_cdecl * purple_input_remove_wrapped_fnc)(guint handle);
 
extern purple_input_remove_wrapped_fnc purple_input_remove_wrapped;
 

	
 
@@ -498,97 +504,99 @@ extern wpurple_g_io_channel_win32_new_socket_wrapped_fnc wpurple_g_io_channel_wi
 
#define purple_account_option_get_type_wrapped purple_account_option_get_type
 
#define purple_account_option_get_setting_wrapped purple_account_option_get_setting
 
#define purple_blist_node_get_type_wrapped purple_blist_node_get_type
 
#define purple_buddy_get_alias_wrapped purple_buddy_get_alias
 
#define purple_buddy_get_server_alias_wrapped purple_buddy_get_server_alias
 
#define purple_find_buddy_wrapped purple_find_buddy
 
#define purple_buddy_get_group_wrapped purple_buddy_get_group
 
#define purple_blist_remove_buddy_wrapped purple_blist_remove_buddy
 
#define purple_blist_alias_buddy_wrapped purple_blist_alias_buddy
 
#define purple_blist_server_alias_buddy_wrapped purple_blist_server_alias_buddy
 
#define purple_find_group_wrapped purple_find_group
 
#define purple_group_new_wrapped purple_group_new
 
#define purple_blist_add_contact_wrapped purple_blist_add_contact
 
#define purple_buddy_get_contact_wrapped purple_buddy_get_contact
 
#define purple_buddy_new_wrapped purple_buddy_new
 
#define purple_blist_add_buddy_wrapped purple_blist_add_buddy
 
#define purple_blist_find_chat_wrapped purple_blist_find_chat
 
#define purple_chat_get_components_wrapped purple_chat_get_components
 
#define purple_buddy_get_presence_wrapped purple_buddy_get_presence
 
#define purple_buddy_get_account_wrapped purple_buddy_get_account
 
#define purple_buddy_get_name_wrapped purple_buddy_get_name
 
#define purple_find_buddies_wrapped purple_find_buddies
 
#define purple_group_get_name_wrapped purple_group_get_name
 
#define purple_blist_set_ui_ops_wrapped purple_blist_set_ui_ops
 
#define purple_set_blist_wrapped purple_set_blist
 
#define purple_blist_new_wrapped purple_blist_new
 
#define purple_blist_load_wrapped purple_blist_load
 
#define purple_blist_get_handle_wrapped purple_blist_get_handle
 
#define purple_buddy_icons_set_account_icon_wrapped purple_buddy_icons_set_account_icon
 
#define purple_buddy_icons_find_wrapped purple_buddy_icons_find
 
#define purple_buddy_icon_get_full_path_wrapped purple_buddy_icon_get_full_path
 
#define purple_buddy_icon_unref_wrapped purple_buddy_icon_unref
 
#define purple_buddy_icons_find_account_icon_wrapped purple_buddy_icons_find_account_icon
 
#define purple_buddy_icon_get_data_wrapped purple_buddy_icon_get_data
 
#define purple_certificate_add_ca_search_path_wrapped purple_certificate_add_ca_search_path
 
#define purple_connection_get_state_wrapped purple_connection_get_state
 
#define purple_connection_get_account_wrapped purple_connection_get_account
 
#define purple_connection_get_display_name_wrapped purple_connection_get_display_name
 
#define purple_connections_set_ui_ops_wrapped purple_connections_set_ui_ops
 
#define purple_connections_get_handle_wrapped purple_connections_get_handle
 
#define purple_conversation_get_im_data_wrapped purple_conversation_get_im_data
 
#define purple_conversation_get_chat_data_wrapped purple_conversation_get_chat_data
 
#define purple_find_conversation_with_account_wrapped purple_find_conversation_with_account
 
#define purple_conversation_new_wrapped purple_conversation_new
 
#define purple_conversation_get_type_wrapped purple_conversation_get_type
 
#define purple_conversation_set_data_wrapped purple_conversation_set_data
 
#define purple_conversation_update_wrapped purple_conversation_update
 
#define purple_conv_im_send_wrapped purple_conv_im_send
 
#define purple_conv_im_send_with_flags_wrapped purple_conv_im_send_with_flags
 
#define purple_conv_chat_send_wrapped purple_conv_chat_send
 
#define purple_conv_chat_send_with_flags_wrapped purple_conv_chat_send_with_flags
 
#define purple_conversation_destroy_wrapped purple_conversation_destroy
 
#define purple_conversation_get_account_wrapped purple_conversation_get_account
 
#define purple_conversation_get_name_wrapped purple_conversation_get_name
 
#define purple_conversations_set_ui_ops_wrapped purple_conversations_set_ui_ops
 
#define purple_conversations_get_handle_wrapped purple_conversations_get_handle
 
#define purple_core_set_ui_ops_wrapped purple_core_set_ui_ops
 
#define purple_core_init_wrapped purple_core_init
 
#define purple_debug_set_ui_ops_wrapped purple_debug_set_ui_ops
 
#define purple_debug_set_verbose_wrapped purple_debug_set_verbose
 
#define purple_dnsquery_set_ui_ops_wrapped purple_dnsquery_set_ui_ops
 
#define purple_timeout_remove_wrapped purple_timeout_remove
 
#define purple_input_add_wrapped purple_input_add
 
#define purple_timeout_add_wrapped purple_timeout_add
 
#define purple_timeout_add_seconds_wrapped purple_timeout_add_seconds
 
#define purple_eventloop_set_ui_ops_wrapped purple_eventloop_set_ui_ops
 
#define purple_input_remove_wrapped purple_input_remove
 
#define purple_xfer_ui_ready_wrapped purple_xfer_ui_ready
 
#define purple_xfer_request_accepted_wrapped purple_xfer_request_accepted
 
#define purple_xfer_request_denied_wrapped purple_xfer_request_denied
 
#define purple_xfer_get_account_wrapped purple_xfer_get_account
 
#define purple_xfer_get_filename_wrapped purple_xfer_get_filename
 
#define purple_xfer_get_size_wrapped purple_xfer_get_size
 
#define purple_xfer_unref_wrapped purple_xfer_unref
 
#define purple_xfer_ref_wrapped purple_xfer_ref
 
#define purple_xfers_set_ui_ops_wrapped purple_xfers_set_ui_ops
 
#define purple_xfers_get_handle_wrapped purple_xfers_get_handle
 
#define purple_roomlist_set_ui_ops_wrapped purple_roomlist_set_ui_ops
 
#define purple_roomlist_get_list_wrapped purple_roomlist_get_list
 
#define purple_imgstore_get_data_wrapped purple_imgstore_get_data
 
#define purple_imgstore_get_size_wrapped purple_imgstore_get_size
 
#define purple_imgstore_unref_wrapped purple_imgstore_unref
 
#define purple_notify_user_info_new_wrapped purple_notify_user_info_new
 
#define purple_notify_user_info_destroy_wrapped purple_notify_user_info_destroy
 
#define purple_notify_user_info_get_entries_wrapped purple_notify_user_info_get_entries
 
#define purple_notify_user_info_entry_get_label_wrapped purple_notify_user_info_entry_get_label
 
#define purple_notify_user_info_entry_get_value_wrapped purple_notify_user_info_entry_get_value
 
#define purple_notify_set_ui_ops_wrapped purple_notify_set_ui_ops
 
#define purple_plugins_add_search_path_wrapped purple_plugins_add_search_path
 
#define purple_plugin_action_free_wrapped purple_plugin_action_free
 
#define purple_prefs_load_wrapped purple_prefs_load
 
#define purple_prefs_set_bool_wrapped purple_prefs_set_bool
 
#define purple_prefs_set_string_wrapped purple_prefs_set_string
 
#define purple_privacy_deny_wrapped purple_privacy_deny
 
#define purple_privacy_allow_wrapped purple_privacy_allow
 
#define purple_privacy_check_wrapped purple_privacy_check
 
#define purple_proxy_info_new_wrapped purple_proxy_info_new
 
#define purple_proxy_info_set_type_wrapped purple_proxy_info_set_type
 
#define purple_proxy_info_set_host_wrapped purple_proxy_info_set_host
docs/guide/developer_lowlevel.textile
Show inline comments
 
@@ -136,96 +136,97 @@ Backend should change the buddy alias or group according to Buddy payload. If th
 
|blocked| True if this buddy should be blocked|
 

	
 
h3. Type: TYPE_ATTENTION, Payload: ConversationMessage
 

	
 
Backend should forward to buddy represented by buddyName information that XMPP user wants his attention.
 

	
 
|_. Variable|_. Description|
 
|userName| JID of XMPP user|
 
|buddyName| Name of the buddy in legacy network|
 
|message| Message|
 

	
 
h3. Type: TYPE_CONV_MESSAGE, Payload: ConversationMessage
 

	
 
Backend should forward to buddy represented by buddyName message received from user.
 

	
 
|_. Variable|_. Description|
 
|userName| JID of XMPP user|
 
|buddyName| Name of the buddy in legacy network|
 
|message|Plain text message|
 
|xhtml|Message formatted using XHTML-IM XEP if available|
 

	
 
h3. Type: TYPE_VCARD, Payload: VCard
 

	
 
If buddyName is empty, backend should update XMPP user's VCard according to VCard payload. If buddyName is not empty, backend has to fetch VCard of buddyName buddy including photo send it back using @Type: TYPE_VCard, Payload: Buddy@
 

	
 
|_. Variable|_. Description|
 
|userName| JID of XMPP user|
 
|buddyName| Name of the buddy in legacy network|
 
|id|Id used when sending the response with buddy's photo back. You have to use the same id in response as you received in request.|
 
|photo| Binary photo|
 
|nickname|Nickname|
 

	
 

	
 

	
 
h2. WrapperMessage payloads sent by backend
 

	
 
This chapter describes all possible payloads which can be sent by backend to Spectrum 2 main instance.
 

	
 
h3. Type: TYPE_CONV_MESSAGE, Payload: ConversationMessage
 

	
 
Backend sends this payload when it receives new message from legacy network which should be forwarded to XMPP user.
 

	
 
|_. Variable|_. Description|
 
|userName| JID of XMPP user|
 
|buddyName| Name of the buddy in legacy network who sent the message. If the conversation is room, buddyName is name of the room.|
 
|message|Plain text message|
 
|xhtml|Message formatted using XHTML-IM XEP if available|
 
|nickname| If the conversation is room, this is the nickname of user who sent the original message|
 
|carbon| If set, the message is a carbon copy of our own message sent in a different legacy network client. It should be treated as a message FROM us, not TO us|
 

	
 
h3. Type: TYPE_ATTENTION, Payload: ConversationMessage
 

	
 
Backend sends this payload when it receives attention request from legacy network which should be forwarded to XMPP user.
 

	
 
|_. Variable|_. Description|
 
|userName| JID of XMPP user|
 
|buddyName| Name of the buddy in legacy network|
 
|message| Message|
 

	
 
h3. Type: TYPE_VCARD, Payload: VCard
 

	
 
Backend sends this payload as a response to @Type: TYPE_VCARD, Payload: VCard@ received from main Spectrum 2 instance.
 

	
 
|_. Variable|_. Description|
 
|userName| JID of XMPP user|
 
|buddyName| Name of the buddy in legacy network|
 
|id|You have to use the same id in response as you received in request.|
 
|photo| Binary photo|
 
|nickname|Nickname|
 

	
 
h3. Type: TYPE_ROOM_SUBJECT_CHANGED, Payload: ConversationMessage
 

	
 
Backend sends this payload when it receives room subject from legacy network which should be forwarded to XMPP user.
 

	
 
|_. Variable|_. Description|
 
|userName| JID of XMPP user|
 
|buddyName| Name of the room.|
 
|message|Plain text subject.|
 
|nickname| Nickname of user who set the subject.|
 

	
 
h3. Type: TYPE_BUDDY_TYPING, Payload: Buddy
 

	
 
Backend sends this payload when buddy starts typing.
 

	
 
|_. Variable|_. Description|
 
|userName| JID of XMPP user|
 
|buddyName| Name of the buddy in legacy network|
 

	
 
h3. Type: TYPE_BUDDY_TYPED, Payload: Buddy
 

	
 
Backend sends this payload when buddy paused typing.
 

	
 
|_. Variable|_. Description|
 
|userName| JID of XMPP user|
 
|buddyName| Name of the buddy in legacy network|
 

	
 
h3. Type: TYPE_BUDDY_STOPPED_TYPED, Payload: Buddy
include/Swiften/Elements/HintPayload.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Implements XEP-0334: Message Processing Hints
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#include <Swiften/Elements/HintPayload.h>
 

	
 
namespace Swift {
 

	
 
HintPayload::HintPayload(Type type)
 
: type_(type) {
 
}
 

	
 
}
include/Swiften/Elements/HintPayload.h
Show inline comments
 
new file 100644
 
/*
 
 * Implements XEP-0334: Message Processing Hints
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <vector>
 
#include <string>
 
#include <boost/shared_ptr.hpp>
 

	
 
#include <Swiften/Elements/Payload.h>
 

	
 
#include "Swiften/SwiftenCompat.h"
 

	
 
namespace Swift {
 
	class HintPayload : public Payload {
 
	public:
 
		typedef SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<HintPayload> ref;
 

	
 
		enum Type { NoPermanentStore, NoStore, NoCopy, Store };
 

	
 
	public:
 
		HintPayload(Type type = NoCopy);
 

	
 
		void setType(Type type) { type_ = type; }
 
		const Type getType() { return type_; }
 

	
 
	private:
 
		Type type_;
 
	};
 
}
include/Swiften/Elements/Privilege.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Implements Privilege tag for XEP-0356: Privileged Entity
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#include <Swiften/Elements/Privilege.h>
 

	
 
namespace Swift {
 

	
 
Privilege::Privilege() {
 
}
 

	
 
}
include/Swiften/Elements/Privilege.h
Show inline comments
 
new file 100644
 
/*
 
 * Implements Privilege tag for XEP-0356: Privileged Entity
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <vector>
 
#include <string>
 
#include <boost/shared_ptr.hpp>
 

	
 
#include <Swiften/Base/API.h>
 
#include <Swiften/Elements/Payload.h>
 

	
 
#include <Swiften/Version.h>
 
#if (SWIFTEN_VERSION >= 0x030000)
 
#define SWIFTEN_SUPPORTS_FORWARDED
 
#include <Swiften/Elements/Forwarded.h>
 
#endif
 

	
 
#include "Swiften/SwiftenCompat.h"
 

	
 
namespace Swift {
 
	class Stanza;
 

	
 
	class Privilege : public Payload {
 
	public:
 
		typedef SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Privilege> ref;
 
#ifdef SWIFTEN_SUPPORTS_FORWARDED
 
		typedef Swift::Forwarded Forwarded;
 
#else
 
		typedef Payload Forwarded;
 
#endif
 

	
 
	public:
 
		Privilege();
 

	
 
		void setForwarded(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Forwarded> forwarded) { forwarded_ = forwarded; }
 
		const SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Forwarded>& getForwarded() const { return forwarded_; }
 

	
 
	private:
 
		SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Forwarded> forwarded_;
 
	};
 
}
include/Swiften/Parser/PayloadParsers/HintPayloadParser.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Implements XEP-0334: Message Processing Hints
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#include <Swiften/Parser/PayloadParsers/HintPayloadParser.h>
 

	
 
namespace Swift {
 

	
 
HintPayloadParser::HintPayloadParser() : level_(0) {
 
}
 

	
 
void HintPayloadParser::handleStartElement(const std::string& element, const std::string& /*ns*/, const AttributeMap& /*attributes*/) {
 
	if (level_ == 0) {
 
		HintPayload::Type type = HintPayload::NoCopy;
 
		if (element == "no-permanent-store") {
 
			type = HintPayload::NoPermanentStore;
 
		} else if (element == "no-store") {
 
			type = HintPayload::NoStore;
 
		} else if (element == "no-copy") {
 
			type = HintPayload::NoCopy;
 
		} else if (element == "store") {
 
			type = HintPayload::Store;
 
		}
 
		getPayloadInternal()->setType(type);
 
	}
 
	++level_;
 
}
 

	
 
void HintPayloadParser::handleEndElement(const std::string&, const std::string&) {
 
	--level_;
 
}
 

	
 
void HintPayloadParser::handleCharacterData(const std::string&) {
 
}
 

	
 
}
include/Swiften/Parser/PayloadParsers/HintPayloadParser.h
Show inline comments
 
new file 100644
 
/*
 
 * Implements XEP-0334: Message Processing Hints
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <Swiften/Elements/HintPayload.h>
 
#include <Swiften/Parser/GenericPayloadParser.h>
 

	
 
namespace Swift {
 
	class HintPayloadParser : public GenericPayloadParser<HintPayload> {
 
	public:
 
		HintPayloadParser();
 

	
 
		virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes);
 
		virtual void handleEndElement(const std::string& element, const std::string&);
 
		virtual void handleCharacterData(const std::string& data);
 

	
 
	private:
 
		int level_;
 
	};
 
}
include/Swiften/Parser/PayloadParsers/PrivilegeParser.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Implements Privilege tag for XEP-0356: Privileged Entity
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#include <Swiften/Parser/PayloadParsers/PrivilegeParser.h>
 
#ifdef SWIFTEN_SUPPORTS_FORWARDED
 
#include <Swiften/Parser/PayloadParsers/ForwardedParser.h>
 
#else
 
#include <Swiften/Parser/PayloadParserFactoryCollection.h>
 
#include <Swiften/Parser/PayloadParserFactory.h>
 
#include <Swiften/Parser/UnknownPayloadParser.h>
 
#endif
 

	
 
namespace Swift {
 

	
 
PrivilegeParser::PrivilegeParser(PayloadParserFactoryCollection* factories) : factories_(factories), level_(TopLevel) {
 
}
 

	
 
void PrivilegeParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) {
 
	if (level_ == PayloadLevel) {
 
		if (element == "forwarded" && ns == "urn:xmpp:forward:0") {
 
#ifdef SWIFTEN_SUPPORTS_FORWARDED
 
			childParser_ = SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast<PayloadParser>(SWIFTEN_SHRPTR_NAMESPACE::make_shared<ForwardedParser>(factories_));
 
#else
 
			PayloadParserFactory* parserFactory = factories_->getPayloadParserFactory(element, ns, attributes);
 
			if (parserFactory) {
 
				childParser_.reset(parserFactory->createPayloadParser());
 
			}
 
			else {
 
				childParser_.reset(new UnknownPayloadParser());
 
			}
 
#endif
 
		};
 
	}
 
	if (childParser_) {
 
		childParser_->handleStartElement(element, ns, attributes);
 
	}
 
	++level_;
 
}
 

	
 
void PrivilegeParser::handleEndElement(const std::string& element, const std::string& ns) {
 
	--level_;
 
	if (childParser_ && level_ >= PayloadLevel) {
 
		childParser_->handleEndElement(element, ns);
 
	}
 
	if (childParser_ && level_ == PayloadLevel) {
 
		getPayloadInternal()->setForwarded(SWIFTEN_SHRPTR_NAMESPACE::dynamic_pointer_cast<Privilege::Forwarded>(childParser_->getPayload()));
 
		childParser_.reset();
 
	}
 
}
 

	
 
void PrivilegeParser::handleCharacterData(const std::string& data) {
 
	if (childParser_) {
 
		childParser_->handleCharacterData(data);
 
	}
 
}
 

	
 
}
include/Swiften/Parser/PayloadParsers/PrivilegeParser.h
Show inline comments
 
new file 100644
 
/*
 
 * Implements Privilege tag for XEP-0356: Privileged Entity
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <Swiften/Base/API.h>
 
#include <Swiften/Elements/Privilege.h>
 
#include <Swiften/Parser/GenericPayloadParser.h>
 

	
 
namespace Swift {
 
	class PayloadParserFactoryCollection;
 
	class PayloadParser;
 

	
 
	class PrivilegeParser : public GenericPayloadParser<Privilege> {
 
	public:
 
		PrivilegeParser(PayloadParserFactoryCollection* factories);
 

	
 
		virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes);
 
		virtual void handleEndElement(const std::string& element, const std::string&);
 
		virtual void handleCharacterData(const std::string& data);
 

	
 
	enum Level {
 
		TopLevel = 0,
 
		PayloadLevel = 1
 
	};
 

	
 
	private:
 
		PayloadParserFactoryCollection* factories_;
 
		SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<PayloadParser> childParser_;
 
		int level_;
 
	};
 
}
include/Swiften/Serializer/PayloadSerializers/HintPayloadSerializer.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Implements XEP-0334: Message Processing Hints
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#include <string>
 

	
 
#include <Swiften/Serializer/PayloadSerializers/HintPayloadSerializer.h>
 

	
 
#include <boost/shared_ptr.hpp>
 

	
 
#include <Swiften/Serializer/XML/XMLTextNode.h>
 
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
 
#include <Swiften/Serializer/XML/XMLElement.h>
 

	
 
namespace Swift {
 

	
 
HintPayloadSerializer::HintPayloadSerializer() : GenericPayloadSerializer<HintPayload>() {
 
}
 

	
 
std::string HintPayloadSerializer::serializePayload(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<HintPayload> hint)  const {
 
	std::string tagname = "";
 
	switch(hint->getType()) {
 
	case HintPayload::NoPermanentStore: tagname = "no-permanent-store"; break;
 
	case HintPayload::NoStore: tagname = "no-store"; break;
 
	case HintPayload::NoCopy: tagname = "no-copy"; break;
 
	case HintPayload::Store: tagname = "store"; break;
 
	}
 

	
 
	return XMLElement(tagname, "urn:xmpp:hints").serialize();
 
}
 

	
 
}
include/Swiften/Serializer/PayloadSerializers/HintPayloadSerializer.h
Show inline comments
 
new file 100644
 
/*
 
 * Implements XEP-0334: Message Processing Hints
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <Swiften/Serializer/GenericPayloadSerializer.h>
 
#include <Swiften/Elements/HintPayload.h>
 

	
 
#include "Swiften/SwiftenCompat.h"
 

	
 
namespace Swift {
 
	class HintPayloadSerializer : public GenericPayloadSerializer<HintPayload> {
 
	public:
 
		HintPayloadSerializer();
 

	
 
		virtual std::string serializePayload(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<HintPayload>)  const;
 
	};
 
}
include/Swiften/Serializer/PayloadSerializers/PrivilegeSerializer.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Implements Privilege tag for XEP-0356: Privileged Entity
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#include <Swiften/Serializer/PayloadSerializers/PrivilegeSerializer.h>
 

	
 
#include <boost/shared_ptr.hpp>
 

	
 
#include <Swiften/Serializer/XML/XMLTextNode.h>
 
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
 
#include <Swiften/Serializer/XML/XMLElement.h>
 

	
 
#ifdef SWIFTEN_SUPPORTS_FORWARDED
 
#include <Swiften/Elements/Forwarded.h>
 
#include <Swiften/Serializer/PayloadSerializers/ForwardedSerializer.h>
 
#else
 
#include <Swiften/Serializer/PayloadSerializerCollection.h>
 
#endif
 

	
 
namespace Swift {
 

	
 
PrivilegeSerializer::PrivilegeSerializer(PayloadSerializerCollection* serializers) : GenericPayloadSerializer<Privilege>(), serializers_(serializers) {
 
}
 

	
 
PrivilegeSerializer::~PrivilegeSerializer() {
 
}
 

	
 
std::string PrivilegeSerializer::serializePayload(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Privilege> payload)  const {
 
	if (!payload) {
 
		return "";
 
	}
 

	
 
	XMLElement element("privilege", "urn:xmpp:privilege:1");
 

	
 
	SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Privilege::Forwarded> forwarded(payload->getForwarded());
 
	if (forwarded) {
 
		std::string forwardedStr = "";
 
#ifdef SWIFTEN_SUPPORTS_FORWARDED
 
		forwardedStr = ForwardedSerializer(serializers_).serialize(forwarded);
 
#else
 
		PayloadSerializer* serializer = serializers_->getPayloadSerializer(payload);
 
		if(serializer) {
 
			forwardedStr = serializer->serialize(payload);
 
		}
 
#endif
 
		element.addNode(SWIFTEN_SHRPTR_NAMESPACE::make_shared<XMLRawTextNode>(forwardedStr));
 
	}
 

	
 
	return element.serialize();
 
}
 

	
 
}
include/Swiften/Serializer/PayloadSerializers/PrivilegeSerializer.h
Show inline comments
 
new file 100644
 
/*
 
 * Implements Privilege tag for XEP-0356: Privileged Entity
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <Swiften/Serializer/GenericPayloadSerializer.h>
 
#include <Swiften/Elements/Privilege.h>
 

	
 
#include "Swiften/SwiftenCompat.h"
 

	
 
namespace Swift {
 
	class PayloadSerializerCollection;
 

	
 
	class PrivilegeSerializer : public GenericPayloadSerializer<Privilege> {
 
	public:
 
		PrivilegeSerializer(PayloadSerializerCollection* serializers);
 
		virtual ~PrivilegeSerializer();
 

	
 
		virtual std::string serializePayload(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Privilege>) const;
 

	
 
	private:
 
		PayloadSerializerCollection* serializers_;
 
	};
 
}
include/Swiften/SwiftenCompat.h
Show inline comments
 
@@ -6,48 +6,57 @@
 
 * 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  02110-1301, USA.
 
 */
 

	
 
#include <Swiften/Version.h>
 

	
 
/*
 
 * Define macros for Swiften compatible shared pointer and signal namespaces.
 
 *
 
 * Using these it is possible to declare shared pointers and signals like this:
 
 *
 
 * SWIFTEN_SIGNAL_NAMESPACE::signal signal;
 
 * SWIFTEN_SIGNAL_CONNECTION_NAMESPACE::connection &connection;
 
 * SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Type> ptr;
 
 *
 
 * These are guaranteed to be the same implementation as Swift uses internally,
 
 * thus can be used when passign/retrieveing data from/to swiften.
 
 *
 
 * This is due to Swift 4 moved from boost::shared_ptr to SWIFTEN_SHRPTR_NAMESPACE::shared_ptr
 
 * and from boost::signals to boost::signals2 .
 
 */
 

	
 
#if (SWIFTEN_VERSION >= 0x040000)
 
#define SWIFTEN_UNIQUE_PTR std::unique_ptr
 
#define SWIFTEN_SHRPTR_NAMESPACE std
 
#include <boost/signals2.hpp>
 
#define SWIFTEN_SIGNAL_NAMESPACE boost::signals2
 
#define SWIFTEN_SIGNAL_CONNECTION_NAMESPACE boost::signals2
 
#define SWIFT_HOSTADDRESS(x) *(Swift::HostAddress::fromString(x))
 
#else
 
#define SWIFTEN_UNIQUE_PTR std::auto_ptr
 
#define SWIFTEN_SHRPTR_NAMESPACE boost
 
#include <boost/signals.hpp>
 
#define SWIFTEN_SIGNAL_NAMESPACE boost
 
#define SWIFTEN_SIGNAL_CONNECTION_NAMESPACE boost::signals
 
#define SWIFT_HOSTADDRESS(x) Swift::HostAddress(x)
 
#endif
 

	
 
#if (SWIFTEN_VERSION >= 0x030000)
 
//Swiften supports carbon Sent and Received tags as well as Forwarded tags inside those
 
#define SWIFTEN_SUPPORTS_CARBONS
 
//Swiften supports Forwarded tag
 
#define SWIFTEN_SUPPORTS_FORWARDED
 
//Privilege tag is implemented locally, but it makes little sense without forwarded tag
 
#define SWIFTEN_SUPPORTS_PRIVILEGE
 
#endif
 
\ No newline at end of file
include/transport/Conversation.h
Show inline comments
 
@@ -19,97 +19,107 @@
 
 */
 

	
 
#pragma once
 

	
 
#include <string>
 
#include <algorithm>
 
#include <list>
 
#include "Swiften/Elements/Message.h"
 
#include "Swiften/Elements/Presence.h"
 
#include "Swiften/SwiftenCompat.h"
 

	
 
namespace Transport {
 

	
 
class ConversationManager;
 

	
 
/// Represents one XMPP-Legacy network conversation.
 
class Conversation {
 
	public:
 
		typedef enum {
 
			PARTICIPANT_FLAG_NONE = 0,
 
			PARTICIPANT_FLAG_MODERATOR = 1,
 
			PARTICIPANT_FLAG_CONFLICT = 2,
 
			PARTICIPANT_FLAG_BANNED = 4,
 
			PARTICIPANT_FLAG_NOT_AUTHORIZED = 8,
 
			PARTICIPANT_FLAG_ME = 16,
 
			PARTICIPANT_FLAG_KICKED = 32,
 
			PARTICIPANT_FLAG_ROOM_NOT_FOUD = 64
 
		} ParticipantFlag;
 

	
 
		/// Creates new conversation.
 

	
 
		/// \param conversationManager ConversationManager associated with this Conversation.
 
		/// \param legacyName Legacy network name of recipient.
 
		/// \param muc True if this conversation is Multi-user chat.
 
		Conversation(ConversationManager *conversationManager, const std::string &legacyName, bool muc = false);
 

	
 
		/// Destructor.
 
		virtual ~Conversation();
 

	
 
		/// Returns legacy network name of this conversation.
 

	
 
		/// \return legacy network name of this conversation.
 
		const std::string &getLegacyName() { return m_legacyName; }
 

	
 
		/// Handles new message from Legacy network and forwards it to XMPP.
 

	
 
		/// \param message Message received from legacy network.
 
		/// \param nickname For MUC conversation this is nickname of room participant who sent this message.
 
		void handleMessage(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> &message, const std::string &nickname = "");
 
		void handleMessage(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> &message, const std::string &nickname = "", const bool carbon = false);
 

	
 
		//Generates a carbon <sent> wrapper <message> around the given payload and delivers it
 
		void forwardAsCarbonSent(
 
			const SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> &payload,
 
			const Swift::JID& to);
 

	
 
		//Generates a impersonation request <message> arount the given payload and delivers it
 
		void forwardImpersonated(
 
			SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> payload,
 
			const Swift::JID& server);
 

	
 
		void handleRawMessage(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> &message);
 
		void handleRawPresence(Swift::Presence::ref presence);
 

	
 
		/// Handles participant change in MUC.
 

	
 
		/// \param nickname Nickname of participant which changed.
 
		/// \param flag ParticipantFlag.
 
		/// \param status Current status of this participant.
 
		/// \param statusMessage Current status message of this participant.
 
		/// \param newname If participant was renamed, this variable contains his new name.
 
		void handleParticipantChanged(const std::string &nickname, ParticipantFlag flag, int status = Swift::StatusShow::None, const std::string &statusMessage = "", const std::string &newname = "", const std::string &iconhash = "", const std::string &alias = "");
 

	
 
		/// Sets XMPP user nickname in MUC rooms.
 

	
 
		/// \param nickname XMPP user nickname in MUC rooms.
 
		void setNickname(const std::string &nickname);
 

	
 
		const std::string &getNickname() {
 
			return m_nickname;
 
		}
 

	
 
		void setJID(const Swift::JID &jid) {
 
			m_jid = jid;
 
		}
 

	
 
		void addJID(const Swift::JID &jid) {
 
			m_jids.push_back(jid);
 
		}
 

	
 
		void clearJIDs() {
 
			m_jids.clear();
 
		}
 

	
 
		void removeJID(const Swift::JID &jid);
 

	
 
		const std::list<Swift::JID> &getJIDs() {
 
			return m_jids;
 
		}
 

	
 
		/// Sends message to Legacy network.
 

	
 
		/// \param message Message.
 
		virtual void sendMessage(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> &message) = 0;
 

	
 
		/// Returns ConversationManager associated with this Conversation.
 

	
 
		/// \return  ConversationManager associated with this Conversation.
include/transport/NetworkPlugin.h
Show inline comments
 
@@ -77,97 +77,98 @@ class NetworkPlugin {
 

	
 
		/// Call this function when legacy network buddy changed.
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
		/// \param buddyName Name of legacy network buddy. (eg. "user2@gmail.com")
 
		/// \param alias Alias of legacy network buddy. If empty, then it's not changed on XMPP side.
 
		/// \param groups Groups in which buddy currently is. If empty, then it's not changed on XMPP side.
 
		/// \param status Status of this buddy.
 
		/// \param statusMessage Status message of this buddy.
 
		/// \param iconHash MD5 hash of buddy icon. Empty if none buddy icon.
 
		/// \param blocked True if this buddy is blocked in privacy lists in legacy network.
 
		void handleBuddyChanged(const std::string &user, const std::string &buddyName, const std::string &alias,
 
			const std::vector<std::string> &groups, pbnetwork::StatusType status, const std::string &statusMessage = "", const std::string &iconHash = "",
 
			bool blocked = false
 
		);
 

	
 
		/// Call this method when buddy is removed from legacy network contact list.
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
		/// \param buddyName Name of legacy network buddy. (eg. "user2@gmail.com")
 
		void handleBuddyRemoved(const std::string &user, const std::string &buddyName);
 

	
 
		/// Call this function when participant in room changed.
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
		/// \param nickname Nickname of participant. If participant renamed, this is old name of participant. (eg. "HanzZ")
 
		/// \param room Room in which participant changed. (eg. #spectrum)
 
		/// \param flags Participant flags.
 
		/// \param status Current status of participant. Swift::StatusShow::None if participant left the room.
 
		/// \param statusMessage Current status message of participant.
 
		/// \param newname New name of participant if he changed the nickname. Otherwise empty.
 
		void handleParticipantChanged(const std::string &user, const std::string &nickname, const std::string &room, int flags,
 
			pbnetwork::StatusType = pbnetwork::STATUS_NONE, const std::string &statusMessage = "", const std::string &newname = "",
 
			const std::string &alias = "");
 

	
 
		/// Call this function when user disconnected the legacy network because of some legacy network error.
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
		/// \param error Reserved for future use, currently keep it on 0.
 
		/// \param message XMPP message which is sent to XMPP user.
 
		void handleDisconnected(const std::string &user, int error = 0, const std::string &message = "");
 

	
 
		/// Call this function when user connected the legacy network and is logged in.
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
		void handleConnected(const std::string &user);
 

	
 
		/// Call this function when new message is received from legacy network for user.
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
		/// \param legacyName Name of legacy network buddy or name of room. (eg. "user2@gmail.com")
 
		/// \param message Plain text message.
 
		/// \param nickname Nickname of buddy in room. Empty if it's normal chat message.
 
		/// \param xhtml XHTML message.
 
		void handleMessage(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &nickname = "", const std::string &xhtml = "", const std::string &timestamp = "", bool headline = false, bool pm = false);
 
		/// \param carbon If set, the message is a carbon copy of our own message, sent in a different legacy network client. The message should be treated as sent FROM us, not TO us.
 
		void handleMessage(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &nickname = "", const std::string &xhtml = "", const std::string &timestamp = "", bool headline = false, bool pm = false, bool carbon = false);
 

	
 
		void handleMessageAck(const std::string &user, const std::string &legacyName, const std::string &id);
 

	
 
		/// Call this function when subject in room changed.
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
		/// \param legacyName Name of room. (eg. "#spectrum")
 
		/// \param message Subject message.
 
		/// \param nickname Nickname of user who changed subject.
 
		void handleSubject(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &nickname = "");
 

	
 
		/// Call this function XMPP user's nickname changed.
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
		/// \param room Room in which participant changed. (eg. #spectrum)
 
		/// \param nickname New nickname.
 
		void handleRoomNicknameChanged(const std::string &user, const std::string &room, const std::string &nickname);
 

	
 
		/// Call this function when requested VCard arrived.
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
		/// \param id VCard ID.
 
		/// \param legacyName Name of legacy network buddy. (eg. "user2@gmail.com")
 
		/// \param fullName Name of legacy network buddy. (eg. "Monty Python")
 
		/// \param nickname Nickname.
 
		/// \param photo Raw photo.
 
		void handleVCard(const std::string &user, unsigned int id, const std::string &legacyName, const std::string &fullName, const std::string &nickname, const std::string &photo);
 

	
 
		/// Call this function when buddy started typing.
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
		/// \param buddyName Name of legacy network buddy. (eg. "user2@gmail.com")
 
		void handleBuddyTyping(const std::string &user, const std::string &buddyName);
 

	
 
		/// Call this function when buddy typed, but is not typing anymore.
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
		/// \param buddyName Name of legacy network buddy. (eg. "user2@gmail.com")
 
		void handleBuddyTyped(const std::string &user, const std::string &buddyName);
 

	
 
		/// Call this function when buddy has been typing, but paused for a while.
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
		/// \param buddyName Name of legacy network buddy. (eg. "user2@gmail.com")
 
		void handleBuddyStoppedTyping(const std::string &user, const std::string &buddyName);
 

	
 
		/// Call this function when new authorization request arrived form legacy network
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
		/// \param buddyName Name of legacy network buddy. (eg. "user2@gmail.com")
 
		void handleAuthorization(const std::string &user, const std::string &buddyName);
 

	
 
		/// Call this function when attention request arrived from legacy network.
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
		/// \param buddyName Name of legacy network buddy. (eg. "user2@gmail.com")
include/transport/protocol.proto
Show inline comments
 
@@ -32,96 +32,97 @@ enum StatusType {
 

	
 
message Connected {
 
	required string user = 1;
 
}
 

	
 
message Disconnected {
 
	required string user = 1;
 
	required int32 error = 2;
 
	optional string message = 3;
 
}
 

	
 
message Login {
 
	required string user = 1;
 
	required string legacyName = 2;
 
	required string password = 3;
 
	repeated string extraFields = 4;
 
}
 

	
 
message Logout {
 
	required string user = 1;
 
	required string legacyName = 2;
 
}
 

	
 
message Buddy {
 
	required string userName = 1;
 
	required string buddyName = 2;
 
	optional string alias = 3;
 
	repeated string group = 4;
 
	optional StatusType status = 5;
 
	optional string statusMessage = 6;
 
	optional string iconHash = 7;
 
	optional bool blocked = 8;
 
}
 

	
 
message Buddies {
 
	repeated Buddy buddy = 1;
 
}
 

	
 
message ConversationMessage {
 
	required string userName = 1;
 
	required string buddyName = 2;
 
	required string message = 3;
 
	optional string nickname = 4;
 
	optional string xhtml = 5;
 
	optional string timestamp = 6;
 
	optional bool headline = 7;
 
	optional string id = 8;
 
	optional bool pm = 9;
 
	optional bool carbon = 10;
 
}
 

	
 
message Room {
 
	required string userName = 1;
 
	required string nickname = 2;
 
	required string room = 3;
 
	optional string password = 4;
 
}
 

	
 
message RoomList {
 
	repeated string room = 1;
 
	repeated string name = 2;
 
	optional string user = 3;
 
}
 

	
 
enum ParticipantFlag {
 
	PARTICIPANT_FLAG_NONE = 0;
 
	PARTICIPANT_FLAG_MODERATOR = 1;
 
	PARTICIPANT_FLAG_CONFLICT = 2;
 
	PARTICIPANT_FLAG_BANNED = 4;
 
	PARTICIPANT_FLAG_NOT_AUTHORIZED = 8;
 
	PARTICIPANT_FLAG_ME = 16;
 
	PARTICIPANT_FLAG_KICKED = 32;
 
	PARTICIPANT_FLAG_ROOM_NOT_FOUND = 64;
 
}
 

	
 
message Participant {
 
	required string userName = 1;
 
	required string room = 2;
 
	required string nickname = 3;
 
	required int32 flag = 4;
 
	required StatusType status = 5;
 
	optional string statusMessage = 6;
 
	optional string newname = 7;
 
	optional string iconHash = 8;
 
	optional string alias = 9;
 
}
 

	
 
message VCard {
 
	required string userName = 1;
 
	required string buddyName = 2;
 
	required int32 id = 3;
 
	optional string fullname = 4;
 
	optional string nickname = 5;
 
	optional bytes photo = 6;
 
}
 

	
 
message Status {
libtransport/Conversation.cpp
Show inline comments
 
/**
 
 * XMPP - libpurple transport
 
 *
 
 * Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
 
 *
 
 * 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 <iostream>
 
#include "transport/Conversation.h"
 
#include "transport/ConversationManager.h"
 
#include "transport/User.h"
 
#include "transport/Transport.h"
 
#include "transport/Buddy.h"
 
#include "transport/PresenceOracle.h"
 
#include "transport/RosterManager.h"
 
#include "transport/Frontend.h"
 
#include "transport/Config.h"
 
#include "transport/Logging.h"
 

	
 
#include "Swiften/Elements/MUCItem.h"
 
#include "Swiften/Elements/MUCOccupant.h"
 
#include "Swiften/Elements/MUCUserPayload.h"
 
#include "Swiften/Elements/Delay.h"
 
#include "Swiften/Elements/MUCPayload.h"
 
#include "Swiften/Elements/Presence.h"
 
#include "Swiften/Elements/VCardUpdate.h"
 

	
 
#include "Swiften/SwiftenCompat.h"
 
#ifdef SWIFTEN_SUPPORTS_CARBONS
 
#include "Swiften/Elements/CarbonsSent.h"
 
#include "Swiften/Elements/Forwarded.h"
 
#include "Swiften/Elements/HintPayload.h"
 
#endif
 

	
 
#ifdef SWIFTEN_SUPPORTS_PRIVILEGE
 
#include "Swiften/Elements/Privilege.h"
 
#endif
 

	
 
namespace Transport {
 
	
 
DEFINE_LOGGER(logger, "Conversation");
 

	
 
Conversation::Conversation(ConversationManager *conversationManager, const std::string &legacyName, bool isMUC) : m_conversationManager(conversationManager) {
 
	m_legacyName = legacyName;
 
	m_muc = isMUC;
 
	m_jid = m_conversationManager->getUser()->getJID().toBare();
 
	m_sentInitialPresence = false;
 
	m_nicknameChanged = false;
 
	m_mucEscaping = false;
 
	m_sentInitialSubject = false;
 

	
 
	if (CONFIG_BOOL_DEFAULTED(conversationManager->getComponent()->getConfig(), "features.rawxml", false)) {
 
		m_sentInitialPresence = true;
 
	}
 
}
 

	
 
Conversation::~Conversation() {
 
}
 

	
 
void Conversation::setMUCEscaping(bool mucEscaping) {
 
	LOG4CXX_INFO(logger, m_jid.toString() << ": Setting MUC escaping to " << mucEscaping);
 
	m_mucEscaping = mucEscaping;
 
}
 

	
 
void Conversation::destroyRoom() {
 
	if (m_muc) {
 
		Swift::Presence::ref presence = Swift::Presence::create();
 
		std::string legacyName = m_legacyName;
 
		if (!m_mucEscaping && legacyName.find_last_of("@") != std::string::npos) {
 
			legacyName.replace(legacyName.find_last_of("@"), 1, "%"); // OK
 
		}
 
		legacyName = Swift::JID::getEscapedNode(legacyName);
 
		presence->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), m_nickname));
 
		presence->setType(Swift::Presence::Unavailable);
 

	
 
		Swift::MUCItem item;
 
		item.affiliation = Swift::MUCOccupant::NoAffiliation;
 
		item.role = Swift::MUCOccupant::NoRole;
 
		item.actor = "Transport";
 
		item.reason = "Spectrum 2 transport is being shut down.";
 
		Swift::MUCUserPayload *p = new Swift::MUCUserPayload ();
 
		p->addItem(item);
 

	
 
		Swift::MUCUserPayload::StatusCode c;
 
		c.code = 332;
 
		p->addStatusCode(c);
 
@@ -100,175 +113,270 @@ void Conversation::setRoom(const std::string &room) {
 
	m_room = room;
 
	m_legacyName = m_room + "/" + m_legacyName;
 
}
 

	
 
void Conversation::cacheMessage(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> &message) {
 
	boost::posix_time::ptime timestamp = boost::posix_time::second_clock::universal_time();
 
	SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Delay> delay(SWIFTEN_SHRPTR_NAMESPACE::make_shared<Swift::Delay>());
 
	delay->setStamp(timestamp);
 
	message->addPayload(delay);
 
	m_cachedMessages.push_back(message);
 
	if (m_cachedMessages.size() > 100) {
 
		m_cachedMessages.pop_front();
 
	}
 
}
 

	
 
void Conversation::handleRawMessage(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> &message) {
 
	if (message->getType() != Swift::Message::Groupchat) {
 
		if (m_conversationManager->getComponent()->inServerMode() && m_conversationManager->getUser()->shouldCacheMessages()) {
 
			cacheMessage(message);
 
		}
 
		else {
 
			m_conversationManager->getComponent()->getFrontend()->sendMessage(message);
 
		}
 
	}
 
	else {
 
		if (m_jids.empty()) {
 
			cacheMessage(message);
 
		}
 
		else {
 
			BOOST_FOREACH(const Swift::JID &jid, m_jids) {
 
				message->setTo(jid);
 
				// Subject has to be sent after our own presence (the one with code 110)
 
				if (!message->getSubject().empty()) {
 
					m_subject = message;
 
					if (m_sentInitialPresence == false) {
 
						LOG4CXX_INFO(logger, m_jid.toString() << ": Caching subject message, initial presence not sent yet.");
 
						return;
 
					}
 
					else {
 
						LOG4CXX_INFO(logger, m_jid.toString() << ": Forwarding subject message.");
 
					}
 
				}
 
				m_conversationManager->getComponent()->getFrontend()->sendMessage(message);
 
			}
 
		}
 
	}
 
}
 

	
 
void Conversation::handleMessage(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> &message, const std::string &nickname) {
 
void Conversation::handleMessage(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> &message, const std::string &nickname, const bool carbon) {
 
	if (m_muc) {
 
		message->setType(Swift::Message::Groupchat);
 
	}
 
	else {
 
		if (message->getType() == Swift::Message::Headline) {
 
			if (m_conversationManager->getUser()->getUserSetting("send_headlines") != "1") {
 
				message->setType(Swift::Message::Chat);
 
			}
 
		}
 
		else {
 
			message->setType(Swift::Message::Chat);
 
		}
 
	}
 

	
 
	std::string n = nickname;
 
	if (n.empty() && !m_room.empty() && !m_muc) {
 
		n = m_nickname;
 
	}
 

	
 
	if (message->getType() != Swift::Message::Groupchat) {
 
		message->setTo(m_jid);
 
		// normal message
 
		if (n.empty()) {
 
			Buddy *buddy = m_conversationManager->getUser()->getRosterManager()->getBuddy(m_legacyName);
 
			if (buddy) {
 
				message->setFrom(buddy->getJID());
 
			}
 
			else {
 
				std::string name = m_legacyName;
 
				if (CONFIG_BOOL_DEFAULTED(m_conversationManager->getComponent()->getConfig(), "service.jid_escaping", true)) {
 
					name = Swift::JID::getEscapedNode(m_legacyName);
 
				}
 
				else {
 
					if (name.find_last_of("@") != std::string::npos) {
 
						name.replace(name.find_last_of("@"), 1, "%");
 
					}
 
				}
 

	
 
				message->setFrom(Swift::JID(name, m_conversationManager->getComponent()->getJID().toBare(), "bot"));
 
			}
 
		}
 
		// PM message
 
		else {
 
			if (m_room.empty()) {
 
				message->setFrom(Swift::JID(n, m_conversationManager->getComponent()->getJID().toBare(), "user"));
 
			}
 
			else {
 
				std::string legacyName = m_room;
 
				if (!m_mucEscaping && legacyName.find_last_of("@") != std::string::npos) {
 
					legacyName.replace(legacyName.find_last_of("@"), 1, "%"); // OK
 
				}
 
				legacyName = Swift::JID::getEscapedNode(legacyName);
 
				message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), n));
 
			}
 
		}
 
	}
 
	else {
 
		std::string legacyName = m_legacyName;
 
		if (!m_mucEscaping && legacyName.find_last_of("@") != std::string::npos) {
 
			legacyName.replace(legacyName.find_last_of("@"), 1, "%"); // OK
 
		}
 
		legacyName = Swift::JID::getEscapedNode(legacyName);
 

	
 
		std::string n = nickname;
 
		if (n.empty()) {
 
			n = " ";
 
		}
 

	
 
		std::map<std::string, Participant>::iterator it = m_participants.find(n);
 
		if (it != m_participants.end() && !it->second.alias.empty()) {
 
			n = it->second.alias;
 
		}
 

	
 
		message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), n));
 
		LOG4CXX_INFO(logger, "MSG FROM " << message->getFrom().toString());
 
	}
 

	
 

	
 
	if (carbon) {
 
#ifdef SWIFTEN_SUPPORTS_CARBONS
 
		LOG4CXX_INFO(logger, "CARBON MSG");
 
		//Swap from and to
 
		Swift::JID from = message->getFrom();
 
		message->setFrom(message->getTo());
 
		message->setTo(from);
 

	
 
		//Carbons should be sent to every resource directly.
 
		//Even if we tried to send to bare jid, the server would at best route it
 
		//as it would normal message (usually to the highest priority resource),
 
		//but won't produce carbons to other resources as it does with normal messages.
 
		Component* transport = this->getConversationManager()->getComponent();
 
		std::vector<Swift::Presence::ref> presences = transport->getPresenceOracle()->getAllPresence(this->m_jid.toBare());
 
		if (presences.empty()) {
 
			LOG4CXX_INFO(logger, "No presences for JID " << this->m_jid.toString()
 
			    << ", will send to bare JID for archival.");
 
			this->forwardAsCarbonSent(message, this->m_jid.toBare());
 
		} else
 
		BOOST_FOREACH(const Swift::Presence::ref &it, presences) {
 
			this->forwardAsCarbonSent(message, it->getFrom());
 
		}
 
#else //!SWIFTEN_SUPPORTS_CARBONS
 
		//Ignore the message.
 
#endif
 
	} else {
 
		handleRawMessage(message);
 
	}
 
}
 

	
 
void Conversation::forwardAsCarbonSent(
 
	const SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> &payload,
 
	const Swift::JID& to)
 
{
 
#ifdef SWIFTEN_SUPPORTS_CARBONS
 
	LOG4CXX_INFO(logger, "Carbon <sent> to -> " << to.toString());
 

	
 
	//Message envelope
 
	SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> message(new Swift::Message());
 

	
 
	//Type MUST be equal to the original message type
 
	message->setType(payload->getType());
 

	
 
	//XEP-0280 docs say "from" MUST be the carbon subscriber's JID,
 
	//so a transport will need to wrap this in another <privilege> wrapper.
 
	message->setFrom(m_jid.toBare());
 
	message->setTo(to);
 

	
 
	//Wrap the payload in a <sent><forwarded>
 
	SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Forwarded> forwarded(new Swift::Forwarded());
 
	forwarded->setStanza(payload);
 
	SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::CarbonsSent> sent(new Swift::CarbonsSent());
 
	sent->setForwarded(forwarded);
 
	message->addPayload(sent);
 

	
 
	//Add no-copy to prevent some servers from creating carbons of carbons
 
	Swift::HintPayload::ref noCopy(new Swift::HintPayload(Swift::HintPayload::NoCopy));
 
	message->addPayload(noCopy);
 

	
 
	this->forwardImpersonated(message, Swift::JID("", message->getFrom().getDomain()));
 
#else
 
	//We cannot send the carbon.
 
#endif
 
}
 

	
 
//Generates a XEP-0356 privilege wrapper asking to impersonate a user from a given domain
 
void Conversation::forwardImpersonated(
 
	SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> payload,
 
	const Swift::JID& server)
 
{
 
#ifdef SWIFTEN_SUPPORTS_PRIVILEGE
 
	LOG4CXX_INFO(logger, "Impersonate to -> " << server.toString());
 
	Component* transport = this->getConversationManager()->getComponent();
 

	
 
	//Message envelope
 
	SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> message(new Swift::Message());
 
	// "from" MUST be our bare jid
 
	message->setFrom(transport->getJID());
 
	// "to" MUST be the bare jid of the server we're asking to impersonate
 
	message->setTo(server);
 
	message->setType(Swift::Message::Normal);
 

	
 
	SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Forwarded> forwarded(new Swift::Forwarded());
 
	forwarded->setStanza(payload);
 
	
 
	Swift::Privilege::ref privilege(new Swift::Privilege());
 
	privilege->setForwarded(forwarded);
 

	
 
	message->addPayload(privilege);
 
	LOG4CXX_INFO(logger, "Impersonate: sending message");
 
	handleRawMessage(message);
 
#else
 
	//Try to send the message as is -- some servers can be configured to accept this
 
	handleRawMessage(payload);
 
#endif
 
}
 

	
 
std::string Conversation::getParticipants() {
 
	std::string ret;
 
	for (std::map<std::string, Participant>::iterator it = m_participants.begin(); it != m_participants.end(); it++) {
 
		ret += (*it).second.presence->getFrom().getResource() + ", ";
 
	}
 
	return ret;
 
}
 

	
 
void Conversation::sendParticipants(const Swift::JID &to, const std::string &nickname) {
 
	// When user tries to join this room from another resource using
 
	// different nickname than the original one has, we have to rename
 
	// him.
 
	LOG4CXX_INFO(logger, m_jid.toString() << ": Sending participants to " << to.toString() << ", Nickname:" << nickname << ", Conversation nickname:" << m_nickname);
 
	if (m_nickname != nickname && !nickname.empty()) {
 
		Swift::Presence::ref presence;
 
		std::string tmp = m_nickname;
 

	
 
		// At first connect the user.
 
		m_nickname = nickname;
 
		presence = generatePresence(nickname, 0, (int) Swift::StatusShow::Online, "", "", "");
 
		presence->setTo(to);
 
		m_conversationManager->getComponent()->getFrontend()->sendPresence(presence);
 

	
 
		// Now change his nickname to the right one.
 
		m_nicknameChanged = true;
 
		presence = generatePresence(nickname, 0, (int) Swift::StatusShow::Online, "", tmp, "");
 
		presence->setTo(to);
 
		m_conversationManager->getComponent()->getFrontend()->sendPresence(presence);
 

	
 
	}
 

	
 
	// Self presence has to be sent as first.
 
	Swift::Presence::ref presence = generatePresence(m_nickname, 0, (int) Swift::StatusShow::Online, "", "", "");
 
	presence->setTo(to);
 
	m_conversationManager->getComponent()->getFrontend()->sendPresence(presence);
 

	
 
	for (std::map<std::string, Participant>::iterator it = m_participants.begin(); it != m_participants.end(); it++) {
 
		(*it).second.presence->setTo(to);
 
		m_conversationManager->getComponent()->getFrontend()->sendPresence((*it).second.presence);
 
	}
 
}
 

	
 
void Conversation::sendCachedMessages(const Swift::JID &to) {
 
	for (std::list<SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> >::const_iterator it = m_cachedMessages.begin(); it != m_cachedMessages.end(); it++) {
 
		if (to.isValid()) {
 
			(*it)->setTo(to);
libtransport/NetworkPluginServer.cpp
Show inline comments
 
@@ -689,99 +689,98 @@ void NetworkPluginServer::handleConvMessagePayload(const std::string &data, bool
 
	}
 

	
 
    wrapIncomingImage(msg.get(), payload);
 

	
 
	if (payload.headline()) {
 
		msg->setType(Swift::Message::Headline);
 
	}
 

	
 
	// Add xhtml-im payload.
 
	if (CONFIG_BOOL(m_config, "service.enable_xhtml") && !payload.xhtml().empty()) {
 
		msg->addPayload(SWIFTEN_SHRPTR_NAMESPACE::make_shared<Swift::XHTMLIMPayload>(payload.xhtml()));
 
	}
 

	
 
	if (!payload.timestamp().empty()) {
 
		boost::posix_time::ptime timestamp = boost::posix_time::from_iso_string(payload.timestamp());
 
		SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Delay> delay(SWIFTEN_SHRPTR_NAMESPACE::make_shared<Swift::Delay>());
 
		delay->setStamp(timestamp);
 
		msg->addPayload(delay);
 
	}
 

	
 
	NetworkConversation *conv = (NetworkConversation *) user->getConversationManager()->getConversation(payload.buddyname());
 

	
 
	// We can't create Conversation for payload with nickname, because this means the message is from room,
 
	// but this user is not in any room, so it's OK to just reject this message
 
	if (!conv && !payload.nickname().empty()) {
 
		LOG4CXX_WARN(logger, "handleConvMessagePayload: No conversation with name " << payload.buddyname());
 
		return;
 
	}
 

	
 
	if (conv && payload.pm()) {
 
		conv = (NetworkConversation *) user->getConversationManager()->getConversation(payload.buddyname() + "/" + payload.nickname());
 
		if (!conv) {
 
			conv = new NetworkConversation(user->getConversationManager(), payload.nickname());
 
			std::string name = payload.buddyname();
 
			conv->setRoom(name);
 
			conv->setNickname(payload.buddyname() + "/" + payload.nickname());
 

	
 
			user->getConversationManager()->addConversation(conv);
 
			conv->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, this, _1, _2));
 
		}
 
	}
 

	
 
	// Create new Conversation if it does not exist
 
	if (!conv) {
 
		conv = new NetworkConversation(user->getConversationManager(), payload.buddyname());
 
		user->getConversationManager()->addConversation(conv);
 
		conv->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, this, _1, _2));
 
	}
 

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

	
 
void NetworkPluginServer::handleConvMessageAckPayload(const std::string &data) {
 
	pbnetwork::ConversationMessage payload;
 

	
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 

	
 
	User *user = m_userManager->getUser(payload.username());
 
	if (!user)
 
		return;
 

	
 
	if (payload.id().empty()) {
 
		LOG4CXX_WARN(logger, "Received message ack with empty ID, not forwarding to XMPP.");
 
		return;
 
	}
 

	
 
	SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> msg(new Swift::Message());
 
	msg->addPayload(SWIFTEN_SHRPTR_NAMESPACE::make_shared<Swift::DeliveryReceipt>(payload.id()));
 

	
 
	NetworkConversation *conv = (NetworkConversation *) user->getConversationManager()->getConversation(payload.buddyname());
 

	
 
	// Receipts don't create conversation
 
	if (!conv) {
 
		return;
 
	}
 

	
 
	// Forward it
 
	conv->handleMessage(msg);
 
}
 

	
 
void NetworkPluginServer::handleAttentionPayload(const std::string &data) {
 
	pbnetwork::ConversationMessage payload;
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 

	
 
	User *user = m_userManager->getUser(payload.username());
 
	if (!user)
 
		return;
 

	
 
	SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> msg(new Swift::Message());
 
	msg->setBody(payload.message());
 
	msg->addPayload(SWIFTEN_SHRPTR_NAMESPACE::make_shared<Swift::AttentionPayload>());
plugin/cpp/networkplugin.cpp
Show inline comments
 
@@ -49,106 +49,107 @@ template <class T> std::string stringOf(T object) {
 
	os << object;
 
	return (os.str());
 
}
 

	
 
NetworkPlugin::NetworkPlugin() {
 
	m_pingReceived = false;
 

	
 
	double shared;
 
#ifndef WIN32
 
	process_mem_usage(shared, m_init_res);
 
#endif
 
}
 

	
 
NetworkPlugin::~NetworkPlugin() {
 
}
 

	
 
void NetworkPlugin::sendConfig(const PluginConfig &cfg) {
 
	std::string data = "[registration]\n";
 
	data += std::string("needPassword=") + (cfg.m_needPassword ? "1" : "0") + "\n";
 
	data += std::string("needRegistration=") + (cfg.m_needRegistration ? "1" : "0") + "\n";
 

	
 
	for (std::vector<std::string>::const_iterator it = cfg.m_extraFields.begin(); it != cfg.m_extraFields.end(); it++) {
 
		data += std::string("extraField=") + (*it) + "\n";
 
	}
 

	
 
	data += "[features]\n";
 
	data += std::string("muc=") + (cfg.m_supportMUC ? "1" : "0") + "\n";
 
	data += std::string("rawxml=") + (cfg.m_rawXML ? "1" : "0") + "\n";
 
	data += std::string("disable_jid_escaping=") + (cfg.m_disableJIDEscaping ? "1" : "0") + "\n";
 
	
 

	
 
	pbnetwork::BackendConfig m;
 
	m.set_config(data);
 

	
 
	std::string message;
 
	m.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_BACKEND_CONFIG);
 

	
 
	send(message);
 
}
 

	
 
void NetworkPlugin::sendRawXML(std::string &xml) {
 
	WRAP(xml, pbnetwork::WrapperMessage_Type_TYPE_RAW_XML);
 

	
 
	send(xml);
 
}
 

	
 
void NetworkPlugin::handleMessage(const std::string &user, const std::string &legacyName, const std::string &msg, const std::string &nickname, const std::string &xhtml, const std::string &timestamp, bool headline, bool pm) {
 
void NetworkPlugin::handleMessage(const std::string &user, const std::string &legacyName, const std::string &msg, const std::string &nickname, const std::string &xhtml, const std::string &timestamp, bool headline, bool pm, bool carbon) {
 
	pbnetwork::ConversationMessage m;
 
	m.set_username(user);
 
	m.set_buddyname(legacyName);
 
	m.set_message(msg);
 
	m.set_nickname(nickname);
 
	m.set_xhtml(xhtml);
 
	m.set_timestamp(timestamp);
 
	m.set_headline(headline);
 
	m.set_pm(pm);
 
	m.set_carbon(carbon);
 

	
 
	std::string message;
 
	m.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_CONV_MESSAGE);
 

	
 
	send(message);
 
}
 

	
 
void NetworkPlugin::handleMessageAck(const std::string &user, const std::string &legacyName, const std::string &id) {
 
	pbnetwork::ConversationMessage m;
 
	m.set_username(user);
 
	m.set_buddyname(legacyName);
 
	m.set_message("");
 
	m.set_id(id);
 

	
 
	std::string message;
 
	m.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_CONV_MESSAGE_ACK);
 

	
 
	send(message);
 
}
 

	
 
void NetworkPlugin::handleAttention(const std::string &user, const std::string &buddyName, const std::string &msg) {
 
	pbnetwork::ConversationMessage m;
 
	m.set_username(user);
 
	m.set_buddyname(buddyName);
 
	m.set_message(msg);
 

	
 
	std::string message;
 
	m.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_ATTENTION);
 

	
 
	send(message);
 
}
 

	
 
void NetworkPlugin::handleVCard(const std::string &user, unsigned int id, const std::string &legacyName, const std::string &fullName, const std::string &nickname, const std::string &photo) {
 
	pbnetwork::VCard vcard;
 
	vcard.set_username(user);
 
	vcard.set_buddyname(legacyName);
 
	vcard.set_id(id);
 
	vcard.set_fullname(fullName);
 
	vcard.set_nickname(nickname);
 
	vcard.set_photo(photo);
 

	
 
	std::string message;
spectrum/src/frontends/xmpp/XMPPFrontend.cpp
Show inline comments
 
/**
 
 * 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 "XMPPFrontend.h"
 
#include "XMPPRosterManager.h"
 
#include "XMPPUser.h"
 
#include "XMPPUserManager.h"
 
#include <boost/bind.hpp>
 
#include <boost/smart_ptr/make_shared.hpp>
 
#include <boost/algorithm/string/predicate.hpp>
 
#include "transport/StorageBackend.h"
 
#include "transport/Factory.h"
 
#include "transport/UserRegistry.h"
 
#include "transport/Logging.h"
 
#include "transport/Config.h"
 
#include "transport/Transport.h"
 
#include "storageparser.h"
 
#include "Swiften/SwiftenCompat.h"
 
#ifdef _WIN32
 
#include <Swiften/TLS/CAPICertificate.h>
 
#include "Swiften/TLS/Schannel/SchannelServerContext.h"
 
#include "Swiften/TLS/Schannel/SchannelServerContextFactory.h"
 
#elif defined(__APPLE__) && HAVE_SWIFTEN_3
 
#include <Swiften/TLS/SecureTransport/SecureTransportCertificate.h>
 
#include <Swiften/TLS/SecureTransport/SecureTransportServerContext.h>
 
#else
 
#include "Swiften/TLS/PKCS12Certificate.h"
 
#include "Swiften/TLS/CertificateWithKey.h"
 
#include "Swiften/TLS/OpenSSL/OpenSSLServerContext.h"
 
#include "Swiften/TLS/OpenSSL/OpenSSLServerContextFactory.h"
 
#endif
 
#include "Swiften/Parser/PayloadParsers/AttentionParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/AttentionSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/XHTMLIMParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/XHTMLIMSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/StatsParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/StatsSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/GatewayPayloadParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/GatewayPayloadSerializer.h"
 
#include "Swiften/Serializer/PayloadSerializers/SpectrumErrorSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/MUCPayloadParser.h"
 
#include "BlockParser.h"
 
#include "BlockSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/InvisibleParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/InvisibleSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/HintPayloadParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/HintPayloadSerializer.h"
 
#ifdef SWIFTEN_SUPPORTS_PRIVILEGE
 
#include "Swiften/Parser/PayloadParsers/PrivilegeParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/PrivilegeSerializer.h"
 
#endif
 
#include "Swiften/Parser/GenericPayloadParserFactory.h"
 
#if SWIFTEN_VERSION >= 0x030000
 
#include "Swiften/Parser/GenericPayloadParserFactory2.h"
 
#endif
 
#include "Swiften/Queries/IQRouter.h"
 
#include "Swiften/Elements/RosterPayload.h"
 
#include "discoitemsresponder.h"
 
#include "Swiften/Elements/InBandRegistrationPayload.h"
 

	
 
using namespace Swift;
 

	
 
namespace Transport {
 
	
 
DEFINE_LOGGER(logger, "XMPPFrontend");
 

	
 
XMPPFrontend::XMPPFrontend() {
 
}
 

	
 
class SwiftServerExposed: public Swift::Server
 
{
 
public:
 
	PayloadParserFactoryCollection* getPayloadParserFactories() { return Swift::Server::getPayloadParserFactories(); }
 
	PayloadSerializerCollection* getPayloadSerializers() { return Swift::Server::getPayloadSerializers(); }
 
};
 

	
 
class SwiftComponentExposed: public Swift::Component
 
{
 
public:
 
	PayloadParserFactoryCollection* getPayloadParserFactories() { return Swift::Component::getPayloadParserFactories(); }
 
	PayloadSerializerCollection* getPayloadSerializers() { return Swift::Component::getPayloadSerializers(); }
 
};
 

	
 
void XMPPFrontend::init(Component *transport, Swift::EventLoop *loop, Swift::NetworkFactories *factories, Config *config, Transport::UserRegistry *userRegistry) {
 
	m_transport = transport;
 
	m_component = NULL;
 
	m_server = NULL;
 
	m_rawXML = false;
 
	m_config = transport->getConfig();
 
	m_userManager = NULL;
 
	m_jid = Swift::JID(CONFIG_STRING(m_config, "service.jid"));
 

	
 
	m_config->onBackendConfigUpdated.connect(boost::bind(&XMPPFrontend::handleBackendConfigChanged, this));
 

	
 
	m_parserFactories.push_back(new Swift::GenericPayloadParserFactory<StorageParser>("private", "jabber:iq:private"));
 
	m_parserFactories.push_back(new Swift::GenericPayloadParserFactory<Swift::AttentionParser>("attention", "urn:xmpp:attention:0"));
 
	m_parserFactories.push_back(new Swift::GenericPayloadParserFactory<Swift::XHTMLIMParser>("html", "http://jabber.org/protocol/xhtml-im"));
 
	m_parserFactories.push_back(new Swift::GenericPayloadParserFactory<Transport::BlockParser>("block", "urn:xmpp:block:0"));
 
	m_parserFactories.push_back(new Swift::GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
 
	m_parserFactories.push_back(new Swift::GenericPayloadParserFactory<Swift::StatsParser>("query", "http://jabber.org/protocol/stats"));
 
	m_parserFactories.push_back(new Swift::GenericPayloadParserFactory<Swift::GatewayPayloadParser>("query", "jabber:iq:gateway"));
 
	m_parserFactories.push_back(new Swift::GenericPayloadParserFactory<Swift::MUCPayloadParser>("x", "http://jabber.org/protocol/muc"));
 
	m_parserFactories.push_back(new Swift::GenericPayloadParserFactory<Swift::HintPayloadParser>("no-permanent-store", "urn:xmpp:hints"));
 
	m_parserFactories.push_back(new Swift::GenericPayloadParserFactory<Swift::HintPayloadParser>("no-store", "urn:xmpp:hints"));
 
	m_parserFactories.push_back(new Swift::GenericPayloadParserFactory<Swift::HintPayloadParser>("no-copy", "urn:xmpp:hints"));
 
	m_parserFactories.push_back(new Swift::GenericPayloadParserFactory<Swift::HintPayloadParser>("store", "urn:xmpp:hints"));
 

	
 
	m_payloadSerializers.push_back(new Swift::AttentionSerializer());
 
	m_payloadSerializers.push_back(new Swift::XHTMLIMSerializer());
 
	m_payloadSerializers.push_back(new Transport::BlockSerializer());
 
	m_payloadSerializers.push_back(new Swift::InvisibleSerializer());
 
	m_payloadSerializers.push_back(new Swift::StatsSerializer());
 
	m_payloadSerializers.push_back(new Swift::SpectrumErrorSerializer());
 
	m_payloadSerializers.push_back(new Swift::GatewayPayloadSerializer());
 
	m_payloadSerializers.push_back(new Swift::HintPayloadSerializer());
 

	
 
	if (CONFIG_BOOL(m_config, "service.server_mode")) {
 
		LOG4CXX_INFO(logger, "Creating component in server mode on port " << CONFIG_INT(m_config, "service.port"));
 
		m_server = new Swift::Server(loop, factories, userRegistry, m_jid, CONFIG_STRING(m_config, "service.server"), CONFIG_INT(m_config, "service.port"));
 
		if (!CONFIG_STRING(m_config, "service.cert").empty()) {
 
#ifndef _WIN32
 
#ifndef __APPLE__
 
//TODO: fix
 
			LOG4CXX_INFO(logger, "Using PKCS#12 certificate " << CONFIG_STRING(m_config, "service.cert"));
 
			LOG4CXX_INFO(logger, "SSLv23_server_method used.");
 
			TLSServerContextFactory *f = new OpenSSLServerContextFactory();
 
			CertificateWithKey::ref certificate = SWIFTEN_SHRPTR_NAMESPACE::make_shared<PKCS12Certificate>(CONFIG_STRING(m_config, "service.cert"), createSafeByteArray(CONFIG_STRING(m_config, "service.cert_password")));
 
			m_server->addTLSEncryption(f, certificate);
 
#endif
 
#endif
 
			
 
		}
 
		else {
 
			LOG4CXX_WARN(logger, "No PKCS#12 certificate used. TLS is disabled.");
 
		}
 
// 		m_server->start();
 
		m_stanzaChannel = m_server->getStanzaChannel();
 
		m_iqRouter = m_server->getIQRouter();
 

	
 
		SwiftServerExposed* entity(reinterpret_cast<SwiftServerExposed*>(m_server));
 
#ifdef SWIFTEN_SUPPORTS_PRIVILEGE
 
		m_parserFactories.push_back(new Swift::GenericPayloadParserFactory2<Swift::PrivilegeParser>("privilege", "urn:xmpp:privilege:1", entity->getPayloadParserFactories()));
 
		m_payloadSerializers.push_back(new Swift::PrivilegeSerializer(entity->getPayloadSerializers()));
 
#endif
 

	
 
		BOOST_FOREACH(Swift::PayloadParserFactory *factory, m_parserFactories) {
 
			m_server->addPayloadParserFactory(factory);
 
		}
 

	
 
		BOOST_FOREACH(Swift::PayloadSerializer *serializer, m_payloadSerializers) {
 
			m_server->addPayloadSerializer(serializer);
 
		}
 

	
 
		m_server->onDataRead.connect(boost::bind(&XMPPFrontend::handleDataRead, this, _1));
 
		m_server->onDataWritten.connect(boost::bind(&XMPPFrontend::handleDataWritten, this, _1));
 
	}
 
	else {
 
		LOG4CXX_INFO(logger, "Creating component in gateway mode");
 
#if HAVE_SWIFTEN_3
 
		m_component = new Swift::Component(m_jid, CONFIG_STRING(m_config, "service.password"), factories);
 
#else
 
		m_component = new Swift::Component(loop, factories, m_jid, CONFIG_STRING(m_config, "service.password"));
 
#endif
 
		m_component->setSoftwareVersion("Spectrum", SPECTRUM_VERSION);
 
		m_component->onConnected.connect(boost::bind(&XMPPFrontend::handleConnected, this));
 
		m_component->onError.connect(boost::bind(&XMPPFrontend::handleConnectionError, this, _1));
 
		m_component->onDataRead.connect(boost::bind(&XMPPFrontend::handleDataRead, this, _1));
 
		m_component->onDataWritten.connect(boost::bind(&XMPPFrontend::handleDataWritten, this, _1));
 

	
 
		SwiftComponentExposed* entity(reinterpret_cast<SwiftComponentExposed*>(m_component));
 
#ifdef SWIFTEN_SUPPORTS_PRIVILEGE
 
		m_parserFactories.push_back(new Swift::GenericPayloadParserFactory2<Swift::PrivilegeParser>("privilege", "urn:xmpp:privilege:1", entity->getPayloadParserFactories()));
 
		m_payloadSerializers.push_back(new Swift::PrivilegeSerializer(entity->getPayloadSerializers()));
 
#endif
 

	
 
		BOOST_FOREACH(Swift::PayloadParserFactory *factory, m_parserFactories) {
 
			m_component->addPayloadParserFactory(factory);
 
		}
 

	
 
		BOOST_FOREACH(Swift::PayloadSerializer *serializer, m_payloadSerializers) {
 
			m_component->addPayloadSerializer(serializer);
 
		}
 

	
 
		m_stanzaChannel = m_component->getStanzaChannel();
 
		m_iqRouter = m_component->getIQRouter();
 
	}
 

	
 

	
 
	m_capsMemoryStorage = new CapsMemoryStorage();
 
#if HAVE_SWIFTEN_3
 
	m_capsManager = new CapsManager(m_capsMemoryStorage, m_stanzaChannel, m_iqRouter, factories->getCryptoProvider());
 
#else
 
	m_capsManager = new CapsManager(m_capsMemoryStorage, m_stanzaChannel, m_iqRouter);
 
#endif
 
	m_entityCapsManager = new EntityCapsManager(m_capsManager, m_stanzaChannel);
 
	m_entityCapsManager->onCapsChanged.connect(boost::bind(&XMPPFrontend::handleCapsChanged, this, _1));
 

	
 
	m_stanzaChannel->onPresenceReceived.connect(bind(&XMPPFrontend::handleGeneralPresence, this, _1));
 
	m_stanzaChannel->onMessageReceived.connect(bind(&XMPPFrontend::handleMessage, this, _1));
 
}
 

	
 
XMPPFrontend::~XMPPFrontend() {
 
	delete m_entityCapsManager;
 
	delete m_capsManager;
 
	delete m_capsMemoryStorage;
 
	if (m_component)
 
		delete m_component;
 
	if (m_server) {
 
		m_server->stop();
 
		delete m_server;
 
	}
 

	
 
	BOOST_FOREACH(Swift::PayloadParserFactory *factory, m_parserFactories) {
 
		delete factory;
 
	}
 
	m_parserFactories.clear();
 

	
 
	BOOST_FOREACH(Swift::PayloadSerializer *serializer, m_payloadSerializers) {
 
		delete serializer;
 
	}
 
	m_payloadSerializers.clear();
 
}
 

	
 
void XMPPFrontend::handleGeneralPresence(Swift::Presence::ref presence) {
 
	onPresenceReceived(presence);
 
}
 

	
 
void XMPPFrontend::handleMessage(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> message) {
 
	onMessageReceived(message);
 
}
 

	
 

	
 
void XMPPFrontend::clearRoomList() {
 
	static_cast<XMPPUserManager *>(m_userManager)->getDiscoItemsResponder()->clearRooms();
 
}
 

	
tests/libtransport/basictest.cpp
Show inline comments
 
#include "basictest.h"
 
#include "XMPPFrontend.h"
 
#include "XMPPUserRegistration.h"
 
#include "XMPPUserManager.h"
 
#include <cppunit/TestFixture.h>
 
#include <cppunit/extensions/HelperMacros.h>
 
#include <Swiften/Version.h>
 
#include <Swiften/Swiften.h>
 
#include <Swiften/EventLoop/DummyEventLoop.h>
 
#include <Swiften/Server/Server.h>
 
#include <Swiften/Network/DummyNetworkFactories.h>
 
#include <Swiften/Network/DummyConnectionServer.h>
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
 

	
 
#include "Swiften/Serializer/GenericPayloadSerializer.h"
 
#include "Swiften/Parser/GenericPayloadParserFactory.h"
 
#if SWIFTEN_VERSION >= 0x030000
 
#include "Swiften/Parser/GenericPayloadParserFactory2.h"
 
#endif
 

	
 
#include "storageparser.h"
 
#include "Swiften/Parser/PayloadParsers/AttentionParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/AttentionSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/XHTMLIMParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/XHTMLIMSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/StatsParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/StatsSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/GatewayPayloadParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/GatewayPayloadSerializer.h"
 
#include "Swiften/Serializer/PayloadSerializers/SpectrumErrorSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/MUCPayloadParser.h"
 
#include "BlockParser.h"
 
#include "BlockSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/InvisibleParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/InvisibleSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/HintPayloadParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/HintPayloadSerializer.h"
 
#ifdef SWIFTEN_SUPPORTS_PRIVILEGE
 
#include "Swiften/Parser/PayloadParsers/PrivilegeParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/PrivilegeSerializer.h"
 
#endif
 

	
 
using namespace Transport;
 

	
 
void BasicTest::setMeUp (void) {
 
	streamEnded = false;
 
	std::istringstream ifs("service.server_mode = 1\nservice.jid=localhost\nservice.more_resources=1\nservice.admin_jid=me@localhost\n");
 
	cfg = new Config();
 
	cfg->load(ifs);
 

	
 
	factory = new TestingFactory();
 

	
 
	storage = new TestingStorageBackend();
 

	
 
	loop = new Swift::DummyEventLoop();
 
	factories = new Swift::DummyNetworkFactories(loop);
 

	
 
	userRegistry = new UserRegistry(cfg, factories);
 

	
 
	frontend = new Transport::XMPPFrontend();
 

	
 
	component = new Component(frontend, loop, factories, cfg, factory, userRegistry);
 
	component->start();
 

	
 
	userManager = frontend->createUserManager(component, userRegistry, storage);
 

	
 
	itemsResponder = static_cast<XMPPUserManager *>(userManager)->getDiscoItemsResponder();
 

	
 
	payloadSerializers = new Swift::FullPayloadSerializerCollection();
 
	payloadParserFactories = new Swift::FullPayloadParserFactoryCollection();
 

	
 
	parserFactories.push_back(new Swift::GenericPayloadParserFactory<StorageParser>("private", "jabber:iq:private"));
 
	parserFactories.push_back(new Swift::GenericPayloadParserFactory<Swift::AttentionParser>("attention", "urn:xmpp:attention:0"));
 
	parserFactories.push_back(new Swift::GenericPayloadParserFactory<Swift::XHTMLIMParser>("html", "http://jabber.org/protocol/xhtml-im"));
 
	parserFactories.push_back(new Swift::GenericPayloadParserFactory<Transport::BlockParser>("block", "urn:xmpp:block:0"));
 
	parserFactories.push_back(new Swift::GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
 
	parserFactories.push_back(new Swift::GenericPayloadParserFactory<Swift::StatsParser>("query", "http://jabber.org/protocol/stats"));
 
	parserFactories.push_back(new Swift::GenericPayloadParserFactory<Swift::GatewayPayloadParser>("query", "jabber:iq:gateway"));
 
	parserFactories.push_back(new Swift::GenericPayloadParserFactory<Swift::MUCPayloadParser>("x", "http://jabber.org/protocol/muc"));
 
	parserFactories.push_back(new Swift::GenericPayloadParserFactory<Swift::HintPayloadParser>("no-permanent-store", "urn:xmpp:hints"));
 
	parserFactories.push_back(new Swift::GenericPayloadParserFactory<Swift::HintPayloadParser>("no-store", "urn:xmpp:hints"));
 
	parserFactories.push_back(new Swift::GenericPayloadParserFactory<Swift::HintPayloadParser>("no-copy", "urn:xmpp:hints"));
 
	parserFactories.push_back(new Swift::GenericPayloadParserFactory<Swift::HintPayloadParser>("store", "urn:xmpp:hints"));
 
#ifdef SWIFTEN_SUPPORTS_PRIVILEGE
 
	parserFactories.push_back(new Swift::GenericPayloadParserFactory2<Swift::PrivilegeParser>("privilege", "urn:xmpp:privilege:1", payloadParserFactories));
 
#endif
 

	
 
	BOOST_FOREACH(Swift::PayloadParserFactory *factory, parserFactories) {
 
		payloadParserFactories->addFactory(factory);
 
	}
 

	
 
	_payloadSerializers.push_back(new Swift::AttentionSerializer());
 
	_payloadSerializers.push_back(new Swift::XHTMLIMSerializer());
 
	_payloadSerializers.push_back(new Transport::BlockSerializer());
 
	_payloadSerializers.push_back(new Swift::InvisibleSerializer());
 
	_payloadSerializers.push_back(new Swift::StatsSerializer());
 
	_payloadSerializers.push_back(new Swift::SpectrumErrorSerializer());
 
	_payloadSerializers.push_back(new Swift::GatewayPayloadSerializer());
 
	_payloadSerializers.push_back(new Swift::HintPayloadSerializer());
 
#ifdef SWIFTEN_SUPPORTS_PRIVILEGE
 
	_payloadSerializers.push_back(new Swift::PrivilegeSerializer(payloadSerializers));
 
#endif
 

	
 
	BOOST_FOREACH(Swift::PayloadSerializer *serializer, _payloadSerializers) {
 
		payloadSerializers->addSerializer(serializer);
 
	}
 

	
 
	parser = new Swift::XMPPParser(this, payloadParserFactories, factories->getXMLParserFactory());
 
	parser2 = new Swift::XMPPParser(this, payloadParserFactories, factories->getXMLParserFactory());
 

	
 
	serverFromClientSession = SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::ServerFromClientSession>(new Swift::ServerFromClientSession("id", factories->getConnectionFactory()->createConnection(),
 
			payloadParserFactories, payloadSerializers, userRegistry, factories->getXMLParserFactory(), Swift::JID("user@localhost/resource")));
 
	serverFromClientSession->startSession();
 

	
 
	serverFromClientSession->onDataWritten.connect(boost::bind(&BasicTest::handleDataReceived, this, _1));
 

	
 
	dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend *>(component->getFrontend())->getStanzaChannel())->addSession(serverFromClientSession);
 
	parser->parse("<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='localhost' version='1.0'>");
 
	parser2->parse("<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='localhost' version='1.0'>");
 
	received.clear();
 
	received2.clear();
 
	receivedData.clear();
 
	loop->processEvents();
 
}
 

	
 
void BasicTest::tearMeDown (void) {
 
	dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend *>(component->getFrontend())->getStanzaChannel())->removeSession(serverFromClientSession);
 
	if (serverFromClientSession2) {
 
		dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend *>(component->getFrontend())->getStanzaChannel())->removeSession(serverFromClientSession2);
 
		serverFromClientSession2.reset();
 
	}
 
	delete userManager;
 
	delete component;
 
	delete frontend;
 
	delete userRegistry;
 
	delete factories;
 
	delete factory;
 
	delete loop;
 
	delete cfg;
 
	delete parser;
 
	delete parser2;
 
	delete storage;
 
// 	delete userRegistration;
 
	received.clear();
 
	received2.clear();
 
	receivedData.clear();
 
	receivedData2.clear();
 

	
 
	delete payloadParserFactories;
 
	delete payloadSerializers;
0 comments (0 inline, 0 general)