Changeset - 711c1674fe9d
[Not reviewed]
0 7 0
HanzZ - 12 years ago 2013-01-26 15:22:25
hanzz.k@gmail.com
Send 'http://jabber.org/protocol/muc' if MUC is supported by backend
7 files changed with 32 insertions and 13 deletions:
0 comments (0 inline, 0 general)
backends/libcommuni/ircnetworkplugin.cpp
Show inline comments
 
@@ -11,96 +11,97 @@ DEFINE_LOGGER(logger, "IRCNetworkPlugin");
 
IRCNetworkPlugin::IRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port) {
 
	this->config = config;
 
	m_currentServer = 0;
 
	m_firstPing = true;
 
	m_socket = new QTcpSocket();
 
	m_socket->connectToHost(FROM_UTF8(host), port);
 
	connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData()));
 

	
 
	std::string server = CONFIG_STRING_DEFAULTED(config, "service.irc_server", "");
 
	if (!server.empty()) {
 
		m_servers.push_back(server);
 
	}
 
	else {
 
		
 
		std::list<std::string> list;
 
		list = CONFIG_LIST_DEFAULTED(config, "service.irc_server", list);
 
		
 
		m_servers.insert(m_servers.begin(), list.begin(), list.end());
 
	}
 

	
 
	if (CONFIG_HAS_KEY(config, "service.irc_identify")) {
 
		m_identify = CONFIG_STRING(config, "service.irc_identify");
 
	}
 
	else {
 
		m_identify = "NickServ identify $name $password";
 
	}
 
}
 

	
 
void IRCNetworkPlugin::tryNextServer() {
 
	if (!m_servers.empty()) {
 
		int nextServer = (m_currentServer + 1) % m_servers.size();
 
		LOG4CXX_INFO(logger, "Server " << m_servers[m_currentServer] << " disconnected user. Next server to try will be " << m_servers[nextServer]);
 
		m_currentServer = nextServer;
 
	}
 
}
 

	
 
void IRCNetworkPlugin::readData() {
 
	size_t availableBytes = m_socket->bytesAvailable();
 
	if (availableBytes == 0)
 
		return;
 

	
 
	if (m_firstPing) {
 
		m_firstPing = false;
 
		// Users can join the network without registering if we allow
 
		// one user to connect multiple IRC networks.
 
		if (m_servers.empty()) {
 
			NetworkPlugin::PluginConfig cfg;
 
			cfg.setNeedRegistration(false);
 
			cfg.setSupportMUC(true);
 
			sendConfig(cfg);
 
		}
 
	}
 

	
 
	std::string d = std::string(m_socket->readAll().data(), availableBytes);
 
	handleDataRead(d);
 
}
 

	
 
void IRCNetworkPlugin::sendData(const std::string &string) {
 
	m_socket->write(string.c_str(), string.size());
 
}
 

	
 
MyIrcSession *IRCNetworkPlugin::createSession(const std::string &user, const std::string &hostname, const std::string &nickname, const std::string &password, const std::string &suffix) {
 
	MyIrcSession *session = new MyIrcSession(user, this, suffix);
 
	session->setUserName(FROM_UTF8(nickname));
 
	session->setNickName(FROM_UTF8(nickname));
 
	session->setRealName(FROM_UTF8(nickname));
 
	session->setHost(FROM_UTF8(hostname));
 
	session->setPort(6667);
 
// 	session->setEncoding("UTF8");
 

	
 
	if (!password.empty()) {
 
		std::string identify = m_identify;
 
		boost::replace_all(identify, "$password", password);
 
		boost::replace_all(identify, "$name", nickname);
 
		session->setIdentify(identify);
 
	}
 

	
 
	LOG4CXX_INFO(logger, user << ": Connecting " << hostname << " as " << nickname << ", suffix=" << suffix);
 

	
 
	session->open();
 

	
 
	return session;
 
}
 

	
 
void IRCNetworkPlugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
 
	if (!m_servers.empty()) {
 
		// legacy name is users nickname
 
		if (m_sessions[user] != NULL) {
 
			LOG4CXX_WARN(logger, user << ": Already logged in.");
 
			return;
 
		}
 

	
 
		m_sessions[user] = createSession(user, m_servers[m_currentServer], legacyName, password, "");
 
	}
 
	else {
 
		// We are waiting for first room join to connect user to IRC network, because we don't know which
 
		// network he choose...
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 "transport/networkplugin.h"
 
#include "transport/logging.h"
 
#include "transport/config.h"
 
#include "transport/logging.h"
 
#include "geventloop.h"
 

	
 
// #include "valgrind/memcheck.h"
 
#ifndef __FreeBSD__
 
#include "malloc.h"
 
#endif
 
#include <algorithm>
 
#include "errno.h"
 
#include <boost/make_shared.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");
 

	
 
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;
 

	
 
boost::shared_ptr<Config> config;
 
SpectrumNetworkPlugin *np;
 

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

	
 
struct FTData {
 
	unsigned long id;
 
	unsigned long timer;
 
	bool paused;
 
};
 

	
 
static void *notify_user_info(PurpleConnection *gc, const char *who, PurpleNotifyUserInfo *user_info);
 
@@ -1611,96 +1612,104 @@ static bool initPurple() {
 
		purple_prefs_set_bool_wrapped("/purple/logging/log_chats", false);
 
		purple_prefs_set_bool_wrapped("/purple/logging/log_system", false);
 

	
 

	
 
// 		purple_signal_connect_wrapped(purple_conversations_get_handle_wrapped(), "received-im-msg", &conversation_handle, PURPLE_CALLBACK(newMessageReceived), NULL);
 
		purple_signal_connect_wrapped(purple_conversations_get_handle_wrapped(), "buddy-typing", &conversation_handle, PURPLE_CALLBACK(buddyTyping), NULL);
 
		purple_signal_connect_wrapped(purple_conversations_get_handle_wrapped(), "buddy-typed", &conversation_handle, PURPLE_CALLBACK(buddyTyped), NULL);
 
		purple_signal_connect_wrapped(purple_conversations_get_handle_wrapped(), "buddy-typing-stopped", &conversation_handle, PURPLE_CALLBACK(buddyTypingStopped), NULL);
 
		purple_signal_connect_wrapped(purple_blist_get_handle_wrapped(), "buddy-privacy-changed", &conversation_handle, PURPLE_CALLBACK(buddyPrivacyChanged), NULL);
 
		purple_signal_connect_wrapped(purple_conversations_get_handle_wrapped(), "got-attention", &conversation_handle, PURPLE_CALLBACK(gotAttention), NULL);
 
		purple_signal_connect_wrapped(purple_connections_get_handle_wrapped(), "signed-on", &blist_handle,PURPLE_CALLBACK(signed_on), NULL);
 
// 		purple_signal_connect_wrapped(purple_blist_get_handle_wrapped(), "buddy-removed", &blist_handle,PURPLE_CALLBACK(buddyRemoved), NULL);
 
// 		purple_signal_connect_wrapped(purple_blist_get_handle_wrapped(), "buddy-signed-on", &blist_handle,PURPLE_CALLBACK(buddySignedOn), NULL);
 
// 		purple_signal_connect_wrapped(purple_blist_get_handle_wrapped(), "buddy-signed-off", &blist_handle,PURPLE_CALLBACK(buddySignedOff), NULL);
 
// 		purple_signal_connect_wrapped(purple_blist_get_handle_wrapped(), "buddy-status-changed", &blist_handle,PURPLE_CALLBACK(buddyStatusChanged), NULL);
 
		purple_signal_connect_wrapped(purple_blist_get_handle_wrapped(), "blist-node-removed", &blist_handle,PURPLE_CALLBACK(NodeRemoved), NULL);
 
// 		purple_signal_connect_wrapped(purple_conversations_get_handle_wrapped(), "chat-topic-changed", &conversation_handle, PURPLE_CALLBACK(conv_chat_topic_changed), NULL);
 
		static int xfer_handle;
 
		purple_signal_connect_wrapped(purple_xfers_get_handle_wrapped(), "file-send-start", &xfer_handle, PURPLE_CALLBACK(fileSendStart), NULL);
 
		purple_signal_connect_wrapped(purple_xfers_get_handle_wrapped(), "file-recv-start", &xfer_handle, PURPLE_CALLBACK(fileRecvStart), NULL);
 
		purple_signal_connect_wrapped(purple_xfers_get_handle_wrapped(), "file-recv-request", &xfer_handle, PURPLE_CALLBACK(newXfer), NULL);
 
		purple_signal_connect_wrapped(purple_xfers_get_handle_wrapped(), "file-recv-complete", &xfer_handle, PURPLE_CALLBACK(XferReceiveComplete), NULL);
 
		purple_signal_connect_wrapped(purple_xfers_get_handle_wrapped(), "file-send-complete", &xfer_handle, PURPLE_CALLBACK(XferSendComplete), NULL);
 
// 
 
// 		purple_commands_init();
 

	
 
	}
 
	return ret;
 
}
 

	
 

	
 
