Changeset - 68527d73e2b8
[Not reviewed]
0 5 0
Jan Kaluza - 10 years ago 2016-02-24 17:06:10
jkaluza@redhat.com
Libtransport: Allow unregistered boolean variables in Config
5 files changed with 23 insertions and 3 deletions:
0 comments (0 inline, 0 general)
libtransport/Config.cpp
Show inline comments
 
@@ -174,98 +174,106 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
 
			}
 
		}
 
		else if (opt.string_key == "service.working_dir") {
 
			found_working = true;
 
		}
 
		else if (opt.string_key == "service.pidfile") {
 
			found_pidfile = true;
 
		}
 
		else if (opt.string_key == "service.portfile") {
 
			found_portfile = true;
 
		}
 
		else if (opt.string_key == "database.database") {
 
			found_database = true;
 
		}
 
	}
 

	
 
	if (!found_working) {
 
		std::vector<std::string> value;
 
		value.push_back("/var/lib/spectrum2/$jid");
 
		parsed.options.push_back(boost::program_options::basic_option<char>("service.working_dir", value));
 
	}
 
	if (!found_pidfile) {
 
		std::vector<std::string> value;
 
		value.push_back("/var/run/spectrum2/$jid.pid");
 
		parsed.options.push_back(boost::program_options::basic_option<char>("service.pidfile", value));
 
	}
 
	if (!found_portfile) {
 
		std::vector<std::string> value;
 
		value.push_back("/var/run/spectrum2/$jid.port");
 
		parsed.options.push_back(boost::program_options::basic_option<char>("service.portfile", value));
 
	}
 
	if (!found_backend_port) {
 
		std::vector<std::string> value;
 
		std::string p = boost::lexical_cast<std::string>(getRandomPort(_jid.empty() ? jid : _jid));
 
		value.push_back(p);
 
		parsed.options.push_back(boost::program_options::basic_option<char>("service.backend_port", value));
 
	}
 
	if (!found_database) {
 
		std::vector<std::string> value;
 
		value.push_back("/var/lib/spectrum2/$jid/database.sql");
 
		parsed.options.push_back(boost::program_options::basic_option<char>("database.database", value));
 
	}
 

	
 
	std::list<std::string> has_key;
 
	BOOST_FOREACH(option &opt, parsed.options) {
 
		if (opt.unregistered) {
 
			if (std::find(has_key.begin(), has_key.end(), opt.string_key) == has_key.end()) {
 
				has_key.push_back(opt.string_key);
 
				if (opt.value[0] == "true" || opt.value[0] == "1") {
 
					m_unregistered[opt.string_key] = variable_value(true, false);
 
				}
 
				else if (opt.value[0] == "true" || opt.value[0] == "1") {
 
					m_unregistered[opt.string_key] = variable_value(false, false);
 
				}
 
				else {
 
					m_unregistered[opt.string_key] = variable_value(opt.value[0], false);
 
				}
 
			}
 
			else {
 
				std::list<std::string> list;
 
				try {
 
					list = m_unregistered[opt.string_key].as<std::list<std::string> >();
 
				}
 
				catch(...) {
 
					list.push_back(m_unregistered[opt.string_key].as<std::string>());
 
				}
 
				
 
				list.push_back(opt.value[0]);
 
				m_unregistered[opt.string_key] = variable_value(list, false);
 
			}
 
		}
 
		else if (opt.value[0].find("$jid") != std::string::npos) {
 
			boost::replace_all(opt.value[0], "$jid", jid);
 
		}
 
	}
 

	
 
	// Load configs passed by command line
 
	if (m_argc != 0 && m_argv) {
 
		basic_command_line_parser<char> parser = command_line_parser(m_argc, m_argv).options(opts).allow_unregistered();
 
		parsed_options parsed = parser.run();
 
		BOOST_FOREACH(option &opt, parsed.options) {
 
			if (opt.unregistered && !opt.value.empty()) {
 
				m_unregistered[opt.string_key] = variable_value(opt.value[0], false);
 
			}
 
		}
 
		store(parsed, m_variables);
 
	}
 

	
 
	store(parsed, m_variables);
 
	notify(m_variables);
 

	
 
	onConfigReloaded();
 

	
 
	return true;
 
}
 

	
 