static void transportDataReceived(gpointer data, gint source, PurpleInputCondition cond) {
 
	if (cond & PURPLE_INPUT_READ) {
 
		char buffer[65535];
 
		char *ptr = buffer;
 
#ifdef WIN32
 
		ssize_t n = recv(source, ptr, sizeof(buffer), 0);
 
#else
 
		ssize_t n = read(source, ptr, sizeof(buffer));
 
#endif
 
		if (n <= 0) {
 
			if (errno == EAGAIN) {
 
				return;
 
			}
 
			LOG4CXX_INFO(logger, "Diconnecting from spectrum2 server");
 
			exit(errno);
 
		}
 
		std::string d = std::string(buffer, n);
 

	
 
		if (firstPing) {
 
			firstPing = false;
 
			NetworkPlugin::PluginConfig cfg;
 
			cfg.setSupportMUC(true);
 
			np->sendConfig(cfg);
 
		}
 

	
 
		np->handleDataRead(d);
 
	}
 
	else {
 
		if (writeInput != 0) {
 
			purple_input_remove_wrapped(writeInput);
 
			writeInput = 0;
 
		}
 
		np->readyForData();
 
	}
 
}
 

	
 
int main(int argc, char **argv) {
 
#ifndef WIN32
 
#ifndef __FreeBSD__
 
		mallopt(M_CHECK_ACTION, 2);
 
		mallopt(M_PERTURB, 0xb);
 
#endif
 

	
 
		signal(SIGPIPE, SIG_IGN);
 

	
 
		if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
 
			std::cout << "SIGCHLD handler can't be set\n";
 
			return -1;
 
		}
 
#endif
 

	
 
	std::string error;
 
	Config *cfg = Config::createFromArgs(argc, argv, error, host, port);
 
	if (cfg == NULL) {
 
		std::cerr << error;
 
		return 1;
 
	}
 

	
 
	config = boost::shared_ptr<Config>(cfg);
 
 
 
	Logging::initBackendLogging(config.get());
 
	initPurple();
 
 
 
	main_socket = create_socket(host.c_str(), port);
 
	purple_input_add_wrapped(main_socket, PURPLE_INPUT_READ, &transportDataReceived, NULL);
 
	purple_timeout_add_seconds_wrapped(30, pingTimeout, NULL);
 
 
 
	np = new SpectrumNetworkPlugin();
 
	bool libev = CONFIG_STRING_DEFAULTED(config, "service.eventloop", "") == "libev";
 

	
 
	GMainLoop *m_loop;
 