bool Config::load(std::istream &ifs) {
 
	options_description opts("Transport options");
 
	return load(ifs, opts);
 
}
 

	
 
bool Config::load(const std::string &configfile, const std::string &jid) {
 
	try {
 
		options_description opts("Transport options");
 
		return load(configfile, opts, jid);
 
	} catch ( const boost::program_options::multiple_occurrences& e ) {
spectrum/src/frontends/xmpp/adhocmanager.cpp
Show inline comments
 
@@ -28,96 +28,99 @@
 
#include "transport/Transport.h"
 
#include "transport/Config.h"
 

	
 
#include "XMPPFrontend.h"
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "AdHocManager");
 

	
 
AdHocManager::AdHocManager(Component *component, DiscoItemsResponder *discoItemsResponder, UserManager *userManager, StorageBackend *storageBackend) : Swift::Responder<Swift::Command>(static_cast<XMPPFrontend *>(component->getFrontend())->getIQRouter()){
 
	m_component = component;
 
	m_discoItemsResponder = discoItemsResponder;
 
	m_userManager = userManager;
 
	m_storageBackend = storageBackend;
 

	
 
	m_collectTimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(20);
 
	m_collectTimer->onTick.connect(boost::bind(&AdHocManager::removeOldSessions, this));
 
	m_collectTimer->start();
 

	
 
	m_userManager->onUserCreated.connect(boost::bind(&AdHocManager::handleUserCreated, this, _1));
 
}
 

	
 
AdHocManager::~AdHocManager() {
 
	m_collectTimer->stop();
 
	stop();
 
}
 

	
 
void AdHocManager::start() {
 
	Swift::Responder<Swift::Command>::start();
 
}
 

	
 
void AdHocManager::stop() {
 
	Swift::Responder<Swift::Command>::stop();
 

	
 
	for (SessionsMap::iterator it = m_sessions.begin(); it != m_sessions.end(); it++) {
 
		std::vector<std::string> candidates;
 
		for (CommandsMap::iterator ct = it->second.begin(); ct != it->second.end(); ct++) {
 
			delete ct->second;
 
		}
 
	}
 

	
 
	m_sessions.clear();
 
}
 

	
 
void AdHocManager::handleUserCreated(User *user) {
 
	for (std::map<std::string, AdHocCommandFactory *>::const_iterator it = m_factories.begin(); it != m_factories.end(); it++) {
 
		for (std::map<std::string, std::string>::const_iterator it2 = it->second->getUserSettings().begin(); it2 != it->second->getUserSettings().end(); it2++) {
 
			std::string value = CONFIG_STRING_DEFAULTED(m_component->getConfig(), it->second->getNode() + "." + it2->first, it2->second);
 
			if (it2->second == "true" || it2->second == "1" || it2->second == "false" || it2->second == "0") {
 
				value = CONFIG_BOOL_DEFAULTED(m_component->getConfig(), it->second->getNode() + "." + it2->first, it2->second == "true" || it2->second == "1") ? "1" : "0";
 
			}
 
			if (m_storageBackend) {
 
				int type = (int) TYPE_BOOLEAN;
 
				m_storageBackend->getUserSetting(user->getUserInfo().id, it2->first, type, value);
 
			}
 
			user->addUserSetting(it2->first, value);
 
		}
 
	}
 
}
 

	
 
void AdHocManager::addAdHocCommand(AdHocCommandFactory *factory) {
 
	if (m_factories.find(factory->getNode()) != m_factories.end()) {
 
		LOG4CXX_ERROR(logger, "Command with node " << factory->getNode() << " is already registered. Ignoring this attempt.");
 
		return;
 
	}
 

	
 
	m_factories[factory->getNode()] = factory;
 
	m_discoItemsResponder->addAdHocCommand(factory->getNode(), factory->getName());
 
}
 

	
 
void AdHocManager::removeOldSessions() {
 
	unsigned long removedCommands = 0;
 
	time_t now = time(NULL);
 

	
 
	std::vector<std::string> toRemove;
 
	for (SessionsMap::iterator it = m_sessions.begin(); it != m_sessions.end(); it++) {
 
		std::vector<std::string> candidates;
 
		for (CommandsMap::iterator ct = it->second.begin(); ct != it->second.end(); ct++) {
 
			if (now - ct->second->getLastActivity() > 15*60) {
 
				candidates.push_back(it->first);
 
				delete ct->second;
 
				removedCommands++;
 
			}
 
		}
 

	
 
		BOOST_FOREACH(std::string &key, candidates) {
 
			it->second.erase(key);
 
		}
 

	
 
		if (it->second.empty()) {
 
			toRemove.push_back(it->first);
 
		}
 
	}
 

	
 
	BOOST_FOREACH(std::string &key, toRemove) {
 
		m_sessions.erase(key);
 
	}
 

	
 
	if (removedCommands > 0) {
spectrum/src/frontends/xmpp/settingsadhoccommand.cpp
Show inline comments
 
@@ -22,101 +22,101 @@
 
#include "transport/UserManager.h"
 
#include "transport/User.h"
 
#include "transport/Logging.h"
 
#include "transport/StorageBackend.h"
 
#include "transport/Transport.h"
 
#include "transport/Config.h"
 
#include "formutils.h"
 

	
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "SettingsAdHocCommand");
 

	
 
SettingsAdHocCommand::SettingsAdHocCommand(Component *component, UserManager *userManager, StorageBackend *storageBackend, const Swift::JID &initiator, const Swift::JID &to) : AdHocCommand(component, userManager, storageBackend, initiator, to) {
 
	m_state = Init;
 
}
 

	
 
SettingsAdHocCommand::~SettingsAdHocCommand() {
 
}
 

	
 
boost::shared_ptr<Swift::Command> SettingsAdHocCommand::getForm() {
 
	if (!m_storageBackend) {
 
		boost::shared_ptr<Swift::Command> response(new Swift::Command("settings", m_id, Swift::Command::Completed));
 
		boost::shared_ptr<Swift::Form> form(new Swift::Form());
 
		FormUtils::addTextFixedField(form, "This server does not support transport settings. There is no storage backend configured");
 
		response->setForm(form);
 
		return response;
 
	}
 

	
 
	UserInfo user;
 
	if (m_storageBackend->getUser(m_initiator.toBare().toString(), user) == false) {
 
		boost::shared_ptr<Swift::Command> response(new Swift::Command("settings", m_id, Swift::Command::Completed));
 
		boost::shared_ptr<Swift::Form> form(new Swift::Form());
 
		FormUtils::addTextFixedField(form, "You are not registered.");
 
		response->setForm(form);
 
		return response;
 
	}
 

	
 
	boost::shared_ptr<Swift::Command> response(new Swift::Command("settings", m_id, Swift::Command::Executing));
 
	boost::shared_ptr<Swift::Form> form(new Swift::Form());
 

	
 
	std::string value;
 
	int type = (int) TYPE_BOOLEAN;
 

	
 
	value = "1";
 
	m_storageBackend->getUserSetting(user.id, "enable_transport", type, value);
 
	FormUtils::addBooleanField(form, "enable_transport", value, "Enable transport");
 

	
 
	value = CONFIG_STRING_DEFAULTED(m_component->getConfig(), "settings.send_headlines", "0");
 
	value = CONFIG_BOOL_DEFAULTED(m_component->getConfig(), "settings.send_headlines", false) ? "1" : "0";
 
	m_storageBackend->getUserSetting(user.id, "send_headlines", type, value);
 
	FormUtils::addBooleanField(form, "send_headlines", value, "Allow sending messages as headlines");
 

	
 
	value = CONFIG_STRING_DEFAULTED(m_component->getConfig(), "settings.stay_connected", "0");
 
	value = CONFIG_BOOL_DEFAULTED(m_component->getConfig(), "settings.stay_connected", false) ? "1" : "0";
 
	m_storageBackend->getUserSetting(user.id, "stay_connected", type, value);
 
	FormUtils::addBooleanField(form, "stay_connected", value, "Stay connected to legacy network when offline on XMPP");
 

	
 
	response->setForm(form);
 
	return response;
 
}
 

	
 
void SettingsAdHocCommand::updateUserSetting(Swift::Form::ref form, UserInfo &user, const std::string &name) {
 
	std::string value = FormUtils::fieldValue(form, name, "");
 
	if (value.empty()) {
 
		return;
 
	}
 

	
 
	m_storageBackend->updateUserSetting(user.id, name, value);
 
}
 

	
 
boost::shared_ptr<Swift::Command> SettingsAdHocCommand::handleResponse(boost::shared_ptr<Swift::Command> payload) {
 
	UserInfo user;
 
	bool registered = m_storageBackend->getUser(m_initiator.toBare().toString(), user);
 

	
 
	if (registered && payload->getForm()) {
 
		updateUserSetting(payload->getForm(), user, "enable_transport");
 
		updateUserSetting(payload->getForm(), user, "send_headlines");
 
		updateUserSetting(payload->getForm(), user, "stay_connected");
 
	}
 

	
 
	boost::shared_ptr<Swift::Command> response(new Swift::Command("settings", m_id, Swift::Command::Completed));
 
	return response;
 
}
 

	
 
boost::shared_ptr<Swift::Command> SettingsAdHocCommand::handleRequest(boost::shared_ptr<Swift::Command> payload) {
 
	boost::shared_ptr<Swift::Command> response;
 
	if (payload->getAction() == Swift::Command::Cancel) {
 
		response = boost::shared_ptr<Swift::Command>(new Swift::Command("settings", m_id, Swift::Command::Canceled));
 
		return response;
 
	}
 

	
 
	switch (m_state) {
 
		case Init:
 
			response = getForm();
 
			m_state = WaitingForResponse;
 
			break;
 
		case WaitingForResponse:
 
			response = handleResponse(payload);
 
			break;
 
		default:
 
			break;
 
	}
tests/libtransport/config.cpp
Show inline comments
 
#include <cppunit/TestFixture.h>
 
#include <cppunit/extensions/HelperMacros.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 "basictest.h"
 

	
 

	
 
using namespace Transport;
 

	
 
class ConfigTest : public CPPUNIT_NS :: TestFixture{
 
	CPPUNIT_TEST_SUITE(ConfigTest);
 
	CPPUNIT_TEST(setStringTwice);
 
	CPPUNIT_TEST(setUnknownBool);
 
	CPPUNIT_TEST(updateBackendConfig);
 
	CPPUNIT_TEST(updateBackendConfigJIDEscaping);
 
	CPPUNIT_TEST(unregisteredList);
 
	CPPUNIT_TEST(unregisteredString);
 
	CPPUNIT_TEST(unregisteredListAsString);
 
	CPPUNIT_TEST(unregisteredStringAsList);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 
		void setUp (void) {
 
		}
 

	
 
		void tearDown (void) {
 

	
 
		}
 

	
 
	void setStringTwice() {
 
		char *argv[3] = {"binary", "--service.jids=localhost", NULL};
 
		Config cfg(2, argv);
 
		std::istringstream ifs("service.jids = irc.freenode.org\n");
 
		cfg.load(ifs);
 
		CPPUNIT_ASSERT_EQUAL(std::string("localhost"), CONFIG_STRING(&cfg, "service.jids"));
 
	}
 

	
 
	void setUnknownBool() {
 
		char *argv[3] = {"binary", "--service.jids=localhost", NULL};
 
		Config cfg(2, argv);
 
		std::istringstream ifs("service.irc_send_pass = 1\n");
 
		cfg.load(ifs);
 
		CPPUNIT_ASSERT_EQUAL(true, CONFIG_BOOL_DEFAULTED(&cfg, "service.irc_send_pass", false));
 
	}
 

	
 
	void updateBackendConfig() {
 
		Config cfg;
 
		CPPUNIT_ASSERT(!cfg.hasKey("registration.needPassword"));
 

	
 
		cfg.updateBackendConfig("[registration]\nneedPassword=0\n");
 
		CPPUNIT_ASSERT(cfg.hasKey("registration.needPassword"));
 
		CPPUNIT_ASSERT_EQUAL(false, CONFIG_BOOL(&cfg, "registration.needPassword"));
 
	}
 

	
 
	void updateBackendConfigJIDEscaping() {
 
		Config cfg;
 
		std::istringstream ifs("service.jids = irc.freenode.org\n");
 
		cfg.load(ifs);
 
		CPPUNIT_ASSERT_EQUAL(true, CONFIG_BOOL(&cfg, "service.jid_escaping"));
 

	
 
		cfg.updateBackendConfig("[features]\ndisable_jid_escaping=1\n");
 
		CPPUNIT_ASSERT_EQUAL(false, CONFIG_BOOL(&cfg, "service.jid_escaping"));
 
	}
 

	
 
	void unregisteredList() {
 
		Config cfg;
 
		std::istringstream ifs("service.irc_server = irc.freenode.org\nservice.irc_server=localhost\n");
 
		cfg.load(ifs);
 
		CPPUNIT_ASSERT_EQUAL(2, (int) CONFIG_LIST(&cfg, "service.irc_server").size());
 
	}
 

	
 
	void unregisteredString() {
 
		Config cfg;
 
		std::istringstream ifs("service.irc_server = irc.freenode.org");
 
		cfg.load(ifs);
 
		CPPUNIT_ASSERT_EQUAL(std::string("irc.freenode.org"), CONFIG_STRING(&cfg, "service.irc_server"));
 
	}
 

	
 
	void unregisteredListAsString() {
 
		Config cfg;
 
		std::istringstream ifs("service.irc_server = irc.freenode.orgn\nservice.irc_server = irc2.freenode.org");
 
		cfg.load(ifs);
 
		CPPUNIT_ASSERT_EQUAL(std::string(""), CONFIG_STRING_DEFAULTED(&cfg, "service.irc_server", ""));
 
	}
 

	
 
	void unregisteredStringAsList() {
 
		Config cfg;
 
		std::istringstream ifs("service.irc_server = irc.freenode.org");
 
		cfg.load(ifs);
 
		std::list<std::string> list;
 
		CPPUNIT_ASSERT_EQUAL(0, (int) CONFIG_LIST_DEFAULTED(&cfg, "service.irc_server", list).size());
 
	}
 

	
tests/tests_output/localhost/vcard/client.dat
Show inline comments
 
return {
 
	[1] = {
 
		[1] = {
 
			[1] = "image/png";
 
			["attr"] = {
 
				["xmlns"] = "vcard-temp";
 
			};
 
			["name"] = "TYPE";
 
		};
 
		[2] = {
 
			[1] = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAAAAAAKSURBVHicY2AAAAACAAEAAAAASUVORA==";
 
			["attr"] = {
 
				["xmlns"] = "vcard-temp";
 
			};
 
			["name"] = "BINVAL";
 
		};
 
		["name"] = "PHOTO";
 
		["attr"] = {
 
			["xmlns"] = "vcard-temp";
 
		};
 
	};
 
	["attr"] = {
 
		["prodid"] = "-//HandGen//NONSGML vGen v1.0//EN";
 
		["version"] = "2.0";
 
		["prodid"] = "-//HandGen//NONSGML vGen v1.0//EN";
 
		["xmlns"] = "vcard-temp";
 
	};
 
	["name"] = "vCard";
 
};
0 comments (0 inline, 0 general)