#ifdef WITH_LIBEVENT
 
	if (!libev) {
include/transport/networkplugin.h
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
 
 */
 

	
 
#pragma once
 

	
 
#include <time.h>
 
#include "transport/protocol.pb.h"
 
// #include "conversation.h"
 
#include <iostream>
 
#include <list>
 

	
 
namespace Transport {
 

	
 
/// Represents Spectrum2 legacy network plugin.
 

	
 
/// This class is base class for all C++ legacy network plugins. It provides a way to connect 
 
/// Spectrum2 NetworkPluginServer and allows to use high-level API for legacy network plugins
 
/// development.
 
class NetworkPlugin {
 
	public:
 
		enum ExitCode { StorageBackendNeeded = -2 };
 

	
 
		class PluginConfig {
 
			public:
 
				PluginConfig() : m_needPassword(true), m_needRegistration(false) {}
 
				PluginConfig() : m_needPassword(true), m_needRegistration(false), m_supportMUC(false) {}
 
				virtual ~PluginConfig() {}
 

	
 
				void setNeedRegistration(bool needRegistration = false) { m_needRegistration = needRegistration; }
 
				void setNeedPassword(bool needPassword = true) { m_needPassword = needPassword; }
 
				void setSupportMUC(bool supportMUC = true) { m_supportMUC = supportMUC; }
 
				void setExtraFields(const std::vector<std::string> &fields) { m_extraFields = fields; }
 

	
 
			private:
 
				bool m_needPassword;
 
				bool m_needRegistration;
 
				bool m_supportMUC;
 
				std::vector<std::string> m_extraFields;
 

	
 
				friend class NetworkPlugin;
 
		};
 

	
 
		/// Creates new NetworkPlugin and connects the Spectrum2 NetworkPluginServer.
 
		/// \param loop Event loop.
 
		/// \param host Host where Spectrum2 NetworkPluginServer runs.
 
		/// \param port Port.
 
		NetworkPlugin();
 

	
 
		/// Destructor.
 
		virtual ~NetworkPlugin();
 

	
 
		void sendConfig(const PluginConfig &cfg);
 

	
 
		/// 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 = "");
 

	
 
		/// 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")
plugin/cpp/networkplugin.cpp
Show inline comments
 
@@ -26,96 +26,99 @@
 

	
 
#ifndef WIN32
 
#include <arpa/inet.h>
 
#include <sys/types.h>
 
#include <unistd.h>
 
#else 
 
#include <winsock2.h>
 
#include <stdint.h>
 
#include <process.h>
 
#define getpid _getpid
 
#endif
 

	
 
DEFINE_LOGGER(logger, "NetworkPlugin");
 

	
 
namespace Transport {
 

	
 
#define WRAP(MESSAGE, TYPE) 	pbnetwork::WrapperMessage wrap; \
 
	wrap.set_type(TYPE); \
 
	wrap.set_payload(MESSAGE); \
 
	wrap.SerializeToString(&MESSAGE);
 

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

	
 
NetworkPlugin::NetworkPlugin() {
 
	m_pingReceived = false;
 

	
 
	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";
 

	
 
	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::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) {
 
	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);
 

	
 
	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);
src/config.cpp
Show inline comments
 
@@ -269,96 +269,97 @@ bool Config::load(const std::string &configfile, const std::string &jid) {
 
#endif
 
		return false;
 
	}
 
}
 

	
 
bool Config::reload() {
 
	if (m_file.empty()) {
 
		return false;
 
	}
 

	
 
	return load(m_file, m_jid);
 
}
 

	
 
Config::SectionValuesCont Config::getSectionValues(const std::string& sectionName) {
 
	SectionValuesCont sectionValues;
 

	
 
	std::string sectionSearchString = sectionName + ".";
 
	BOOST_FOREACH (const Variables::value_type & varItem, m_variables) {
 
		if (boost::istarts_with(varItem.first, sectionSearchString))
 
			sectionValues[varItem.first] = varItem.second;
 
	}
 

	
 
	BOOST_FOREACH (const UnregisteredCont::value_type & varItem, m_unregistered) {
 
		if (boost::istarts_with(varItem.first, sectionSearchString))
 
			sectionValues[varItem.first] = varItem.second;
 
	}
 

	
 
	return sectionValues;
 
}
 

	
 
std::string Config::getCommandLineArgs() const {
 
	std::ostringstream commandLineArgs;
 

	
 
	// Return the command-line arguments that were passed to us originally (but remove the initial .exe part)
 
	for (int i = 1; i < m_argc; ++i) 	{
 
		commandLineArgs << "\"" << m_argv[i] << "\" ";
 
	}
 

	
 
	return commandLineArgs.str();
 
}
 

	
 
void Config::updateBackendConfig(const std::string &backendConfig) {
 
	options_description opts("Backend options");
 
	opts.add_options()
 
		("registration.needPassword", value<bool>()->default_value(true), "")
 
		("registration.needRegistration", value<bool>()->default_value(false), "")
 
		("registration.extraField", value<std::vector<std::string> >()->multitoken(), "")
 
		("features.receipts", value<bool>()->default_value(false), "")
 
		("features.muc", value<bool>()->default_value(false), "")
 
	;
 

	
 
	std::stringstream ifs(backendConfig);
 
	parsed_options parsed = parse_config_file(ifs, opts, true);
 

	
 
	store(parsed, m_backendConfig);
 
	notify(m_backendConfig);
 

	
 
	onBackendConfigUpdated();
 
}
 

	
 
Config *Config::createFromArgs(int argc, char **argv, std::string &error, std::string &host, int &port) {
 
	std::string jid;
 
	std::ostringstream os;
 
	std::string configFile;
 
	boost::program_options::variables_map vm;
 
	boost::program_options::options_description desc("Usage: spectrum <config_file.cfg>\nAllowed options");
 
	desc.add_options()
 
		("help", "help")
 
		("host,h", boost::program_options::value<std::string>(&host)->default_value(""), "Host to connect to")
 
		("port,p", boost::program_options::value<int>(&port)->default_value(10000), "Port to connect to")
 
		("no-daemonize,n", "Do not run spectrum as daemon")
 
		("no-debug,d", "Create coredumps on crash")
 
		("jid,j", boost::program_options::value<std::string>(&jid)->default_value(""), "Specify JID of transport manually")
 
		("config", boost::program_options::value<std::string>(&configFile)->default_value(""), "Config file")
 
		;
 

	
 
	os << desc;
 
	try
 
	{
 
		boost::program_options::positional_options_description p;
 
		p.add("config", -1);
 
		boost::program_options::store(boost::program_options::command_line_parser(argc, argv).
 
			options(desc).positional(p).allow_unregistered().run(), vm);
 
		boost::program_options::notify(vm);
 
			
 
		if(vm.count("help"))
 
		{
 
			error = os.str();
 
			return NULL;
 
		}
 

	
 
		if(vm.count("config") == 0) {
 
			error = os.str();
 
			return NULL;
 
		}
 
	}
 
	catch (std::runtime_error& e)
src/discoinforesponder.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 "discoinforesponder.h"
 

	
 
#include <iostream>
 
#include <boost/bind.hpp>
 
#include <boost/algorithm/string.hpp>
 
#include "Swiften/Disco/DiscoInfoResponder.h"
 
#include "Swiften/Queries/IQRouter.h"
 
#include "Swiften/Elements/DiscoInfo.h"
 
#include "transport/config.h"
 
#include "transport/logging.h"
 
#include "Swiften/Disco/CapsInfoGenerator.h"
 

	
 
using namespace Swift;
 
using namespace boost;
 

	
 
DEFINE_LOGGER(logger, "DiscoInfoResponder");
 

	
 
namespace Transport {
 

	
 
DiscoInfoResponder::DiscoInfoResponder(Swift::IQRouter *router, Config *config) : Swift::GetResponder<DiscoInfo>(router) {
 
	m_config = config;
 
	m_config->onBackendConfigUpdated.connect(boost::bind(&DiscoInfoResponder::updateBuddyFeatures, this));
 
	m_config->onBackendConfigUpdated.connect(boost::bind(&DiscoInfoResponder::updateFeatures, this));
 
	m_buddyInfo = NULL;
 
	m_transportInfo.addIdentity(DiscoInfo::Identity(CONFIG_STRING(m_config, "identity.name"),
 
													CONFIG_STRING(m_config, "identity.category"),
 
													CONFIG_STRING(m_config, "identity.type")));
 

	
 
	std::list<std::string> features;
 
	features.push_back("jabber:iq:register");
 
	features.push_back("jabber:iq:gateway");
 
	features.push_back("jabber:iq:private");
 
	features.push_back("http://jabber.org/protocol/disco#info");
 
	features.push_back("http://jabber.org/protocol/commands");
 
	setTransportFeatures(features);
 

	
 
	updateBuddyFeatures();
 
	updateFeatures();
 
}
 

	
 
DiscoInfoResponder::~DiscoInfoResponder() {
 
	delete m_buddyInfo;
 
}
 

	
 
void DiscoInfoResponder::updateBuddyFeatures() {
 
void DiscoInfoResponder::updateFeatures() {
 
	std::list<std::string> features2;
 
	features2.push_back("jabber:iq:register");
 
	features2.push_back("jabber:iq:gateway");
 
	features2.push_back("jabber:iq:private");
 
	features2.push_back("http://jabber.org/protocol/disco#info");
 
	features2.push_back("http://jabber.org/protocol/commands");
 
	if (CONFIG_BOOL_DEFAULTED(m_config, "features.muc", false)) {
 
		features2.push_back("http://jabber.org/protocol/muc");
 
	}
 
	setTransportFeatures(features2);
 

	
 
	std::list<std::string> features;
 
	features.push_back("http://jabber.org/protocol/disco#items");
 
	features.push_back("http://jabber.org/protocol/disco#info");
 
	features.push_back("http://jabber.org/protocol/chatstates");
 
	features.push_back("http://jabber.org/protocol/xhtml-im");
 
	if (CONFIG_BOOL_DEFAULTED(m_config, "features.receipts", false)) {
 
		features.push_back("urn:xmpp:receipts");
 
	}
 
	setBuddyFeatures(features);
 
}
 

	
 
void DiscoInfoResponder::setTransportFeatures(std::list<std::string> &features) {
 
	for (std::list<std::string>::iterator it = features.begin(); it != features.end(); it++) {
 
		if (!m_transportInfo.hasFeature(*it)) {
 
			m_transportInfo.addFeature(*it);
 
		}
 
	}
 
}
 

	
 
void DiscoInfoResponder::setBuddyFeatures(std::list<std::string> &f) {
 
	delete m_buddyInfo;
 
	m_buddyInfo = new Swift::DiscoInfo;
 
	m_buddyInfo->addIdentity(DiscoInfo::Identity(CONFIG_STRING(m_config, "identity.name"), "client", "pc"));
 

	
 
	for (std::list<std::string>::iterator it = f.begin(); it != f.end(); it++) {
 
		if (!m_buddyInfo->hasFeature(*it)) {
 
			m_buddyInfo->addFeature(*it);
 
		}
 
	}
 

	
 
	CapsInfoGenerator caps("spectrum");
 
	m_capsInfo = caps.generateCapsInfo(*m_buddyInfo);
 
	onBuddyCapsInfoChanged(m_capsInfo);
 
}
 

	
 
void DiscoInfoResponder::addRoom(const std::string &jid, const std::string &name) {
 
	std::string j = jid;
 
	boost::algorithm::to_lower(j);
 
	m_rooms[j] = name;
 
}
 

	
 
void DiscoInfoResponder::clearRooms() {
 
	m_rooms.clear();
 
}
 

	
 
void DiscoInfoResponder::addAdHocCommand(const std::string &node, const std::string &name) {
 
	m_commands[node] = node;
 
}
src/discoinforesponder.h
Show inline comments
 
@@ -7,59 +7,59 @@
 
 * it under the terms of the GNU General Public License as published by
 
 * the Free Software Foundation; either version 2 of the License, or
 
 * (at your option) any later version.
 
 *
 
 * This program is distributed in the hope that it will be useful,
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 * GNU General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU General Public License
 
 * along with this program; if not, write to the Free Software
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#pragma once
 

	
 
#include <vector>
 
#include <list>
 
#include <boost/signal.hpp>
 
#include "Swiften/Queries/GetResponder.h"
 
#include "Swiften/Elements/DiscoInfo.h"
 
#include "Swiften/Elements/CapsInfo.h"
 

	
 
namespace Transport {
 

	
 
class Config;
 

	
 
class DiscoInfoResponder : public Swift::GetResponder<Swift::DiscoInfo> {
 
	public:
 
		DiscoInfoResponder(Swift::IQRouter *router, Config *config);
 
		~DiscoInfoResponder();
 

	
 
		void setTransportFeatures(std::list<std::string> &features);
 
		void setBuddyFeatures(std::list<std::string> &features);
 

	
 
		void addRoom(const std::string &jid, const std::string &name);
 
		void clearRooms();
 

	
 
		void addAdHocCommand(const std::string &node, const std::string &name);
 

	
 
		boost::signal<void (const Swift::CapsInfo &capsInfo)> onBuddyCapsInfoChanged;
 

	
 
		Swift::CapsInfo &getBuddyCapsInfo() {
 
				return m_capsInfo;
 
		}
 

	
 
	private:
 
		virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::DiscoInfo> payload);
 
		void updateBuddyFeatures();
 
		void updateFeatures();
 

	
 
		Swift::DiscoInfo m_transportInfo;
 
		Swift::DiscoInfo *m_buddyInfo;
 
		Config *m_config;
 
		Swift::CapsInfo m_capsInfo;
 
		std::map<std::string, std::string> m_rooms;
 
		std::map<std::string, std::string> m_commands;
 
};
 

	
 
}
0 comments (0 inline, 0 general)