Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Daniel Henninger 2012-05-07 11:18:54 -04:00
commit 9331f56079
121 changed files with 4089 additions and 2774 deletions

View file

@ -1,6 +1,10 @@
cmake_minimum_required(VERSION 2.6)
project(libtransport)
if(NOT LIB_INSTALL_DIR)
set(LIB_INSTALL_DIR "lib")
endif()
set(CMAKE_MODULE_PATH "cmake_modules")
set(cppunit_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
@ -27,10 +31,10 @@ set(event_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(event)
set(Swiften_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(Swiften REQUIRED)
find_package(Swiften)
set(openssl_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(openssl REQUIRED)
find_package(openssl)
set(Boost_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
if (WIN32)
@ -167,10 +171,12 @@ else()
endif()
if (LOG4CXX_FOUND)
message("Logging : yes")
message("Log4cxx : yes")
include_directories(${LOG4CXX_INCLUDE_DIR})
ADD_DEFINITIONS(-DWITH_LOG4CXX)
else()
message(FATAL_ERROR "Logging : no (install log4cxx-devel)")
set(LOG4CXX_LIBRARIES "")
message("Log4cxx : no (install log4cxx-devel)")
endif()
if (WIN32)
@ -218,6 +224,7 @@ ADD_SUBDIRECTORY(spectrum)
ADD_SUBDIRECTORY(backends)
if (NOT WIN32)
ADD_SUBDIRECTORY(spectrum_manager)
# ADD_SUBDIRECTORY(spectrum2_send_message)
endif()
if (CPPUNIT_FOUND)

View file

@ -1,6 +1,64 @@
Version 2.0.0-beta (X-X-X):
Version 2.0.0-beta3 (2012-XX-XX):
General:
* Log errors related to backend spawning (Show proper log message for
example when path to backend binary is not found).
* Update buddies in database only when it's needed and do not execute
useless database statements.
* Send roster changes also when buddy's group change.
* Fixed bug when transport contact we in all groups.
* Answer to disco#info IQ with proper node (#206).
* Set SQLite3 as default database backend.
* Fixed disconnecting from server caused by sending VCard response
with bad "from" attribute.
* Added Munin plugin (Thanks to Askovpen).
* Added support for more admin_jid JIDs (Thanks to Askovpen).
* Fixed allowed_servers option.
Libpurple:
* prpl-gg: Fetch the contact list properly (#252).
Skype:
* Log more errors.
Backend API:
* Added Python NetworkPlugin class, so it is now easier to write backends
in Python (Thanks to Sarang).
Version 2.0.0-beta2 (2012-03-28):
General:
* Fixed bug when Roster Item Exchange and subscribe stanzas were sent
repeatedly.
* Backends related logs now contain the backend PID.
* Fixed username_mask setting.
* Added new fields into statistics (backends_crashed, messages related
stats).
* Chatstates are now not counted as incoming messages in stats.
* Log4cxx is now optional dependency. Without Log4cxx, Spectrum 2 logs
to standard output.
* Fixed crash when Log4cxx configuration file didn't exist.
* Admin can now see "Admin" contact in server-mode.
libpurple:
* Added initial support for MUC for prpl-jabber protocol.
LibCommuni IRC backend:
* Fixed sending/receiving UTF8 messages.
* Using the [registration] auto_register=1 config option, users don't
have to register manually when connecting IRC network.
Skype:
* Memory usage statistic now includes the Skype client.
* Fixed logging issue when the logs were not stored in the proper instance
directory.
* Skype backend includes also Skype client memory usage into the account.
* Working buddies adding/removing.
* Information about missed call is now forwarded to XMPP user.
* Fixed bug when Skype client instance wasn't killed by backend.
Version 2.0.0-beta (2012-02-28):
General:
* Added PostreSQL support (thanks to Jadestorm).
* Added XEP-0100 (Gateway interaction) support.
* Send presences only "from" bare JID (fixed bug with buddies appearing
twice in the roster and potential unregistering issues).
* Fixed potential MySQL/SQLite3 deadlocks.

View file

@ -9,6 +9,8 @@ if (PROTOBUF_FOUND)
ADD_SUBDIRECTORY(smstools3)
ADD_SUBDIRECTORY(template)
if (NOT WIN32)
ADD_SUBDIRECTORY(frotz)
if (${LIBDBUSGLIB_FOUND})

View file

@ -2,10 +2,13 @@
#include <IrcCommand>
#include <IrcMessage>
#define FROM_UTF8(WHAT) QString::fromUtf8((WHAT).c_str(), (WHAT).size())
#define TO_UTF8(WHAT) std::string((WHAT).toUtf8().data(), (WHAT).toUtf8().size())
IRCNetworkPlugin::IRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port) {
this->config = config;
m_socket = new QTcpSocket();
m_socket->connectToHost(QString::fromStdString(host), port);
m_socket->connectToHost(FROM_UTF8(host), port);
connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData()));
}
@ -28,8 +31,8 @@ void IRCNetworkPlugin::handleLoginRequest(const std::string &user, const std::st
if (CONFIG_BOOL(config, "service.server_mode")) {
MyIrcSession *session = new MyIrcSession(user, this);
std::string h = user.substr(0, user.find("@"));
session->setNickName(QString::fromStdString(h.substr(0, h.find("%"))));
session->setHost(QString::fromStdString(h.substr(h.find("%") + 1)));
session->setNickName(FROM_UTF8(h.substr(0, h.find("%"))));
session->setHost(FROM_UTF8(h.substr(h.find("%") + 1)));
session->setPort(6667);
session->open();
std::cout << "CONNECTING IRC NETWORK " << h.substr(h.find("%") + 1) << "\n";
@ -72,7 +75,7 @@ void IRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const s
}
}
std::cout << "MESSAGE " << u << " " << r << "\n";
m_sessions[u]->sendCommand(IrcCommand::createMessage(QString::fromStdString(r), QString::fromStdString(message)));
m_sessions[u]->sendCommand(IrcCommand::createMessage(FROM_UTF8(r), FROM_UTF8(message)));
std::cout << "SENT\n";
}
@ -89,8 +92,8 @@ void IRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std:
if (room.find("@") != std::string::npos) {
// suffix is %irc.freenode.net to let MyIrcSession return #room%irc.freenode.net
MyIrcSession *session = new MyIrcSession(user, this, room.substr(room.find("@")));
session->setNickName(QString::fromStdString(nickname));
session->setHost(QString::fromStdString(room.substr(room.find("@") + 1)));
session->setNickName(FROM_UTF8(nickname));
session->setHost(FROM_UTF8(room.substr(room.find("@") + 1)));
session->setPort(6667);
session->open();
std::cout << "CONNECTING IRC NETWORK " << room.substr(room.find("@") + 1) << "\n";
@ -103,10 +106,10 @@ void IRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std:
}
std::cout << "JOINING " << r << "\n";
m_sessions[u]->addAutoJoinChannel(r);
m_sessions[u]->sendCommand(IrcCommand::createJoin(QString::fromStdString(r), QString::fromStdString(password)));
m_sessions[u]->sendCommand(IrcCommand::createJoin(FROM_UTF8(r), FROM_UTF8(password)));
m_sessions[u]->rooms += 1;
// update nickname, because we have nickname per session, no nickname per room.
handleRoomNicknameChanged(user, r, m_sessions[u]->nickName().toStdString());
handleRoomNicknameChanged(user, r, TO_UTF8(m_sessions[u]->nickName()));
}
void IRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std::string &room) {
@ -120,7 +123,7 @@ void IRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std
if (m_sessions[u] == NULL)
return;
m_sessions[u]->sendCommand(IrcCommand::createPart(QString::fromStdString(r)));
m_sessions[u]->sendCommand(IrcCommand::createPart(FROM_UTF8(r)));
m_sessions[u]->removeAutoJoinChannel(r);
m_sessions[u]->rooms -= 1;

View file

@ -10,6 +10,7 @@
#include "transport/config.h"
#include "transport/networkplugin.h"
#include "transport/logging.h"
#include "session.h"
#include <QtCore>
#include <QtNetwork>
@ -17,19 +18,9 @@
#include "ircnetworkplugin.h"
#include "singleircnetworkplugin.h"
#include "log4cxx/logger.h"
#include "log4cxx/consoleappender.h"
#include "log4cxx/patternlayout.h"
#include "log4cxx/propertyconfigurator.h"
#include "log4cxx/helpers/properties.h"
#include "log4cxx/helpers/fileinputstream.h"
#include "log4cxx/helpers/transcoder.h"
using namespace boost::program_options;
using namespace Transport;
using namespace log4cxx;
NetworkPlugin * np = NULL;
int main (int argc, char* argv[]) {
@ -83,30 +74,7 @@ int main (int argc, char* argv[]) {
}
QCoreApplication app(argc, argv);
if (CONFIG_STRING(&config, "logging.backend_config").empty()) {
LoggerPtr root = log4cxx::Logger::getRootLogger();
#ifndef _MSC_VER
root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n")));
#else
root->addAppender(new ConsoleAppender(new PatternLayout(L"%d %-5p %c: %m%n")));
#endif
}
else {
log4cxx::helpers::Properties p;
log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(&config, "logging.backend_config"));
p.load(istream);
LogString pid, jid;
log4cxx::helpers::Transcoder::decode(boost::lexical_cast<std::string>(getpid()), pid);
log4cxx::helpers::Transcoder::decode(CONFIG_STRING(&config, "service.jid"), jid);
#ifdef _MSC_VER
p.setProperty(L"pid", pid);
p.setProperty(L"jid", jid);
#else
p.setProperty("pid", pid);
p.setProperty("jid", jid);
#endif
log4cxx::PropertyConfigurator::configure(p);
}
Logging::initBackendLogging(&config);
Swift::QtEventLoop eventLoop;

View file

@ -15,11 +15,12 @@
#include <IrcCommand>
#include <IrcMessage>
#include "log4cxx/logger.h"
#define FROM_UTF8(WHAT) QString::fromUtf8((WHAT).c_str(), (WHAT).size())
#define TO_UTF8(WHAT) std::string((WHAT).toUtf8().data(), (WHAT).toUtf8().size())
using namespace log4cxx;
#include "transport/logging.h"
static LoggerPtr logger = log4cxx::Logger::getLogger("IRCSession");
DEFINE_LOGGER(logger, "IRCSession");
MyIrcSession::MyIrcSession(const std::string &user, NetworkPlugin *np, const std::string &suffix, QObject* parent) : IrcSession(parent)
{
@ -40,13 +41,13 @@ void MyIrcSession::on_connected() {
}
for(std::list<std::string>::const_iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) {
sendCommand(IrcCommand::createJoin(QString::fromStdString(*it)));
sendCommand(IrcCommand::createJoin(FROM_UTF8(*it)));
}
if (getIdentify().find(" ") != std::string::npos) {
std::string to = getIdentify().substr(0, getIdentify().find(" "));
std::string what = getIdentify().substr(getIdentify().find(" ") + 1);
sendCommand(IrcCommand::createMessage(QString::fromStdString(to), QString::fromStdString(what)));
sendCommand(IrcCommand::createMessage(FROM_UTF8(to), FROM_UTF8(what)));
}
}
@ -69,30 +70,30 @@ bool MyIrcSession::correctNickname(std::string &nickname) {
void MyIrcSession::on_joined(IrcMessage *message) {
IrcJoinMessage *m = (IrcJoinMessage *) message;
bool flags = 0;
std::string nickname = m->sender().name().toStdString();
std::string nickname = TO_UTF8(m->sender().name());
flags = correctNickname(nickname);
np->handleParticipantChanged(user, nickname, m->channel().toStdString() + suffix, (int) flags, pbnetwork::STATUS_ONLINE);
LOG4CXX_INFO(logger, user << ": Joined " << m->parameters()[0].toStdString());
np->handleParticipantChanged(user, nickname, TO_UTF8(m->channel()), (int) flags, pbnetwork::STATUS_ONLINE);
LOG4CXX_INFO(logger, user << ": Joined " << TO_UTF8(m->parameters()[0]));
}
void MyIrcSession::on_parted(IrcMessage *message) {
IrcPartMessage *m = (IrcPartMessage *) message;
bool flags = 0;
std::string nickname = m->sender().name().toStdString();
std::string nickname = TO_UTF8(m->sender().name());
flags = correctNickname(nickname);
LOG4CXX_INFO(logger, user << ": " << nickname << " parted " << m->channel().toStdString() + suffix);
np->handleParticipantChanged(user, nickname, m->channel().toStdString() + suffix,(int) flags, pbnetwork::STATUS_NONE, m->reason().toStdString());
LOG4CXX_INFO(logger, user << ": " << nickname << " parted " << TO_UTF8(m->channel()) + suffix);
np->handleParticipantChanged(user, nickname, TO_UTF8(m->channel()) + suffix,(int) flags, pbnetwork::STATUS_NONE, TO_UTF8(m->reason()));
}
void MyIrcSession::on_quit(IrcMessage *message) {
IrcQuitMessage *m = (IrcQuitMessage *) message;
for(std::list<std::string>::const_iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) {
bool flags = 0;
std::string nickname = m->sender().name().toStdString();
std::string nickname = TO_UTF8(m->sender().name());
flags = correctNickname(nickname);
LOG4CXX_INFO(logger, user << ": " << nickname << " quit " << (*it) + suffix);
np->handleParticipantChanged(user, nickname, (*it) + suffix,(int) flags, pbnetwork::STATUS_NONE, m->reason().toStdString());
np->handleParticipantChanged(user, nickname, (*it) + suffix,(int) flags, pbnetwork::STATUS_NONE, TO_UTF8(m->reason()));
}
}
@ -100,10 +101,10 @@ void MyIrcSession::on_nickChanged(IrcMessage *message) {
IrcNickMessage *m = (IrcNickMessage *) message;
for(std::list<std::string>::const_iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) {
std::string nickname = m->sender().name().toStdString();
std::string nickname = TO_UTF8(m->sender().name());
bool flags = m_modes[(*it) + nickname];
LOG4CXX_INFO(logger, user << ": " << nickname << " changed nickname to " << m->nick().toStdString());
np->handleParticipantChanged(user, nickname, (*it) + suffix,(int) flags, pbnetwork::STATUS_ONLINE, "", m->nick().toStdString());
LOG4CXX_INFO(logger, user << ": " << nickname << " changed nickname to " << TO_UTF8(m->nick()));
np->handleParticipantChanged(user, nickname, (*it) + suffix,(int) flags, pbnetwork::STATUS_ONLINE, "", TO_UTF8(m->nick()));
}
}
@ -111,8 +112,8 @@ void MyIrcSession::on_modeChanged(IrcMessage *message) {
IrcModeMessage *m = (IrcModeMessage *) message;
// mode changed: "#testik" "HanzZ" "+o" "hanzz_k"
std::string nickname = m->argument().toStdString();
std::string mode = m->mode().toStdString();
std::string nickname = TO_UTF8(m->argument());
std::string mode = TO_UTF8(m->mode());
if (nickname.empty())
return;
LOG4CXX_INFO(logger, user << ": " << nickname << " changed mode to " << mode);
@ -132,29 +133,29 @@ void MyIrcSession::on_topicChanged(IrcMessage *message) {
IrcTopicMessage *m = (IrcTopicMessage *) message;
bool flags = 0;
std::string nickname = m->sender().name().toStdString();
std::string nickname = TO_UTF8(m->sender().name());
flags = correctNickname(nickname);
LOG4CXX_INFO(logger, user << ": " << nickname << " topic changed to " << m->topic().toStdString());
np->handleSubject(user, m->channel().toStdString() + suffix, m->topic().toStdString(), nickname);
LOG4CXX_INFO(logger, user << ": " << nickname << " topic changed to " << TO_UTF8(m->topic()));
np->handleSubject(user, TO_UTF8(m->channel()) + suffix, TO_UTF8(m->topic()), nickname);
}
void MyIrcSession::on_messageReceived(IrcMessage *message) {
IrcPrivateMessage *m = (IrcPrivateMessage *) message;
std::string target = m->target().toStdString();
std::string target = TO_UTF8(m->target());
LOG4CXX_INFO(logger, user << ": Message from " << target);
if (target.find("#") == 0) {
bool flags = 0;
std::string nickname = m->sender().name().toStdString();
std::string nickname = TO_UTF8(m->sender().name());
flags = correctNickname(nickname);
np->handleMessage(user, target + suffix, m->message().toStdString(), nickname);
np->handleMessage(user, target + suffix, TO_UTF8(m->message()), nickname);
}
else {
bool flags = 0;
std::string nickname = m->sender().name().toStdString();
std::string nickname = TO_UTF8(m->sender().name());
flags = correctNickname(nickname);
np->handleMessage(user, nickname, m->message().toStdString());
np->handleMessage(user, nickname, TO_UTF8(m->message()));
}
}
@ -165,10 +166,10 @@ void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
IrcNumericMessage *m = (IrcNumericMessage *) message;
switch (m->code()) {
case 332:
m_topicData = m->parameters().value(2).toStdString();
m_topicData = TO_UTF8(m->parameters().value(2));
break;
case 333:
np->handleSubject(user, m->parameters().value(1).toStdString() + suffix, m_topicData, m->parameters().value(2).toStdString());
np->handleSubject(user, TO_UTF8(m->parameters().value(1)) + suffix, m_topicData, TO_UTF8(m->parameters().value(2)));
break;
case 353:
channel = m->parameters().value(2);
@ -176,10 +177,10 @@ void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
for (int i = 0; i < members.size(); i++) {
bool flags = 0;
std::string nickname = members.at(i).toStdString();
std::string nickname = TO_UTF8(members.at(i));
flags = correctNickname(nickname);
m_modes[channel.toStdString() + nickname] = flags;
np->handleParticipantChanged(user, nickname, channel.toStdString() + suffix,(int) flags, pbnetwork::STATUS_ONLINE);
m_modes[TO_UTF8(channel) + nickname] = flags;
np->handleParticipantChanged(user, nickname, TO_UTF8(channel) + suffix,(int) flags, pbnetwork::STATUS_ONLINE);
}
break;
case 432:
@ -195,7 +196,7 @@ void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
}
void MyIrcSession::onMessageReceived(IrcMessage *message) {
LOG4CXX_INFO(logger, user << ": " << message->toString().toStdString());
LOG4CXX_INFO(logger, user << ": " << TO_UTF8(message->toString()));
switch (message->type()) {
case IrcMessage::Join:
on_joined(message);

View file

@ -1,17 +1,18 @@
#include "singleircnetworkplugin.h"
#include "log4cxx/logger.h"
#include "transport/logging.h"
#include <IrcCommand>
#include <IrcMessage>
using namespace log4cxx;
#define FROM_UTF8(WHAT) QString::fromUtf8((WHAT).c_str(), (WHAT).size())
#define TO_UTF8(WHAT) std::string((WHAT).toUtf8().data(), (WHAT).toUtf8().size())
static LoggerPtr logger = log4cxx::Logger::getLogger("SingleIRCNetworkPlugin");
DEFINE_LOGGER(logger, "SingleIRCNetworkPlugin");
SingleIRCNetworkPlugin::SingleIRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port) {
this->config = config;
m_server = config->getUnregistered().find("service.irc_server")->second;
m_socket = new QTcpSocket();
m_socket->connectToHost(QString::fromStdString(host), port);
m_socket->connectToHost(FROM_UTF8(host), port);
connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData()));
if (config->getUnregistered().find("service.irc_identify") != config->getUnregistered().end()) {
@ -46,16 +47,18 @@ void SingleIRCNetworkPlugin::handleLoginRequest(const std::string &user, const s
LOG4CXX_INFO(logger, user << ": Connecting " << m_server << " as " << legacyName);
MyIrcSession *session = new MyIrcSession(user, this);
session->setUserName(QString::fromStdString(legacyName));
session->setNickName(QString::fromStdString(legacyName));
session->setRealName(QString::fromStdString(legacyName));
session->setHost(QString::fromStdString(m_server));
session->setUserName(FROM_UTF8(legacyName));
session->setNickName(FROM_UTF8(legacyName));
session->setRealName(FROM_UTF8(legacyName));
session->setHost(FROM_UTF8(m_server));
session->setPort(6667);
std::string identify = m_identify;
boost::replace_all(identify, "$password", password);
boost::replace_all(identify, "$name", legacyName);
session->setIdentify(identify);
if (!password.empty()) {
std::string identify = m_identify;
boost::replace_all(identify, "$password", password);
boost::replace_all(identify, "$name", legacyName);
session->setIdentify(identify);
}
session->open();
@ -90,10 +93,10 @@ void SingleIRCNetworkPlugin::handleMessageSendRequest(const std::string &user, c
}
LOG4CXX_INFO(logger, user << ": Forwarding message to " << r);
m_sessions[user]->sendCommand(IrcCommand::createMessage(QString::fromStdString(r), QString::fromStdString(message)));
m_sessions[user]->sendCommand(IrcCommand::createMessage(FROM_UTF8(r), FROM_UTF8(message)));
if (r.find("#") == 0) {
handleMessage(user, legacyName, message, m_sessions[user]->nickName().toStdString());
handleMessage(user, legacyName, message, TO_UTF8(m_sessions[user]->nickName()));
}
}
@ -105,11 +108,11 @@ void SingleIRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, cons
LOG4CXX_INFO(logger, user << ": Joining " << room);
m_sessions[user]->addAutoJoinChannel(room);
m_sessions[user]->sendCommand(IrcCommand::createJoin(QString::fromStdString(room), QString::fromStdString(password)));
m_sessions[user]->sendCommand(IrcCommand::createJoin(FROM_UTF8(room), FROM_UTF8(password)));
m_sessions[user]->rooms += 1;
// update nickname, because we have nickname per session, no nickname per room.
handleRoomNicknameChanged(user, room, m_sessions[user]->userName().toStdString());
handleRoomNicknameChanged(user, room, TO_UTF8(m_sessions[user]->userName()));
}
void SingleIRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std::string &room) {
@ -122,7 +125,7 @@ void SingleIRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, con
}
LOG4CXX_INFO(logger, user << ": Leaving " << room);
m_sessions[u]->sendCommand(IrcCommand::createPart(QString::fromStdString(r)));
m_sessions[u]->sendCommand(IrcCommand::createPart(FROM_UTF8(r)));
m_sessions[u]->removeAutoJoinChannel(r);
m_sessions[u]->rooms -= 1;
}

View file

@ -0,0 +1,251 @@
import sys
import os
# intialize for methods used in libpurple macros
methods = ["purple_connection_get_state(", "purple_conversation_get_im_data(",
"purple_conversation_get_chat_data(", "purple_blist_node_get_type("]
macros = ["PURPLE_CONV_IM", "PURPLE_CONV_CHAT", "PURPLE_BLIST_NODE_IS_BUDDY", "PURPLE_CONNECTION_IS_CONNECTED"]
definitions = []
if len(sys.argv) != 2:
print "Usage:", sys.argv[0], "<path_to_libpurple_dir_containing_libpurple_headers>"
sys.exit(1)
def handle_file(cpp):
global methods
global macros
sys.stdout.write("getting used methods in " + cpp + ": ")
sys.stdout.flush()
counter = 0
new_file = ""
f = open(cpp, "r")
for line in f.readlines():
new_line = ""
index = 0
while index < len(line):
new_line += line[index]
if line[index:].startswith("purple_") or line[index:].startswith("wpurple_") or line[index:].startswith("serv_"):
if line[index:].find("=") != -1 and line[index:].find("=") < line[index:].find("("):
index += 1
continue
if line[index-1] == "_" or line[index:].find("(") == -1 or line[index:].startswith("purple_commands_init") or line[index:].startswith("serv_addr"):
index += 1
continue
m = line[index:line[index:].find("(")+index]
index += len(m)
if m.find("_wrapped") != -1:
new_line += m[1:] + "("
m = m.replace("_wrapped", "")
else:
new_line += m[1:] + "_wrapped("
if not m + "(" in methods and len(m) != 0:
methods += [m + "("]
counter += 1
index += 1
for x in macros:
if new_line.find(x + "_WRAPPED") == -1:
new_line = new_line.replace(x, x + "_WRAPPED")
new_file += new_line
f.close()
print counter, "new methods found"
return new_file
def handle_header(header, method):
global definitions
f = open(os.path.join(sys.argv[1], header), "r")
lines = f.readlines()
for i in range(len(lines)):
line = lines[i]
if line.find(method) != -1:
if line.startswith(method):
line = lines[i-1][:-1] + line
m = line[:-1]
l = unicode(m).strip()
if l.endswith(")"):
continue
if m.find("/*") > m.find(";"):
m = m[:m.find("/*")]
m.rstrip()
if len(m) != 0:
while m[-1] == " ":
m = m[:-1]
index = i;
while not m.endswith(";"):
index += 1
m += " " + lines[index][:-1].lstrip()
l = unicode(m).strip()
if (l.startswith("#") or l.startswith("*") or l.startswith("/*") or l.count("***") != 0 or l.count("&&") != 0
or l.endswith(")")):
continue;
m = m.replace("G_GNUC_NULL_TERMINATE", "")
if not m in definitions:
print "found", method[:-1], "in", header
definitions += [m]
break
f.close()
def get_raw_args(d):
return d[d.find("(")+1:-2]
def get_args(d):
x = d[d.find("(")+1:-2]
x = x.split(",")
args = []
for arg in x:
y = arg.split(" ")
if len(y) == 1:
continue
args += [y[-1].replace("*", "")]
return args
def get_name(d):
x = d[:d.find("(")+1].lstrip()
if x.find("wpurple_") != -1:
return x[x.find("wpurple_"):]
if x.find("serv_") != -1:
return x[x.find("serv_"):]
return x[x.find("purple_"):]
def get_rtype(d):
if d.find("wpurple_") != -1:
return d[:d.find("wpurple_")].lstrip()
if d.find("serv_") != -1:
return d[:d.find("serv_")].lstrip()
return d[:d.find("purple_")].lstrip()
def output():
global definitions
header = open("purple_defs.h", "w")
print >> header, "#pragma once"
print >> header, "#ifdef WIN32"
print >> header, """
#include <Windows.h>
#include <purple.h>
#define PURPLE_BLIST_NODE_IS_CHAT_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_CHAT_NODE)
#define PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_BUDDY_NODE)
#define PURPLE_BLIST_NODE_IS_CONTACT_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_CONTACT_NODE)
#define PURPLE_BLIST_NODE_IS_GROUP_WRAPPED(n) (purple_blist_node_get_type_wrapped(n) == PURPLE_BLIST_GROUP_NODE)
#define PURPLE_CONV_IM_WRAPPED(c) (purple_conversation_get_im_data_wrapped(c))
#define PURPLE_CONV_CHAT_WRAPPED(c) (purple_conversation_get_chat_data_wrapped(c))
#define PURPLE_CONNECTION_IS_CONNECTED_WRAPPED(gc) \
(purple_connection_get_state_wrapped(gc) == PURPLE_CONNECTED)
"""
for d in definitions:
#typedef void (_cdecl * purple_util_set_user_wrapped_func)(const char *dir);
print >> header, "typedef", get_rtype(d), "(_cdecl *", get_name(d)[:-1] + "_wrapped_fnc)(" + get_raw_args(d) + ");"
#extern purple_util_set_user_wrapped_func purple_util_set_user_wrapped;
print >> header, "extern", get_name(d)[:-1] + "_wrapped_fnc", get_name(d)[:-1] + "_wrapped;"
print >> header, ""
print >> header, ""
print >> header, "#else"
print >> header, ""
print >> header, """
#define PURPLE_BLIST_NODE_IS_CHAT_WRAPPED PURPLE_BLIST_NODE_IS_CHAT
#define PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED PURPLE_BLIST_NODE_IS_BUDDY
#define PURPLE_BLIST_NODE_IS_CONTACT_WRAPPED PURPLE_BLIST_NODE_IS_CONTACT
#define PURPLE_BLIST_NODE_IS_GROUP_WRAPPED PURPLE_BLIST_NODE_IS_GROUP
#define PURPLE_CONV_IM_WRAPPED PURPLE_CONV_IM
#define PURPLE_CONV_CHAT_WRAPPED PURPLE_CONV_CHAT
#define PURPLE_CONNECTION_IS_CONNECTED_WRAPPED PURPLE_CONNECTION_IS_CONNECTED
"""
for d in definitions:
#define purple_util_set_user_wrapped purple_util_set_user
print >> header, "#define", get_name(d)[:-1] + "_wrapped", get_name(d)[:-1]
print >> header, "#endif"
print >> header, ""
print >> header, "bool resolvePurpleFunctions();"
print >> header, ""
cpp = open("purple_defs.cpp", "w")
print >> cpp, "#include \"purple_defs.h\""
print >> cpp, ""
print >> cpp, "#ifdef WIN32"
print >> cpp, "static HMODULE f_hPurple = NULL;"
for d in definitions:
#purple_util_set_user_wrapped_fnc purple_util_set_user_wrapped = NULL;
print >> cpp, get_name(d)[:-1] + "_wrapped_fnc", get_name(d)[:-1] + "_wrapped = NULL;"
print >> cpp, "#endif"
print >> cpp, "bool resolvePurpleFunctions() {"
print >> cpp, "#ifdef WIN32"
print >> cpp, "\tf_hPurple = LoadLibrary(\"libpurple.dll\");"
print >> cpp, "\tif (!f_hPurple)"
print >> cpp, "\t\t\treturn false;"
for d in definitions:
#purple_util_set_user_wrapped = (purple_util_set_user_wrapped_func)GetProcAddress(f_hPurple, "purple_util_set_user_dir");
print >> cpp, "\t" + get_name(d)[:-1] + "_wrapped = (" + get_name(d)[:-1] + "_wrapped_fnc)GetProcAddress(f_hPurple, \"" + get_name(d)[:-1] + "\");"
#if (!purple_util_set_user_wrapped)
print >> cpp, "\tif (!" + get_name(d)[:-1] + "_wrapped)"
print >> cpp, "\t\treturn false;"
print >> cpp, ""
print >> cpp, "#endif"
print >> cpp, "\treturn true;"
print >> cpp, "}"
print >> cpp, ""
cpp.close()
header.close()
for f in os.listdir("."):
if not f.endswith(".cpp") or f.startswith("purple_defs"):
continue
new_file = handle_file(f)
print "updating", f
fd = open(f, "w")
fd.write(new_file)
fd.close()
for f in os.listdir(sys.argv[1]):
if not f.endswith(".h"):
continue
for m in methods:
handle_header(f, m)
sys.argv[1] = sys.argv[1] + "/win32"
for f in os.listdir(sys.argv[1]):
if not f.endswith(".h"):
continue
for m in methods:
handle_header(f, m)
for m in methods:
found = False
for d in definitions:
if d.find(m[:-1]) != -1:
found = True
break
if not found:
print "NOT FOUND:", m
output()

View file

@ -28,11 +28,11 @@
#include "event.h"
#endif
#include "log4cxx/logger.h"
#include "purple_defs.h"
using namespace log4cxx;
#include "transport/logging.h"
static LoggerPtr logger = Logger::getLogger("EventLoop");
DEFINE_LOGGER(logger, "EventLoop");
typedef struct _PurpleIOClosure {
PurpleInputFunction function;

View file

@ -1,36 +1,16 @@
#include "utils.h"
#include "glib.h"
#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 "log4cxx/logger.h"
#include "log4cxx/consoleappender.h"
#include "log4cxx/patternlayout.h"
#include "log4cxx/propertyconfigurator.h"
#include "log4cxx/helpers/properties.h"
#include "log4cxx/helpers/fileinputstream.h"
#include "log4cxx/helpers/transcoder.h"
#ifndef WIN32
#include "sys/wait.h"
#include "sys/signal.h"
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <netinet/ether.h>
#include "sys/socket.h"
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#else
#include <process.h>
#define getpid _getpid
#define ssize_t SSIZE_T
#include "win32/win32dep.h"
#endif
// #include "valgrind/memcheck.h"
#include "malloc.h"
#include <algorithm>
@ -40,11 +20,19 @@
#include <event.h>
#endif
using namespace log4cxx;
#ifdef WIN32
#include "win32/win32dep.h"
#define ssize_t SSIZE_T
#include <process.h>
#define getpid _getpid
#endif
static LoggerPtr logger_libpurple = log4cxx::Logger::getLogger("libpurple");
static LoggerPtr logger = log4cxx::Logger::getLogger("backend");
int m_sock;
#include "purple_defs.h"
DEFINE_LOGGER(logger_libpurple, "libpurple");
DEFINE_LOGGER(logger, "backend");
int main_socket;
static int writeInput;
using namespace Transport;
@ -62,6 +50,21 @@ template <class T> std::string stringOf(T 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;
@ -89,7 +92,7 @@ static std::string KEYFILE_STRING(const std::string &cat, const std::string &key
return def;
}
std::string ret(str);
free(str);
g_free(str);
if (ret.find("#") != std::string::npos) {
ret = ret.substr(0, ret.find("#"));
@ -107,13 +110,8 @@ static std::string KEYFILE_STRING(const std::string &cat, const std::string &key
#define KEYFILE_BOOL(CAT, KEY) g_key_file_get_boolean(keyfile, CAT, KEY, 0)
static gboolean nodaemon = FALSE;
static gchar *logfile = NULL;
static gchar *lock_file = NULL;
static gchar *host = NULL;
static int port = 10000;
static gboolean ver = FALSE;
static gboolean list_purple_settings = FALSE;
struct FTData {
unsigned long id;
@ -122,121 +120,12 @@ struct FTData {
};
static GOptionEntry options_entries[] = {
{ "nodaemon", 'n', 0, G_OPTION_ARG_NONE, &nodaemon, "Disable background daemon mode", NULL },
{ "logfile", 'l', 0, G_OPTION_ARG_STRING, &logfile, "Set file to log", NULL },
{ "pidfile", 'p', 0, G_OPTION_ARG_STRING, &lock_file, "File where to write transport PID", NULL },
{ "version", 'v', 0, G_OPTION_ARG_NONE, &ver, "Shows Spectrum version", NULL },
{ "list-purple-settings", 's', 0, G_OPTION_ARG_NONE, &list_purple_settings, "Lists purple settings which can be used in config file", NULL },
{ "host", 'h', 0, G_OPTION_ARG_STRING, &host, "Host to connect to", NULL },
{ "port", 'p', 0, G_OPTION_ARG_INT, &port, "Port to connect to", NULL },
{ NULL, 0, 0, G_OPTION_ARG_NONE, NULL, "", NULL }
};
static void *notify_user_info(PurpleConnection *gc, const char *who, PurpleNotifyUserInfo *user_info);
static GHashTable *ui_info = NULL;
static GHashTable *spectrum_ui_get_info(void)
{
if(NULL == ui_info) {
ui_info = g_hash_table_new(g_str_hash, g_str_equal);
g_hash_table_insert(ui_info, g_strdup("name"), g_strdup("Spectrum"));
g_hash_table_insert(ui_info, g_strdup("version"), g_strdup("0.5"));
g_hash_table_insert(ui_info, g_strdup("website"), g_strdup("http://spectrum.im"));
g_hash_table_insert(ui_info, g_strdup("dev_website"), g_strdup("http://spectrum.im"));
g_hash_table_insert(ui_info, g_strdup("client_type"), g_strdup("pc"));
/*
* This is the client key for "Pidgin." It is owned by the AIM
* account "markdoliner." Please don't use this key for other
* applications. You can either not specify a client key, in
* which case the default "libpurple" key will be used, or you
* can register for your own client key at
* http://developer.aim.com/manageKeys.jsp
*/
g_hash_table_insert(ui_info, g_strdup("prpl-aim-clientkey"), g_strdup("ma1cSASNCKFtrdv9"));
g_hash_table_insert(ui_info, g_strdup("prpl-icq-clientkey"), g_strdup("ma1cSASNCKFtrdv9"));
/*
* This is the distid for Pidgin, given to us by AOL. Please
* don't use this for other applications. You can just not
* specify a distid and libpurple will use a default.
*/
g_hash_table_insert(ui_info, g_strdup("prpl-aim-distid"), GINT_TO_POINTER(1550));
g_hash_table_insert(ui_info, g_strdup("prpl-icq-distid"), GINT_TO_POINTER(1550));
}
return ui_info;
}
static gboolean
badchar(char c)
{
switch (c) {
case ' ':
case ',':
case '\0':
case '\n':
case '\r':
case '<':
case '>':
case '"':
return TRUE;
default:
return FALSE;
}
}
static gboolean
badentity(const char *c)
{
if (!g_ascii_strncasecmp(c, "&lt;", 4) ||
!g_ascii_strncasecmp(c, "&gt;", 4) ||
!g_ascii_strncasecmp(c, "&quot;", 6)) {
return TRUE;
}
return FALSE;
}
static const char *
process_link(GString *ret,
const char *start, const char *c,
int matchlen,
const char *urlprefix,
int inside_paren)
{
char *url_buf;
const char *t;
for (t = c;; t++) {
if (!badchar(*t) && !badentity(t))
continue;
if (t - c == matchlen)
break;
if (*t == ',' && *(t + 1) != ' ') {
continue;
}
if (t > start && *(t - 1) == '.')
t--;
if (t > start && *(t - 1) == ')' && inside_paren > 0)
t--;
url_buf = g_strndup(c, t - c);
// tmpurlbuf = purple_unescape_html(url_buf);
// std::cout << url_buf << "\n";
g_string_append_printf(ret, "<A HREF=\"%s%s\">%s</A>",
urlprefix,
url_buf, url_buf);
// g_free(tmpurlbuf);
g_free(url_buf);
return t;
}
return c;
}
static gboolean ft_ui_ready(void *data) {
PurpleXfer *xfer = (PurpleXfer *) data;
@ -246,184 +135,6 @@ static gboolean ft_ui_ready(void *data) {
return FALSE;
}
static char *
spectrum_markup_linkify(const char *text)
{
const char *c, *t, *q = NULL;
char *tmpurlbuf, *url_buf;
gunichar g;
gboolean inside_html = FALSE;
int inside_paren = 0;
GString *ret;
if (text == NULL)
return NULL;
ret = g_string_new("");
c = text;
while (*c) {
if(*c == '(' && !inside_html) {
inside_paren++;
ret = g_string_append_c(ret, *c);
c++;
}
if(inside_html) {
if(*c == '>') {
inside_html = FALSE;
} else if(!q && (*c == '\"' || *c == '\'')) {
q = c;
} else if(q) {
if(*c == *q)
q = NULL;
}
} else if(*c == '<') {
inside_html = TRUE;
if (!g_ascii_strncasecmp(c, "<A", 2)) {
while (1) {
if (!g_ascii_strncasecmp(c, "/A>", 3)) {
inside_html = FALSE;
break;
}
ret = g_string_append_c(ret, *c);
c++;
if (!(*c))
break;
}
}
} else if (!g_ascii_strncasecmp(c, "http://", 7)) {
c = process_link(ret, text, c, 7, "", inside_paren);
} else if (!g_ascii_strncasecmp(c, "https://", 8)) {
c = process_link(ret, text, c, 8, "", inside_paren);
} else if (!g_ascii_strncasecmp(c, "ftp://", 6)) {
c = process_link(ret, text, c, 6, "", inside_paren);
} else if (!g_ascii_strncasecmp(c, "sftp://", 7)) {
c = process_link(ret, text, c, 7, "", inside_paren);
} else if (!g_ascii_strncasecmp(c, "file://", 7)) {
c = process_link(ret, text, c, 7, "", inside_paren);
} else if (!g_ascii_strncasecmp(c, "www.", 4) && c[4] != '.' && (c == text || badchar(c[-1]) || badentity(c-1))) {
c = process_link(ret, text, c, 4, "http://", inside_paren);
} else if (!g_ascii_strncasecmp(c, "ftp.", 4) && c[4] != '.' && (c == text || badchar(c[-1]) || badentity(c-1))) {
c = process_link(ret, text, c, 4, "ftp://", inside_paren);
} else if (!g_ascii_strncasecmp(c, "xmpp:", 5) && (c == text || badchar(c[-1]) || badentity(c-1))) {
c = process_link(ret, text, c, 5, "", inside_paren);
} else if (!g_ascii_strncasecmp(c, "mailto:", 7)) {
t = c;
while (1) {
if (badchar(*t) || badentity(t)) {
const char *d;
if (t - c == 7) {
break;
}
if (t > text && *(t - 1) == '.')
t--;
if ((d = strstr(c + 7, "?")) != NULL && d < t)
url_buf = g_strndup(c + 7, d - c - 7);
else
url_buf = g_strndup(c + 7, t - c - 7);
if (!purple_email_is_valid(url_buf)) {
g_free(url_buf);
break;
}
g_free(url_buf);
url_buf = g_strndup(c, t - c);
// tmpurlbuf = purple_unescape_html(url_buf);
g_string_append_printf(ret, "<A HREF=\"%s\">%s</A>",
url_buf, url_buf);
g_free(url_buf);
// g_free(tmpurlbuf);
c = t;
break;
}
t++;
}
} else if (c != text && (*c == '@')) {
int flag;
GString *gurl_buf = NULL;
const char illegal_chars[] = "!@#$%^&*()[]{}/|\\<>\":;\r\n \0";
if (strchr(illegal_chars,*(c - 1)) || strchr(illegal_chars, *(c + 1)))
flag = 0;
else {
flag = 1;
gurl_buf = g_string_new("");
}
t = c;
while (flag) {
/* iterate backwards grabbing the local part of an email address */
g = g_utf8_get_char(t);
if (badchar(*t) || (g >= 127) || (*t == '(') ||
((*t == ';') && ((t > (text+2) && (!g_ascii_strncasecmp(t - 3, "&lt;", 4) ||
!g_ascii_strncasecmp(t - 3, "&gt;", 4))) ||
(t > (text+4) && (!g_ascii_strncasecmp(t - 5, "&quot;", 6)))))) {
/* local part will already be part of ret, strip it out */
ret = g_string_truncate(ret, ret->len - (c - t));
ret = g_string_append_unichar(ret, g);
break;
} else {
g_string_prepend_unichar(gurl_buf, g);
t = g_utf8_find_prev_char(text, t);
if (t < text) {
ret = g_string_assign(ret, "");
break;
}
}
}
t = g_utf8_find_next_char(c, NULL);
while (flag) {
/* iterate forwards grabbing the domain part of an email address */
g = g_utf8_get_char(t);
if (badchar(*t) || (g >= 127) || (*t == ')') || badentity(t)) {
char *d;
url_buf = g_string_free(gurl_buf, FALSE);
/* strip off trailing periods */
if (strlen(url_buf) > 0) {
for (d = url_buf + strlen(url_buf) - 1; *d == '.'; d--, t--)
*d = '\0';
}
tmpurlbuf = purple_unescape_html(url_buf);
if (purple_email_is_valid(tmpurlbuf)) {
g_string_append_printf(ret, "<A HREF=\"mailto:%s\">%s</A>",
url_buf, url_buf);
} else {
g_string_append(ret, url_buf);
}
g_free(url_buf);
g_free(tmpurlbuf);
c = t;
break;
} else {
g_string_append_unichar(gurl_buf, g);
t = g_utf8_find_next_char(t, NULL);
}
}
}
if(*c == ')' && !inside_html) {
inside_paren--;
ret = g_string_append_c(ret, *c);
c++;
}
if (*c == 0)
break;
ret = g_string_append_c(ret, *c);
c++;
}
return g_string_free(ret, FALSE);
}
struct authRequest {
PurpleAccountRequestAuthorizationCb authorize_cb;
PurpleAccountRequestAuthorizationCb deny_cb;
@ -509,13 +220,13 @@ static std::string getAlias(PurpleBuddy *m_buddy) {
class SpectrumNetworkPlugin : public NetworkPlugin {
public:
SpectrumNetworkPlugin(const std::string &host, int port) : NetworkPlugin() {
SpectrumNetworkPlugin() : NetworkPlugin() {
}
void handleExitRequest() {
LOG4CXX_INFO(logger, "Exiting...");
exit(1);
exit(0);
}
void getProtocolAndName(const std::string &legacyName, std::string &name, std::string &protocol) {
@ -593,11 +304,29 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
i++;
}
g_strfreev (keys);
char* contents;
gsize length;
gboolean ret = g_file_get_contents ("gfire.cfg", &contents, &length, NULL);
if (ret) {
purple_account_set_int(account, "version", fromString<int>(std::string(contents, length)));
}
if (KEYFILE_STRING("service", "protocol") == "prpl-novell") {
std::string username(purple_account_get_username(account));
std::vector <std::string> u = split(username, '@');
purple_account_set_username(account, (const char*) u.front().c_str());
std::vector <std::string> s = split(u.back(), ':');
purple_account_set_string(account, "server", s.front().c_str());
purple_account_set_int(account, "port", atoi(s.back().c_str()));
}
}
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
PurpleAccount *account = NULL;
std::string name;
std::string protocol;
getProtocolAndName(legacyName, name, protocol);
@ -614,7 +343,6 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
return;
}
if (purple_accounts_find(name.c_str(), protocol.c_str()) != NULL) {
LOG4CXX_INFO(logger, "Using previously created account with name '" << name.c_str() << "' and protocol '" << protocol << "'");
account = purple_accounts_find(name.c_str(), protocol.c_str());
@ -637,11 +365,13 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
setDefaultAccountOptions(account);
// Enable account + privacy lists
purple_account_set_enabled(account, "spectrum", TRUE);
if (KEYFILE_BOOL("service", "enable_privacy_lists")) {
purple_account_set_privacy_type(account, PURPLE_PRIVACY_DENY_USERS);
}
// Set the status
const PurpleStatusType *status_type = purple_account_get_status_type_with_primitive(account, PURPLE_STATUS_AVAILABLE);
if (status_type != NULL) {
purple_account_set_status(account, purple_status_type_get_id(status_type), TRUE, NULL);
@ -651,6 +381,10 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
PurpleAccount *account = m_sessions[user];
if (account) {
if (purple_account_get_int(account, "version", 0) != 0) {
std::string data = stringOf(purple_account_get_int(account, "version", 0));
g_file_set_contents ("gfire.cfg", data.c_str(), data.size(), NULL);
}
// VALGRIND_DO_LEAK_CHECK;
m_sessions.erase(user);
purple_account_disconnect(account);
@ -661,50 +395,6 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
m_accounts.erase(account);
purple_accounts_delete(account);
//
// // Remove conversations.
// // This has to be called before m_account->ui_data = NULL;, because it uses
// // ui_data to call SpectrumMessageHandler::purpleConversationDestroyed() callback.
// GList *iter;
// for (iter = purple_get_conversations(); iter; ) {
// PurpleConversation *conv = (PurpleConversation*) iter->data;
// iter = iter->next;
// if (purple_conversation_get_account(conv) == account)
// purple_conversation_destroy(conv);
// }
//
// g_free(account->ui_data);
// account->ui_data = NULL;
// m_accounts.erase(account);
//
// purple_notify_close_with_handle(account);
// purple_request_close_with_handle(account);
//
// purple_accounts_remove(account);
//
// GSList *buddies = purple_find_buddies(account, NULL);
// while(buddies) {
// PurpleBuddy *b = (PurpleBuddy *) buddies->data;
// purple_blist_remove_buddy(b);
// buddies = g_slist_delete_link(buddies, buddies);
// }
//
// /* Remove any open conversation for this account */
// for (GList *it = purple_get_conversations(); it; ) {
// PurpleConversation *conv = (PurpleConversation *) it->data;
// it = it->next;
// if (purple_conversation_get_account(conv) == account)
// purple_conversation_destroy(conv);
// }
//
// /* Remove this account's pounces */
// // purple_pounce_destroy_all_by_account(account);
//
// /* This will cause the deletion of an old buddy icon. */
// purple_buddy_icons_set_account_icon(account, NULL, 0);
//
// purple_account_destroy(account);
// force returning of memory chunks allocated by libxml2 to kernel
#ifndef WIN32
malloc_trim(0);
#endif
@ -768,17 +458,30 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml) {
PurpleAccount *account = m_sessions[user];
if (account) {
PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, legacyName.c_str(), account);
PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, legacyName.c_str(), account);
if (!conv) {
conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, legacyName.c_str());
conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, legacyName.c_str(), account);
if (!conv) {
conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, legacyName.c_str());
}
}
if (xhtml.empty()) {
gchar *_markup = purple_markup_escape_text(message.c_str(), -1);
purple_conv_im_send(PURPLE_CONV_IM(conv), _markup);
if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
purple_conv_im_send(PURPLE_CONV_IM(conv), _markup);
}
else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
purple_conv_chat_send(PURPLE_CONV_CHAT(conv), _markup);
}
g_free(_markup);
}
else {
purple_conv_im_send(PURPLE_CONV_IM(conv), xhtml.c_str());
if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
purple_conv_im_send(PURPLE_CONV_IM(conv), xhtml.c_str());
}
else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
purple_conv_chat_send(PURPLE_CONV_CHAT(conv), xhtml.c_str());
}
}
}
}
@ -915,6 +618,41 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
}
}
void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &pasword) {
PurpleAccount *account = m_sessions[user];
if (!account) {
return;
}
PurpleConnection *gc = purple_account_get_connection(account);
GHashTable *comps = NULL;
// Check if the PurpleChat is not stored in buddy list
PurpleChat *chat = purple_blist_find_chat(account, room.c_str());
if (chat) {
comps = purple_chat_get_components(chat);
}
else if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) {
comps = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, room.c_str());
}
LOG4CXX_INFO(logger, user << ": Joining the room " << room);
if (comps) {
serv_join_chat(gc, comps);
g_hash_table_destroy(comps);
}
}
void handleLeaveRoomRequest(const std::string &user, const std::string &room) {
PurpleAccount *account = m_sessions[user];
if (!account) {
return;
}
PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, room.c_str(), account);
purple_conversation_destroy(conv);
}
void handleFTStartRequest(const std::string &user, const std::string &buddyName, const std::string &fileName, unsigned long size, unsigned long ftID) {
PurpleXfer *xfer = m_unhandledXfers[user + fileName + buddyName];
if (xfer) {
@ -954,9 +692,13 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
}
void sendData(const std::string &string) {
write(m_sock, string.c_str(), string.size());
#ifdef WIN32
::send(main_socket, string.c_str(), string.size(), 0);
#else
write(main_socket, string.c_str(), string.size());
#endif
if (writeInput == 0)
writeInput = purple_input_add(m_sock, PURPLE_INPUT_WRITE, &transportDataReceived, NULL);
writeInput = purple_input_add(main_socket, PURPLE_INPUT_WRITE, &transportDataReceived, NULL);
}
void readyForData() {
@ -1090,7 +832,8 @@ static void buddyListNewNode(PurpleBlistNode *node) {
PurpleBuddy *buddy = (PurpleBuddy *) node;
PurpleAccount *account = purple_buddy_get_account(buddy);
LOG4CXX_INFO(logger, "Buddy updated " << np->m_accounts[account] << " " << purple_buddy_get_name(buddy) << " " << getAlias(buddy));
std::vector<std::string> groups = getGroups(buddy);
LOG4CXX_INFO(logger, "Buddy updated " << np->m_accounts[account] << " " << purple_buddy_get_name(buddy) << " " << getAlias(buddy) << " group (" << groups.size() << ")=" << groups[0]);
// Status
pbnetwork::StatusType status = pbnetwork::STATUS_NONE;
@ -1178,8 +921,9 @@ static PurpleBlistUiOps blistUiOps =
static void conv_write_im(PurpleConversation *conv, const char *who, const char *msg, PurpleMessageFlags flags, time_t mtime) {
// Don't forwards our own messages.
if (flags & PURPLE_MESSAGE_SEND || flags & PURPLE_MESSAGE_SYSTEM)
if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM && (flags & PURPLE_MESSAGE_SEND || flags & PURPLE_MESSAGE_SYSTEM)) {
return;
}
PurpleAccount *account = purple_conversation_get_account(conv);
// char *striped = purple_markup_strip_html(message);
@ -1218,19 +962,67 @@ static void conv_write_im(PurpleConversation *conv, const char *who, const char
// LOG4CXX_INFO(logger, "Received message body='" << message_ << "' xhtml='" << xhtml_ << "'");
np->handleMessage(np->m_accounts[account], w, message_, "", xhtml_);
if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
np->handleMessage(np->m_accounts[account], w, message_, "", xhtml_);
}
else {
LOG4CXX_INFO(logger, "Received message body='" << message_ << "' name='" << purple_conversation_get_name(conv) << "' " << w);
np->handleMessage(np->m_accounts[account], purple_conversation_get_name(conv), message_, w, xhtml_);
}
}
static void conv_chat_add_users(PurpleConversation *conv, GList *cbuddies, gboolean new_arrivals) {
PurpleAccount *account = purple_conversation_get_account(conv);
GList *l = cbuddies;
while (l != NULL) {
PurpleConvChatBuddy *cb = (PurpleConvChatBuddy *)l->data;
std::string name(cb->name);
int flags = GPOINTER_TO_INT(cb->flags);
if (flags & PURPLE_CBFLAGS_OP || flags & PURPLE_CBFLAGS_HALFOP) {
// item->addAttribute("affiliation", "admin");
// item->addAttribute("role", "moderator");
flags = 1;
}
else if (flags & PURPLE_CBFLAGS_FOUNDER) {
// item->addAttribute("affiliation", "owner");
// item->addAttribute("role", "moderator");
flags = 1;
}
else {
flags = 0;
// item->addAttribute("affiliation", "member");
// item->addAttribute("role", "participant");
}
np->handleParticipantChanged(np->m_accounts[account], name, purple_conversation_get_name(conv), (int) flags, pbnetwork::STATUS_ONLINE);
l = l->next;
}
}
static void conv_chat_remove_users(PurpleConversation *conv, GList *users) {
PurpleAccount *account = purple_conversation_get_account(conv);
GList *l = users;
while (l != NULL) {
std::string name((char *) l->data);
np->handleParticipantChanged(np->m_accounts[account], name, purple_conversation_get_name(conv), 0, pbnetwork::STATUS_NONE);
l = l->next;
}
}
static PurpleConversationUiOps conversation_ui_ops =
{
NULL,
NULL,
NULL,//conv_write_chat, /* write_chat */
conv_write_im,//conv_write_chat, /* write_chat */
conv_write_im, /* write_im */
NULL,//conv_write_conv, /* write_conv */
NULL,//conv_chat_add_users, /* chat_add_users */
conv_chat_add_users, /* chat_add_users */
NULL,//conv_chat_rename_user, /* chat_rename_user */
NULL,//conv_chat_remove_users, /* chat_remove_users */
conv_chat_remove_users, /* chat_remove_users */
NULL,//pidgin_conv_chat_update_user, /* chat_update_user */
NULL,//pidgin_conv_present_conversation, /* present */
NULL,//pidgin_conv_has_focus, /* has_focus */
@ -1372,11 +1164,13 @@ static void *notify_user_info(PurpleConnection *gc, const char *who, PurpleNotif
if (true) {
gchar *data;
gchar *path = purple_buddy_icon_get_full_path(icon);
if (g_file_get_contents (path, &data, &len, NULL)) {
photo = std::string(data, len);
free(data);
if (path) {
if (g_file_get_contents(path, &data, &len, NULL)) {
photo = std::string(data, len);
g_free(data);
}
g_free(path);
}
free(path);
}
else {
const gchar * data = (gchar*)purple_buddy_icon_get_data(icon, &len);
@ -1674,6 +1468,8 @@ debug_init(void)
REGISTER_G_LOG_HANDLER("GModule");
REGISTER_G_LOG_HANDLER("GLib-GObject");
REGISTER_G_LOG_HANDLER("GThread");
REGISTER_G_LOG_HANDLER("GConf");
#undef REGISTER_G_LOD_HANDLER
}
@ -1697,6 +1493,9 @@ static void signed_on(PurpleConnection *gc, gpointer unused) {
// force returning of memory chunks allocated by libxml2 to kernel
malloc_trim(0);
#endif
// For prpl-gg
execute_purple_plugin_action(gc, "Download buddylist from Server");
}
static void printDebug(PurpleDebugLevel level, const char *category, const char *arg_s) {
@ -1761,13 +1560,19 @@ static void gotAttention(PurpleAccount *account, const char *who, PurpleConversa
static bool initPurple() {
bool ret;
if (!resolvePurpleFunctions()) {
LOG4CXX_ERROR(logger, "Unable to load libpurple.dll or some of the needed methods");
return false;
}
purple_plugins_add_search_path("./plugins");
purple_util_set_user_dir("./");
remove("./accounts.xml");
remove("./blist.xml");
// if (m_configuration.logAreas & LOG_AREA_PURPLE)
purple_debug_set_ui_ops(&debugUiOps);
purple_debug_set_verbose(true);
purple_debug_set_ui_ops(&debugUiOps);
purple_debug_set_verbose(true);
purple_core_set_ui_ops(&coreUiOps);
if (KEYFILE_STRING("service", "eventloop") == "libev") {
@ -1831,56 +1636,17 @@ static bool initPurple() {
}
return ret;
}
#ifndef WIN32
static void spectrum_sigchld_handler(int sig)
{
int status;
pid_t pid;
do {
pid = waitpid(-1, &status, WNOHANG);
} while (pid != 0 && pid != (pid_t)-1);
if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
char errmsg[BUFSIZ];
snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
perror(errmsg);
}
}
#endif
static int create_socket(char *host, int portno) {
struct sockaddr_in serv_addr;
int m_sock = socket(AF_INET, SOCK_STREAM, 0);
memset((char *) &serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(portno);
hostent *hos; // Resolve name
if ((hos = gethostbyname(host)) == NULL) {
// strerror() will not work for gethostbyname() and hstrerror()
// is supposedly obsolete
exit(1);
}
serv_addr.sin_addr.s_addr = *((unsigned long *) hos->h_addr_list[0]);
if (connect(m_sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
close(m_sock);
m_sock = 0;
}
int flags = fcntl(m_sock, F_GETFL);
flags |= O_NONBLOCK;
fcntl(m_sock, F_SETFL, flags);
return m_sock;
}
static void transportDataReceived(gpointer data, gint source, PurpleInputCondition cond) {
if (cond & PURPLE_INPUT_READ) {
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) {
LOG4CXX_INFO(logger, "Diconnecting from spectrum2 server");
exit(errno);
@ -1903,17 +1669,10 @@ int main(int argc, char **argv) {
context = g_option_context_new("config_file_name or profile name");
g_option_context_add_main_entries(context, options_entries, "");
if (!g_option_context_parse (context, &argc, &argv, &error)) {
std::cout << "option parsing failed: " << error->message << "\n";
std::cerr << "option parsing failed: " << error->message << "\n";
return -1;
}
if (ver) {
// std::cout << VERSION << "\n";
std::cout << "verze\n";
g_option_context_free(context);
return 0;
}
if (argc != 2) {
#ifdef WIN32
std::cout << "Usage: spectrum.exe <configuration_file.cfg>\n";
@ -1937,27 +1696,6 @@ int main(int argc, char **argv) {
g_option_context_free(context);
return -1;
}
//
// if (signal(SIGINT, spectrum_sigint_handler) == SIG_ERR) {
// std::cout << "SIGINT handler can't be set\n";
// g_option_context_free(context);
// return -1;
// }
//
// if (signal(SIGTERM, spectrum_sigterm_handler) == SIG_ERR) {
// std::cout << "SIGTERM handler can't be set\n";
// g_option_context_free(context);
// return -1;
// }
//
// struct sigaction sa;
// memset(&sa, 0, sizeof(sa));
// sa.sa_handler = spectrum_sighup_handler;
// if (sigaction(SIGHUP, &sa, NULL)) {
// std::cout << "SIGHUP handler can't be set\n";
// g_option_context_free(context);
// return -1;
// }
#endif
keyfile = g_key_file_new ();
if (!g_key_file_load_from_file (keyfile, argv[1], (GKeyFileFlags) 0, 0)) {
@ -1965,39 +1703,20 @@ int main(int argc, char **argv) {
return 1;
}
if (KEYFILE_STRING("logging", "backend_config").empty()) {
LoggerPtr root = log4cxx::Logger::getRootLogger();
#ifndef _MSC_VER
root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n")));
#else
root->addAppender(new ConsoleAppender(new PatternLayout(L"%d %-5p %c: %m%n")));
#endif
}
else {
log4cxx::helpers::Properties p;
log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(KEYFILE_STRING("logging", "backend_config"));
p.load(istream);
LogString pid, jid;
log4cxx::helpers::Transcoder::decode(stringOf(getpid()), pid);
log4cxx::helpers::Transcoder::decode(KEYFILE_STRING("service", "jid"), jid);
#ifdef _MSC_VER
p.setProperty(L"pid", pid);
p.setProperty(L"jid", jid);
#else
p.setProperty("pid", pid);
p.setProperty("jid", jid);
#endif
log4cxx::PropertyConfigurator::configure(p);
Config config;
if (!config.load(argv[1])) {
std::cerr << "Can't open " << argv[1] << " configuration file.\n";
return 1;
}
Logging::initBackendLogging(&config);
initPurple();
m_sock = create_socket(host, port);
purple_input_add(m_sock, PURPLE_INPUT_READ, &transportDataReceived, NULL);
main_socket = create_socket(host, port);
purple_input_add(main_socket, PURPLE_INPUT_READ, &transportDataReceived, NULL);
purple_timeout_add_seconds(30, pingTimeout, NULL);
np = new SpectrumNetworkPlugin(host, port);
np = new SpectrumNetworkPlugin();
bool libev = KEYFILE_STRING("service", "eventloop") == "libev";
GMainLoop *m_loop;

View file

@ -0,0 +1,5 @@
#include "purple_defs.h"
bool resolvePurpleFunctions() {
return true;
}

View file

@ -0,0 +1,3 @@
#pragma once
bool resolvePurpleFunctions();

View file

@ -0,0 +1,153 @@
/**
* libtransport -- C++ library for easy XMPP Transports development
*
* Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include "utils.h"
#include "glib.h"
#include "purple.h"
#include <algorithm>
#include <iostream>
#include "errno.h"
#ifndef WIN32
#include "sys/wait.h"
#include "sys/signal.h"
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <netinet/ether.h>
#include "sys/socket.h"
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#else
#include <process.h>
#define getpid _getpid
#define ssize_t SSIZE_T
#include "win32/win32dep.h"
#endif
#include "purple_defs.h"
static GHashTable *ui_info = NULL;
void execute_purple_plugin_action(PurpleConnection *gc, const std::string &name) {
PurplePlugin *plugin = gc && PURPLE_CONNECTION_IS_CONNECTED(gc) ? gc->prpl : NULL;
if (plugin && PURPLE_PLUGIN_HAS_ACTIONS(plugin)) {
PurplePluginAction *action = NULL;
GList *actions, *l;
actions = PURPLE_PLUGIN_ACTIONS(plugin, gc);
for (l = actions; l != NULL; l = l->next) {
if (l->data) {
action = (PurplePluginAction *) l->data;
action->plugin = plugin;
action->context = gc;
if ((std::string) action->label == name) {
action->callback(action);
}
purple_plugin_action_free(action);
}
}
}
}
GHashTable *spectrum_ui_get_info(void)
{
if(NULL == ui_info) {
ui_info = g_hash_table_new(g_str_hash, g_str_equal);
g_hash_table_insert(ui_info, g_strdup("name"), g_strdup("Spectrum"));
g_hash_table_insert(ui_info, g_strdup("version"), g_strdup("0.5"));
g_hash_table_insert(ui_info, g_strdup("website"), g_strdup("http://spectrum.im"));
g_hash_table_insert(ui_info, g_strdup("dev_website"), g_strdup("http://spectrum.im"));
g_hash_table_insert(ui_info, g_strdup("client_type"), g_strdup("pc"));
/*
* This is the client key for "Pidgin." It is owned by the AIM
* account "markdoliner." Please don't use this key for other
* applications. You can either not specify a client key, in
* which case the default "libpurple" key will be used, or you
* can register for your own client key at
* http://developer.aim.com/manageKeys.jsp
*/
g_hash_table_insert(ui_info, g_strdup("prpl-aim-clientkey"), g_strdup("ma1cSASNCKFtrdv9"));
g_hash_table_insert(ui_info, g_strdup("prpl-icq-clientkey"), g_strdup("ma1cSASNCKFtrdv9"));
/*
* This is the distid for Pidgin, given to us by AOL. Please
* don't use this for other applications. You can just not
* specify a distid and libpurple will use a default.
*/
g_hash_table_insert(ui_info, g_strdup("prpl-aim-distid"), GINT_TO_POINTER(1550));
g_hash_table_insert(ui_info, g_strdup("prpl-icq-distid"), GINT_TO_POINTER(1550));
}
return ui_info;
}
#ifndef WIN32
void spectrum_sigchld_handler(int sig)
{
int status;
pid_t pid;
do {
pid = waitpid(-1, &status, WNOHANG);
} while (pid != 0 && pid != (pid_t)-1);
if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
char errmsg[BUFSIZ];
snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
perror(errmsg);
}
}
#endif
int create_socket(char *host, int portno) {
struct sockaddr_in serv_addr;
int main_socket = socket(AF_INET, SOCK_STREAM, 0);
memset((char *) &serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(portno);
hostent *hos; // Resolve name
if ((hos = gethostbyname(host)) == NULL) {
// strerror() will not work for gethostbyname() and hstrerror()
// is supposedly obsolete
exit(1);
}
serv_addr.sin_addr.s_addr = *((unsigned long *) hos->h_addr_list[0]);
if (connect(main_socket, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
close(main_socket);
main_socket = 0;
}
// int flags = fcntl(main_socket, F_GETFL);
// flags |= O_NONBLOCK;
// fcntl(main_socket, F_SETFL, flags);
return main_socket;
}

View file

@ -0,0 +1,33 @@
/**
* libtransport -- C++ library for easy XMPP Transports development
*
* Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#pragma once
#include "purple.h"
#include <string>
#ifndef WIN32
void spectrum_sigchld_handler(int sig);
#endif
int create_socket(char *host, int portno);
GHashTable *spectrum_ui_get_info(void);
void execute_purple_plugin_action(PurpleConnection *gc, const std::string &name);

View file

@ -2,8 +2,10 @@
#include <iostream>
#include "transport/config.h"
#include "transport/logging.h"
#include "transport/transport.h"
#include "transport/usermanager.h"
#include "transport/memoryusage.h"
#include "transport/logger.h"
#include "transport/sqlite3backend.h"
#include "transport/userregistration.h"
@ -12,13 +14,8 @@
#include "transport/rostermanager.h"
#include "transport/conversation.h"
#include "transport/networkplugin.h"
#include "transport/logger.h"
#include <boost/filesystem.hpp>
#include "log4cxx/logger.h"
#include "log4cxx/consoleappender.h"
#include "log4cxx/patternlayout.h"
#include "log4cxx/propertyconfigurator.h"
#include "log4cxx/helpers/properties.h"
#include "log4cxx/helpers/fileinputstream.h"
#include "sys/wait.h"
#include "sys/signal.h"
// #include "valgrind/memcheck.h"
@ -26,14 +23,22 @@
#include <dbus-1.0/dbus/dbus-glib-lowlevel.h>
using namespace log4cxx;
static LoggerPtr logger = Logger::getLogger("backend");
DEFINE_LOGGER(logger, "backend");
using namespace Transport;
class SpectrumNetworkPlugin;
#define GET_RESPONSE_DATA(RESP, DATA) ((RESP.find(std::string(DATA) + " ") != std::string::npos) ? RESP.substr(RESP.find(DATA) + strlen(DATA) + 1) : "");
#define GET_PROPERTY(VAR, OBJ, WHICH, PROP) std::string VAR = sk->send_command(std::string("GET ") + OBJ + " " + WHICH + " " + PROP); \
try {\
VAR = GET_RESPONSE_DATA(VAR, PROP);\
}\
catch (std::out_of_range& oor) {\
VAR="";\
}
SpectrumNetworkPlugin *np;
@ -81,7 +86,7 @@ static pbnetwork::StatusType getStatus(const std::string &st) {
class Skype {
public:
Skype(const std::string &user, const std::string &username, const std::string &password);
~Skype() { logout(); }
~Skype() { LOG4CXX_INFO(logger, "Skype instance desctuctor"); logout(); }
void login();
void logout();
std::string send_command(const std::string &message);
@ -97,6 +102,10 @@ class Skype {
bool createDBusProxy();
bool loadSkypeBuddies();
int getPid() {
return (int) m_pid;
}
private:
std::string m_username;
std::string m_password;
@ -124,7 +133,9 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
std::string name = legacyName;
name = name.substr(name.find(".") + 1);
if (name.find("skype.") == 0 || name.find("prpl-skype.") == 0) {
name = name.substr(name.find(".") + 1);
}
LOG4CXX_INFO(logger, "Creating account with name '" << name << "'");
Skype *skype = new Skype(user, name, password);
@ -134,10 +145,27 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
skype->login();
}
void handleMemoryUsage(double &res, double &shared) {
res = 0;
shared = 0;
for(std::map<std::string, Skype *>::const_iterator it = m_sessions.begin(); it != m_sessions.end(); it++) {
Skype *skype = it->second;
if (skype) {
double r;
double s;
process_mem_usage(s, r, skype->getPid());
res += r;
shared += s;
}
}
}
void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
Skype *skype = m_sessions[user];
if (skype) {
LOG4CXX_INFO(logger, "User wants to logout, logging out");
skype->logout();
Logging::shutdownLogging();
exit(1);
}
}
@ -178,6 +206,21 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
}
}
void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
Skype *skype = m_sessions[user];
if (skype) {
skype->send_command("SET USER " + buddyName + " BUDDYSTATUS 2 Please authorize me");
skype->send_command("SET USER " + buddyName + " ISAUTHORIZED TRUE");
}
}
void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
Skype *skype = m_sessions[user];
if (skype) {
skype->send_command("SET USER " + buddyName + " BUDDYSTATUS 1");
}
}
void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml) {
Skype *skype = m_sessions[user];
if (skype) {
@ -253,7 +296,7 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
std::cout << skype->getUsername() << " " << name << "\n";
if (skype->getUsername() == name) {
alias = skype->send_command("GET PROFILE FULLNAME");
alias = alias.substr(17);
alias = GET_RESPONSE_DATA(alias, "FULLNAME")
}
handleVCard(user, id, legacyName, "", alias, photo);
}
@ -268,13 +311,6 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
void handleVCardUpdatedRequest(const std::string &user, const std::string &p, const std::string &nickname) {
}
void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
}
void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
}
void handleBuddyBlockToggled(const std::string &user, const std::string &buddyName, bool blocked) {
}
@ -331,7 +367,8 @@ bool Skype::createDBusProxy() {
LOG4CXX_INFO(logger, m_username << ":" << error->message);
if (m_counter == 15) {
np->handleDisconnected(m_user, 0, error->message);
LOG4CXX_ERROR(logger, "Logging out, proxy couldn't be created: " << error->message);
np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, error->message);
logout();
g_error_free(error);
return FALSE;
@ -360,6 +397,12 @@ static gboolean create_dbus_proxy(gpointer data) {
}
void Skype::login() {
if (m_username.find("..") == 0 || m_username.find("/") != std::string::npos) {
np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Invalid username");
return;
}
boost::filesystem::remove_all(std::string("/tmp/skype/") + m_username);
boost::filesystem::path path(std::string("/tmp/skype/") + m_username);
if (!boost::filesystem::exists(path)) {
boost::filesystem::create_directories(path);
@ -394,6 +437,7 @@ void Skype::login() {
"</config>\n";
g_file_set_contents(std::string(std::string("/tmp/skype/") + m_username + "/" + m_username +"/config.xml").c_str(), config_xml.c_str(), -1, NULL);
sleep(1);
std::string db_path = std::string("/tmp/skype/") + m_username;
char *db = (char *) malloc(db_path.size() + 1);
strcpy(db, db_path.c_str());
@ -401,7 +445,8 @@ void Skype::login() {
gchar* argv[6] = {"skype", "--disable-cleanlooks", "--pipelogin", "--dbpath", db, 0};
int fd;
g_spawn_async_with_pipes(NULL,
GError *error = NULL;
bool spawned = g_spawn_async_with_pipes(NULL,
argv,
NULL /*envp*/,
G_SPAWN_SEARCH_PATH,
@ -411,9 +456,16 @@ void Skype::login() {
&fd,
NULL,
&fd_output,
NULL /*error*/);
&error);
if (!spawned) {
LOG4CXX_ERROR(logger, "Error spawning the Skype instance: " << error->message)
np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Error spawning the Skype instance.");
return;
}
std::string login_data = std::string(m_username + " " + m_password + "\n");
LOG4CXX_INFO(logger, m_username << ": Login data=" << login_data);
LOG4CXX_INFO(logger, m_username << ": Login data=" << m_username);
write(fd, login_data.c_str(), login_data.size());
close(fd);
@ -426,17 +478,18 @@ void Skype::login() {
if (m_connection == NULL)
{
LOG4CXX_INFO(logger, "Creating DBus connection.");
LOG4CXX_INFO(logger, "Creating DBUS connection.");
GError *error = NULL;
m_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
if (m_connection == NULL && error != NULL)
{
LOG4CXX_INFO(logger, m_username << ": DBUS Error: " << error->message);
LOG4CXX_INFO(logger, m_username << ": Creating DBUS Connection error: " << error->message);
g_error_free(error);
return;
}
}
sleep(1);
m_timer = g_timeout_add_seconds(1, create_dbus_proxy, this);
}
@ -449,28 +502,35 @@ bool Skype::loadSkypeBuddies() {
int bytes_read = read(fd_output, buffer, 1023);
if (bytes_read > 0) {
buffer[bytes_read] = 0;
np->handleDisconnected(m_user, 0, buffer);
close(fd_output);
logout();
return FALSE;
std::string b(buffer);
LOG4CXX_WARN(logger, "Skype wrote this on stdout '" << b << "'");
if (b.find("Incorrect Password") != std::string::npos) {
LOG4CXX_INFO(logger, "Incorrect password, logging out")
np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_FAILED, "Incorrect password");
close(fd_output);
logout();
return FALSE;
}
}
std::string re = send_command("NAME Spectrum");
if (m_counter++ > 15) {
np->handleDisconnected(m_user, 0, "");
LOG4CXX_ERROR(logger, "Logging out, because we tried to connect the Skype over DBUS 15 times without success");
np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Skype is not ready. This issue have been logged and admins will check it and try to fix it soon.");
close(fd_output);
logout();
return FALSE;
}
if (re.empty() || re == "CONNSTATUS OFFLINE") {
if (re.empty() || re == "CONNSTATUS OFFLINE" || re == "ERROR 68") {
return TRUE;
}
close(fd_output);
if (send_command("PROTOCOL 7") != "PROTOCOL 7") {
np->handleDisconnected(m_user, 0, "Skype is not ready");
LOG4CXX_ERROR(logger, "PROTOCOL 7 failed, logging out");
np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Skype is not ready. This issue have been logged and admins will check it and try to fix it soon.");
logout();
return FALSE;
}
@ -479,20 +539,32 @@ bool Skype::loadSkypeBuddies() {
std::map<std::string, std::string> group_map;
std::string groups = send_command("SEARCH GROUPS CUSTOM");
groups = groups.substr(groups.find(' ') + 1);
std::vector<std::string> grps;
boost::split(grps, groups, boost::is_any_of(","));
BOOST_FOREACH(std::string grp, grps) {
std::vector<std::string> data;
std::string name = send_command("GET GROUP " + grp + " DISPLAYNAME");
boost::split(data, name, boost::is_any_of(" "));
name = name.substr(name.find("DISPLAYNAME") + 12);
if (groups.find(' ') != std::string::npos) {
groups = groups.substr(groups.find(' ') + 1);
std::vector<std::string> grps;
boost::split(grps, groups, boost::is_any_of(","));
BOOST_FOREACH(std::string grp, grps) {
std::vector<std::string> data;
std::string name = send_command("GET GROUP " + grp + " DISPLAYNAME");
std::string users = send_command("GET GROUP " + data[1] + " USERS");
users = name.substr(name.find("USERS") + 6);
boost::split(data, users, boost::is_any_of(","));
BOOST_FOREACH(std::string u, data) {
group_map[u] = grp;
if (name.find("ERROR") == 0) {
continue;
}
boost::split(data, name, boost::is_any_of(" "));
name = GET_RESPONSE_DATA(name, "DISPLAYNAME");
std::string users = send_command("GET GROUP " + data[1] + " USERS");
try {
users = GET_RESPONSE_DATA(users, "USERS");
}
catch (std::out_of_range& oor) {
continue;
}
boost::split(data, users, boost::is_any_of(","));
BOOST_FOREACH(std::string u, data) {
group_map[u] = grp;
}
}
}
@ -505,7 +577,7 @@ bool Skype::loadSkypeBuddies() {
// online status;friendly name;voicemail;mood
// (comma-seperated lines, usernames can have comma's)
for (int i=0; full_friends_list[i] && *full_friends_list[i] != '\0'; i+=8)
for (int i=0; full_friends_list[i] && full_friends_list[i+1] && *full_friends_list[i] != '\0'; i+=8)
{
std::string buddy = full_friends_list[i];
@ -553,8 +625,12 @@ void Skype::logout() {
send_command("SET USERSTATUS OFFLINE");
sleep(2);
g_object_unref(m_proxy);
LOG4CXX_INFO(logger, m_username << ": Killing Skype instance");
LOG4CXX_INFO(logger, m_username << ": Terminating Skype instance (SIGTERM)");
kill((int) m_pid, SIGTERM);
// Give skype a chance
sleep(2);
LOG4CXX_INFO(logger, m_username << ": Killing Skype instance (SIGKILL)");
kill((int) m_pid, SIGKILL);
m_pid = 0;
}
}
@ -565,6 +641,7 @@ std::string Skype::send_command(const std::string &message) {
// int message_num;
// gchar error_return[30];
LOG4CXX_INFO(logger, "Sending: '" << message << "'");
if (!dbus_g_proxy_call (m_proxy, "Invoke", &error, G_TYPE_STRING, message.c_str(), G_TYPE_INVALID,
G_TYPE_STRING, &str, G_TYPE_INVALID))
{
@ -572,14 +649,16 @@ std::string Skype::send_command(const std::string &message) {
{
LOG4CXX_INFO(logger, m_username << ": DBUS Error: " << error->message);
g_error_free(error);
return "";
} else {
LOG4CXX_INFO(logger, m_username << ": DBUS no response");
return "";
}
}
if (str != NULL)
{
LOG4CXX_INFO(logger, m_username << ": DBUS:" << str);
LOG4CXX_INFO(logger, m_username << ": DBUS:'" << str << "'");
}
return str ? std::string(str) : std::string();
}
@ -599,57 +678,73 @@ static void handle_skype_message(std::string &message, Skype *sk) {
}
else {
pbnetwork::StatusType status = getStatus(cmd[3]);
std::string mood_text = sk->send_command("GET USER " + cmd[1] + " MOOD_TEXT");
mood_text = mood_text.substr(mood_text.find("MOOD_TEXT") + 10);
std::string alias = sk->send_command("GET USER " + cmd[1] + " FULLNAME");
alias = alias.substr(alias.find("FULLNAME") + 9);
GET_PROPERTY(mood_text, "USER", cmd[1], "MOOD_TEXT");
GET_PROPERTY(alias, "USER", cmd[1], "FULLNAME");
std::vector<std::string> groups;
np->handleBuddyChanged(sk->getUser(), cmd[1], alias, groups, status, mood_text);
}
}
else if (cmd[2] == "MOOD_TEXT") {
std::string st = sk->send_command("GET USER " + cmd[1] + " ONLINESTATUS");
st = st.substr(st.find("ONLINESTATUS") + 13);
GET_PROPERTY(st, "USER", cmd[1], "ONLINESTATUS");
pbnetwork::StatusType status = getStatus(st);
std::string mood_text = message.substr(message.find("MOOD_TEXT") + 10);
std::string mood_text = GET_RESPONSE_DATA(message, "MOOD_TEXT");
std::vector<std::string> groups;
np->handleBuddyChanged(sk->getUser(), cmd[1], "", groups, status, mood_text);
}
else if (cmd[2] == "BUDDYSTATUS" && cmd[3] == "3") {
std::string st = sk->send_command("GET USER " + cmd[1] + " ONLINESTATUS");
st = st.substr(st.find("ONLINESTATUS") + 13);
GET_PROPERTY(mood_text, "USER", cmd[1], "MOOD_TEXT");
GET_PROPERTY(st, "USER", cmd[1], "ONLINESTATUS");
pbnetwork::StatusType status = getStatus(st);
std::string mood_text = message.substr(message.find("MOOD_TEXT") + 10);
std::vector<std::string> groups;
np->handleBuddyChanged(sk->getUser(), cmd[1], "", groups, status, mood_text);
}
else if (cmd[2] == "FULLNAME") {
GET_PROPERTY(alias, "USER", cmd[1], "FULLNAME");
GET_PROPERTY(mood_text, "USER", cmd[1], "MOOD_TEXT");
GET_PROPERTY(st, "USER", cmd[1], "ONLINESTATUS");
pbnetwork::StatusType status = getStatus(st);
std::vector<std::string> groups;
np->handleBuddyChanged(sk->getUser(), cmd[1], alias, groups, status, mood_text);
}
}
else if (cmd[0] == "CHATMESSAGE") {
if (cmd[3] == "RECEIVED") {
std::string body = sk->send_command("GET CHATMESSAGE " + cmd[1] + " BODY");
body = body.substr(body.find("BODY") + 5);
GET_PROPERTY(body, "CHATMESSAGE", cmd[1], "BODY");
GET_PROPERTY(from_handle, "CHATMESSAGE", cmd[1], "FROM_HANDLE");
std::string chatname = sk->send_command("GET CHATMESSAGE " + cmd[1] + " CHATNAME");
size_t start = chatname.find("$") + 1;
size_t len = chatname.find(";") - start;
std::string from = chatname.substr(start, len);
std::string from_handle = sk->send_command("GET CHATMESSAGE " + cmd[1] + " FROM_HANDLE");
from_handle = from_handle.substr(from_handle.find("FROM_HANDLE") + 12);
// if (from_handle != sk->getUsername()) {
from = from_handle;
// }
if (from_handle == sk->getUsername())
return;
np->handleMessage(sk->getUser(), from, body);
np->handleMessage(sk->getUser(), from_handle, body);
sk->send_command("SET CHATMESSAGE " + cmd[1] + " SEEN");
}
}
else if (cmd[0] == "CALL") {
// CALL 884 STATUS RINGING
if (cmd[2] == "STATUS") {
if (cmd[3] == "RINGING" || cmd[3] == "MISSED") {
// handle only incoming calls
GET_PROPERTY(type, "CALL", cmd[1], "TYPE");
if (type.find("INCOMING") != 0) {
return;
}
GET_PROPERTY(from, "CALL", cmd[1], "PARTNER_HANDLE");
GET_PROPERTY(dispname, "CALL", cmd[1], "PARTNER_DISPNAME");
if (cmd[3] == "RINGING") {
np->handleMessage(sk->getUser(), from, "User " + dispname + " is calling you.");
}
else {
np->handleMessage(sk->getUser(), from, "You have missed call from user " + dispname + ".");
}
}
}
}
}
@ -707,6 +802,7 @@ static int create_socket(char *host, int portno) {
if ((hos = gethostbyname(host)) == NULL) {
// strerror() will not work for gethostbyname() and hstrerror()
// is supposedly obsolete
Logging::shutdownLogging();
exit(1);
}
serv_addr.sin_addr.s_addr = *((unsigned long *) hos->h_addr_list[0]);
@ -729,6 +825,7 @@ static gboolean transportDataReceived(GIOChannel *source, GIOCondition condition
ssize_t n = read(m_sock, ptr, sizeof(buffer));
if (n <= 0) {
LOG4CXX_INFO(logger, "Diconnecting from spectrum2 server");
Logging::shutdownLogging();
exit(errno);
}
std::string d = std::string(buffer, n);
@ -737,6 +834,7 @@ static gboolean transportDataReceived(GIOChannel *source, GIOCondition condition
}
static void io_destroy(gpointer data) {
Logging::shutdownLogging();
exit(1);
}
@ -812,18 +910,7 @@ int main(int argc, char **argv) {
return 1;
}
if (CONFIG_STRING(&config, "logging.backend_config").empty()) {
LoggerPtr root = log4cxx::Logger::getRootLogger();
root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n")));
}
else {
log4cxx::helpers::Properties p;
log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(&config, "logging.backend_config"));
p.load(istream);
p.setProperty("pid", boost::lexical_cast<std::string>(getpid()));
log4cxx::PropertyConfigurator::configure(p);
}
Logging::initBackendLogging(&config);
// initPurple(config);

View file

@ -9,6 +9,7 @@
*/
#include "transport/config.h"
#include "transport/logging.h"
#include "transport/networkplugin.h"
#include "transport/sqlite3backend.h"
#include "transport/mysqlbackend.h"
@ -25,13 +26,6 @@
Swift::SimpleEventLoop *loop_;
#include "log4cxx/logger.h"
#include "log4cxx/consoleappender.h"
#include "log4cxx/patternlayout.h"
#include "log4cxx/propertyconfigurator.h"
#include "log4cxx/helpers/properties.h"
#include "log4cxx/helpers/fileinputstream.h"
#include "log4cxx/helpers/transcoder.h"
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
@ -40,9 +34,7 @@ using namespace boost::filesystem;
using namespace boost::program_options;
using namespace Transport;
using namespace log4cxx;
static LoggerPtr logger = log4cxx::Logger::getLogger("SMSNetworkPlugin");
DEFINE_LOGGER(logger, "SMSNetworkPlugin");
#define INTERNAL_USER "/sms@backend@internal@user"
@ -312,80 +304,19 @@ int main (int argc, char* argv[]) {
return 1;
}
if (CONFIG_STRING(&config, "logging.backend_config").empty()) {
LoggerPtr root = log4cxx::Logger::getRootLogger();
#ifndef _MSC_VER
root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n")));
#else
root->addAppender(new ConsoleAppender(new PatternLayout(L"%d %-5p %c: %m%n")));
#endif
}
else {
log4cxx::helpers::Properties p;
log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(&config, "logging.backend_config"));
p.load(istream);
LogString pid, jid;
log4cxx::helpers::Transcoder::decode(boost::lexical_cast<std::string>(getpid()), pid);
log4cxx::helpers::Transcoder::decode(CONFIG_STRING(&config, "service.jid"), jid);
#ifdef _MSC_VER
p.setProperty(L"pid", pid);
p.setProperty(L"jid", jid);
#else
p.setProperty("pid", pid);
p.setProperty("jid", jid);
#endif
log4cxx::PropertyConfigurator::configure(p);
}
Logging::initBackendLogging(&config);
#ifdef WITH_SQLITE
if (CONFIG_STRING(&config, "database.type") == "sqlite3") {
storageBackend = new SQLite3Backend(&config);
if (!storageBackend->connect()) {
std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
return -1;
std::string error;
StorageBackend *storageBackend = StorageBackend::createBackend(&config, error);
if (storageBackend == NULL) {
if (!error.empty()) {
std::cerr << error << "\n";
return -2;
}
}
#else
if (CONFIG_STRING(&config, "database.type") == "sqlite3") {
std::cerr << "Spectrum2 is not compiled with mysql backend.\n";
return -2;
}
#endif
#ifdef WITH_MYSQL
if (CONFIG_STRING(&config, "database.type") == "mysql") {
storageBackend = new MySQLBackend(&config);
if (!storageBackend->connect()) {
std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
return -1;
}
}
#else
if (CONFIG_STRING(&config, "database.type") == "mysql") {
std::cerr << "Spectrum2 is not compiled with mysql backend.\n";
return -2;
}
#endif
#ifdef WITH_PQXX
if (CONFIG_STRING(&config, "database.type") == "pqxx") {
storageBackend = new PQXXBackend(&config);
if (!storageBackend->connect()) {
std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
return -1;
}
}
#else
if (CONFIG_STRING(&config, "database.type") == "pqxx") {
std::cerr << "Spectrum2 is not compiled with pqxx backend.\n";
return -2;
}
#endif
if (CONFIG_STRING(&config, "database.type") != "mysql" && CONFIG_STRING(&config, "database.type") != "sqlite3"
&& CONFIG_STRING(&config, "database.type") != "pqxx" && CONFIG_STRING(&config, "database.type") != "none") {
std::cerr << "Unknown storage backend " << CONFIG_STRING(&config, "database.type") << "\n";
return -2;
else if (!storageBackend->connect()) {
std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
return -1;
}
Swift::SimpleEventLoop eventLoop;

View file

@ -0,0 +1,10 @@
cmake_minimum_required(VERSION 2.6)
FILE(GLOB SRC *.c *.cpp)
ADD_EXECUTABLE(spectrum2_template_backend ${SRC})
target_link_libraries(spectrum2_template_backend transport pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
#INSTALL(TARGETS spectrum2_template_backend RUNTIME DESTINATION bin)

1
backends/template/README Normal file
View file

@ -0,0 +1 @@
This is just template for creating new generic spectrum2 backends. It does not do anything!

153
backends/template/main.cpp Normal file
View file

@ -0,0 +1,153 @@
// Transport includes
#include "transport/config.h"
#include "transport/networkplugin.h"
#include "transport/logging.h"
// Swiften
#include "Swiften/Swiften.h"
// for signal handler
#include "unistd.h"
#include "signal.h"
#include "sys/wait.h"
#include "sys/signal.h"
// Boost
#include <boost/algorithm/string.hpp>
using namespace boost::filesystem;
using namespace boost::program_options;
using namespace Transport;
DEFINE_LOGGER(logger, "Backend Template");
// eventloop
Swift::SimpleEventLoop *loop_;
// Plugin
class TemplatePlugin;
TemplatePlugin * np = NULL;
class TemplatePlugin : public NetworkPlugin {
public:
Swift::BoostNetworkFactories *m_factories;
Swift::BoostIOServiceThread m_boostIOServiceThread;
boost::shared_ptr<Swift::Connection> m_conn;
TemplatePlugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() {
this->config = config;
m_factories = new Swift::BoostNetworkFactories(loop);
m_conn = m_factories->getConnectionFactory()->createConnection();
m_conn->onDataRead.connect(boost::bind(&TemplatePlugin::_handleDataRead, this, _1));
m_conn->connect(Swift::HostAddressPort(Swift::HostAddress(host), port));
LOG4CXX_INFO(logger, "Starting the plugin.");
}
// NetworkPlugin uses this method to send the data to networkplugin server
void sendData(const std::string &string) {
m_conn->write(Swift::createSafeByteArray(string));
}
// This method has to call handleDataRead with all received data from network plugin server
void _handleDataRead(boost::shared_ptr<Swift::SafeByteArray> data) {
std::string d(data->begin(), data->end());
handleDataRead(d);
}
void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
handleConnected(user);
LOG4CXX_INFO(logger, user << ": Added buddy - Echo.");
handleBuddyChanged(user, "echo", "Echo", std::vector<std::string>(), pbnetwork::STATUS_ONLINE);
}
void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
}
void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "") {
LOG4CXX_INFO(logger, "Sending message from " << user << " to " << legacyName << ".");
if (legacyName == "echo") {
handleMessage(user, legacyName, message);
}
}
void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
LOG4CXX_INFO(logger, user << ": Added buddy " << buddyName << ".");
handleBuddyChanged(user, buddyName, alias, groups, pbnetwork::STATUS_ONLINE);
}
void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
}
private:
Config *config;
};
static void spectrum_sigchld_handler(int sig)
{
int status;
pid_t pid;
do {
pid = waitpid(-1, &status, WNOHANG);
} while (pid != 0 && pid != (pid_t)-1);
if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
char errmsg[BUFSIZ];
snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
perror(errmsg);
}
}
int main (int argc, char* argv[]) {
std::string host;
int port;
if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
std::cout << "SIGCHLD handler can't be set\n";
return -1;
}
boost::program_options::options_description desc("Usage: spectrum [OPTIONS] <config_file.cfg>\nAllowed options");
desc.add_options()
("host,h", value<std::string>(&host), "host")
("port,p", value<int>(&port), "port")
;
try
{
boost::program_options::variables_map vm;
boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
boost::program_options::notify(vm);
}
catch (std::runtime_error& e)
{
std::cout << desc << "\n";
exit(1);
}
catch (...)
{
std::cout << desc << "\n";
exit(1);
}
if (argc < 5) {
return 1;
}
Config config;
if (!config.load(argv[5])) {
std::cerr << "Can't open " << argv[1] << " configuration file.\n";
return 1;
}
Logging::initBackendLogging(&config);
Swift::SimpleEventLoop eventLoop;
loop_ = &eventLoop;
np = new TemplatePlugin(&config, &eventLoop, host, port);
loop_->run();
return 0;
}

View file

@ -0,0 +1,103 @@
#!/usr/bin/python
import asyncore, argparse, protocol_pb2, socket, logging
from NetworkPlugin import NetworkPlugin
np = None
logger = logging.getLogger('Template Backend')
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)
def handleTransportData(data):
"""
This function is called when data is received from the NetworkPlugin server
"""
np.handleDataRead(data)
class SpectrumPlugin(NetworkPlugin):
global logger
def __init__(self, iochannel):
NetworkPlugin.__init__(self)
self.iochannel = iochannel
logger.info("Starting plugin.")
def sendData(self, string):
"""
NetworkPlugin uses this method to send the data to networkplugin server
"""
self.iochannel.sendData(string)
logger.info("Starting plugin.")
def handleLoginRequest(self, user, legacyName, password):
self.handleConnected(user)
logger.info("Added Echo Buddy")
self.handleBuddyChanged(user, "echo", "Echo", [], protocol_pb2.STATUS_ONLINE)
def handleLogoutRequest(self, user, legacyName):
pass
def handleMessageSendRequest(self, user, legacyName, message, xhtml = ""):
logger.info("Message sent from " + user + ' to ' + legacyName)
if(legacyName == "echo"):
logger.info("Message Echoed: " + message)
self.handleMessage(user, legacyName, message)
def handleBuddyUpdatedRequest(self, user, buddyName, alias, groups):
logger.info("Added Buddy " + buddyName)
self.handleBuddyChanged(user, buddyName, alias, groups, protocol_pb2.STATUS_ONLINE)
def handleBuddyRemovedRequest(self, user, buddyName, groups):
pass
class IOChannel(asyncore.dispatcher):
def __init__(self, host, port, readCallBack):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect((host, port))
self.handleReceivedData = readCallBack
self.send_buffer = ""
def sendData(self, data):
self.send_buffer += data
def handle_connect(self):
pass
def handle_close(self):
self.close()
def handle_read(self):
data = self.recv(65536)
self.handleReceivedData(data)
def handle_write(self):
sent = self.send(self.send_buffer)
self.send_buffer = self.send_buffer[sent:]
def writable(self):
return (len(self.send_buffer) > 0)
def readable(self):
return True
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('--host', type=str, required=True)
parser.add_argument('--port', type=int, required=True)
parser.add_argument('config_file', type=str)
args = parser.parse_args()
io = IOChannel(args.host, args.port, handleTransportData)
np = SpectrumPlugin(io)
asyncore.loop()

View file

@ -1,5 +1,8 @@
FIND_LIBRARY(IRC_LIBRARY NAMES Communi)
FIND_PATH(IRC_INCLUDE_DIR NAMES "ircglobal.h" PATH_SUFFIXES Communi qt4/Communi )
find_package(Qt4 REQUIRED)
include( ${QT_USE_FILE} )
FIND_LIBRARY(IRC_LIBRARY NAMES Communi PATHS ${QT_LIBRARY_DIR})
FIND_PATH(IRC_INCLUDE_DIR NAMES "ircglobal.h" PATHS ${QT_INCLUDE_DIR} PATH_SUFFIXES Communi)
# message( STATUS ${IRC_LIBRARY})
if( IRC_LIBRARY AND IRC_INCLUDE_DIR )

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,16 @@
/*
* Copyright (c) 2011 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <Swiften/Elements/GatewayPayload.h>
namespace Swift {
GatewayPayload::GatewayPayload(const JID &jid, const std::string &desc, const std::string &prompt) :
jid(jid), desc(desc), prompt(prompt) {
}
}

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2011 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#pragma once
#include <vector>
#include <string>
#include <Swiften/Elements/Payload.h>
#include <Swiften/JID/JID.h>
namespace Swift {
class GatewayPayload : public Payload {
public:
GatewayPayload(const JID &jid = JID(), const std::string &desc = "", const std::string &prompt = "");
void setJID(const JID &jid) {
this->jid = jid;
}
const JID &getJID() const {
return jid;
}
void setDesc(const std::string &desc) {
this->desc = desc;
}
const std::string &getDesc() const {
return desc;
}
void setPrompt(const std::string &prompt) {
this->prompt = prompt;
}
const std::string &getPrompt() const {
return prompt;
}
private:
JID jid;
std::string desc;
std::string prompt;
};
}

View file

@ -0,0 +1,14 @@
/*
* Copyright (c) 2011 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <Swiften/Elements/PubSubItem.h>
namespace Swift {
PubSubItem::PubSubItem() {
}
}

View file

@ -0,0 +1,64 @@
/*
* Copyright (c) 2011 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#pragma once
#include <vector>
#include <string>
#include <Swiften/Elements/Payload.h>
namespace Swift {
class PubSubItem : public Payload {
public:
PubSubItem();
void addPayload(boost::shared_ptr<Payload> payload) {
payloads.push_back(payload);
}
const std::vector<boost::shared_ptr<Payload> > getPayloads() const {
return payloads;
}
template<typename T>
const std::vector<boost::shared_ptr<T> > getPayloads() const {
std::vector<boost::shared_ptr<T> > matched_payloads;
for (std::vector<boost::shared_ptr<Payload> >::const_iterator i = payloads.begin(); i != payloads.end(); ++i) {
boost::shared_ptr<T> result = boost::dynamic_pointer_cast<T>(*i);
if (result) {
matched_payloads.push_back(result);
}
}
return matched_payloads;
}
template<typename T>
const boost::shared_ptr<T> getPayload() const {
boost::shared_ptr<T> result;
for (std::vector<boost::shared_ptr<Payload> >::const_iterator i = payloads.begin(); i != payloads.end(); ++i) {
result = boost::dynamic_pointer_cast<T>(*i);
if (result) {
return result;
}
}
return result;
}
const std::string& getId() const { return id; }
void setId(const std::string& id) {
this->id = id;
}
private:
std::vector<boost::shared_ptr<Payload> > payloads;
std::string id;
};
}

View file

@ -0,0 +1,14 @@
/*
* Copyright (c) 2011 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <Swiften/Elements/PubSubPayload.h>
namespace Swift {
PubSubPayload::PubSubPayload() {
}
}

View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 2012 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#pragma once
#include <vector>
#include <string>
#include <Swiften/Elements/Payload.h>
namespace Swift {
class PubSubPayload : public Payload {
public:
PubSubPayload();
void addPayload(boost::shared_ptr<Payload> payload) {
payloads.push_back(payload);
}
const std::vector<boost::shared_ptr<Payload> > getPayloads() const {
return payloads;
}
template<typename T>
const std::vector<boost::shared_ptr<T> > getPayloads() const {
std::vector<boost::shared_ptr<T> > matched_payloads;
for (std::vector<boost::shared_ptr<Payload> >::const_iterator i = payloads.begin(); i != payloads.end(); ++i) {
boost::shared_ptr<T> result = boost::dynamic_pointer_cast<T>(*i);
if (result) {
matched_payloads.push_back(result);
}
}
return matched_payloads;
}
template<typename T>
const boost::shared_ptr<T> getPayload() const {
boost::shared_ptr<T> result;
for (std::vector<boost::shared_ptr<Payload> >::const_iterator i = payloads.begin(); i != payloads.end(); ++i) {
result = boost::dynamic_pointer_cast<T>(*i);
if (result) {
return result;
}
}
return result;
}
private:
std::vector<boost::shared_ptr<Payload> > payloads;
};
}

View file

@ -0,0 +1,16 @@
/*
* Copyright (c) 2011 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <Swiften/Elements/PubSubPublishPayload.h>
namespace Swift {
PubSubPublishPayload::PubSubPublishPayload(const std::string &node) :
node(node) {
}
}

View file

@ -0,0 +1,43 @@
/*
* Copyright (c) 2011 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#pragma once
#include <vector>
#include <string>
#include <Swiften/Elements/Payload.h>
#include <Swiften/Elements/PubSubItem.h>
#include <Swiften/JID/JID.h>
namespace Swift {
class PubSubPublishPayload : public Payload {
public:
enum Type { None, Pending, Subscribed, Unconfigured };
PubSubPublishPayload(const std::string &node = "");
void setNode(const std::string &node) {
this->node = node;
}
const std::string &getNode() const {
return node;
}
void addItem(const boost::shared_ptr<Payload> &item) {
items.push_back(item);
}
const std::vector<boost::shared_ptr<Payload> > &getItems() const {
return items;
}
private:
std::string node;
std::vector<boost::shared_ptr<Payload> > items;
};
}

View file

@ -0,0 +1,16 @@
/*
* Copyright (c) 2011 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <Swiften/Elements/PubSubSubscribePayload.h>
namespace Swift {
PubSubSubscribePayload::PubSubSubscribePayload(const JID &jid, const std::string &node) :
jid(jid), node(node) {
}
}

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2011 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#pragma once
#include <vector>
#include <string>
#include <Swiften/Elements/Payload.h>
#include <Swiften/JID/JID.h>
namespace Swift {
class PubSubSubscribePayload : public Payload {
public:
PubSubSubscribePayload(const JID &jid = JID(), const std::string &node = "");
void setJID(const JID &jid) {
this->jid = jid;
}
const JID &getJID() const {
return jid;
}
void setNode(const std::string &node) {
this->node = node;
}
const std::string &getNode() const {
return node;
}
private:
JID jid;
std::string node;
};
}

View file

@ -0,0 +1,16 @@
/*
* Copyright (c) 2011 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <Swiften/Elements/PubSubSubscriptionPayload.h>
namespace Swift {
PubSubSubscriptionPayload::PubSubSubscriptionPayload(const JID &jid, const std::string &node) :
jid(jid), node(node), type(None) {
}
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2011 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#pragma once
#include <vector>
#include <string>
#include <Swiften/Elements/Payload.h>
#include <Swiften/JID/JID.h>
namespace Swift {
class PubSubSubscriptionPayload : public Payload {
public:
enum Type { None, Pending, Subscribed, Unconfigured };
PubSubSubscriptionPayload(const JID &jid = JID(), const std::string &node = "");
void setJID(const JID &jid) {
this->jid = jid;
}
const JID &getJID() const {
return jid;
}
void setNode(const std::string &node) {
this->node = node;
}
const std::string &getNode() const {
return node;
}
void setId(const std::string &id) {
this->id = id;
}
const std::string &getId() const {
return id;
}
void setType(const Type &type) {
this->type = type;
}
const Type &getType() const {
return type;
}
private:
JID jid;
std::string node;
std::string id;
Type type;
};
}

View file

@ -18,6 +18,7 @@ DummyNetworkFactories::DummyNetworkFactories(EventLoop* eventLoop) {
domainNameResolver = new PlatformDomainNameResolver(eventLoop);
connectionServerFactory = new DummyConnectionServerFactory(eventLoop);
m_platformXMLParserFactory = new PlatformXMLParserFactory();
this->eventLoop = eventLoop;
}
DummyNetworkFactories::~DummyNetworkFactories() {

View file

@ -41,6 +41,10 @@ namespace Swift {
return m_platformXMLParserFactory;
}
EventLoop *getEventLoop() const {
return eventLoop;
}
Swift::TLSContextFactory* getTLSContextFactory() const {
return 0;
}
@ -55,5 +59,6 @@ namespace Swift {
ConnectionFactory* connectionFactory;
DomainNameResolver* domainNameResolver;
ConnectionServerFactory* connectionServerFactory;
EventLoop *eventLoop;
};
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2012 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <Swiften/Parser/PayloadParsers/GatewayPayloadParser.h>
#include <boost/lexical_cast.hpp>
#include <Swiften/Parser/PayloadParserFactoryCollection.h>
#include <Swiften/Parser/PayloadParserFactory.h>
#include <Swiften/Base/foreach.h>
#include <Swiften/Elements/MUCOccupant.h>
#include <Swiften/Parser/Tree/TreeReparser.h>
namespace Swift {
void GatewayPayloadParser::handleTree(ParserElement::ref root) {
foreach (ParserElement::ref child, root->getAllChildren()) {
if (child->getName() == "desc") {
getPayloadInternal()->setDesc(child->getText());
}
else if (child->getName() == "prompt") {
getPayloadInternal()->setPrompt(child->getText());
}
else if (child->getName() == "jid") {
getPayloadInternal()->setJID(child->getText());
}
}
}
}

View file

@ -0,0 +1,21 @@
/*
* Copyright (c) 2012 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#pragma once
#include <boost/optional.hpp>
#include <Swiften/Elements/GatewayPayload.h>
#include <Swiften/Parser/GenericPayloadTreeParser.h>
#include <Swiften/Parser/PayloadParsers/MUCItemParser.h>
namespace Swift {
class GatewayPayloadParser : public GenericPayloadTreeParser<GatewayPayload> {
public:
GatewayPayloadParser() {}
virtual void handleTree(ParserElement::ref root);
};
}

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include <Swiften/Parser/PayloadParsers/MUCPayloadParser.h>
#include <boost/lexical_cast.hpp>
#include <Swiften/Parser/PayloadParserFactoryCollection.h>
#include <Swiften/Parser/PayloadParserFactory.h>
#include <Swiften/Base/foreach.h>
#include <Swiften/Elements/MUCOccupant.h>
#include <Swiften/Parser/Tree/TreeReparser.h>
namespace Swift {
void MUCPayloadParser::handleTree(ParserElement::ref root) {
foreach (ParserElement::ref child, root->getAllChildren()) {
if (child->getName() == "password" && child->getNamespace() == root->getNamespace()) {
getPayloadInternal()->setPassword(child->getText());
}
}
}
}

View file

@ -0,0 +1,22 @@
/*
* Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <boost/optional.hpp>
#include <Swiften/Elements/MUCPayload.h>
#include <Swiften/Parser/GenericPayloadTreeParser.h>
#include <Swiften/Parser/PayloadParsers/MUCItemParser.h>
namespace Swift {
class PayloadParserFactoryCollection;
class MUCPayloadParser : public GenericPayloadTreeParser<MUCPayload> {
public:
MUCPayloadParser(){}
virtual void handleTree(ParserElement::ref root);
};
}

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2012 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <Swiften/Parser/PayloadParsers/PubSubItemParser.h>
#include <boost/lexical_cast.hpp>
#include <Swiften/Parser/PayloadParserFactoryCollection.h>
#include <Swiften/Parser/PayloadParserFactory.h>
#include <Swiften/Base/foreach.h>
#include <Swiften/Elements/MUCOccupant.h>
#include <Swiften/Parser/Tree/TreeReparser.h>
namespace Swift {
void PubSubItemParser::handleTree(ParserElement::ref root) {
std::string id = root->getAttributes().getAttribute("id");
if (!id.empty()) {
getPayloadInternal()->setId(id);
}
foreach (ParserElement::ref child, root->getAllChildren()) {
getPayloadInternal()->addPayload(TreeReparser::parseTree(child, factories));
}
}
}

View file

@ -0,0 +1,24 @@
/*
* Copyright (c) 2012 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#pragma once
#include <boost/optional.hpp>
#include <Swiften/Elements/PubSubItem.h>
#include <Swiften/Parser/GenericPayloadTreeParser.h>
#include <Swiften/Parser/PayloadParsers/MUCItemParser.h>
namespace Swift {
class PayloadParserFactoryCollection;
class PubSubItemParser : public GenericPayloadTreeParser<PubSubItem> {
public:
PubSubItemParser(PayloadParserFactoryCollection* collection) : factories(collection) {}
virtual void handleTree(ParserElement::ref root);
private:
PayloadParserFactoryCollection* factories;
};
}

View file

@ -0,0 +1,25 @@
/*
* Copyright (c) 2012 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <Swiften/Parser/PayloadParsers/PubSubPayloadParser.h>
#include <boost/lexical_cast.hpp>
#include <Swiften/Parser/PayloadParserFactoryCollection.h>
#include <Swiften/Parser/PayloadParserFactory.h>
#include <Swiften/Base/foreach.h>
#include <Swiften/Elements/MUCOccupant.h>
#include <Swiften/Parser/Tree/TreeReparser.h>
namespace Swift {
void PubSubPayloadParser::handleTree(ParserElement::ref root) {
foreach (ParserElement::ref child, root->getAllChildren()) {
getPayloadInternal()->addPayload(TreeReparser::parseTree(child, factories));
}
}
}

View file

@ -0,0 +1,24 @@
/*
* Copyright (c) 2012 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#pragma once
#include <boost/optional.hpp>
#include <Swiften/Elements/PubSubPayload.h>
#include <Swiften/Parser/GenericPayloadTreeParser.h>
#include <Swiften/Parser/PayloadParsers/MUCItemParser.h>
namespace Swift {
class PayloadParserFactoryCollection;
class PubSubPayloadParser : public GenericPayloadTreeParser<PubSubPayload> {
public:
PubSubPayloadParser(PayloadParserFactoryCollection* collection) : factories(collection) {}
virtual void handleTree(ParserElement::ref root);
private:
PayloadParserFactoryCollection* factories;
};
}

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2012 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <Swiften/Parser/PayloadParsers/PubSubPublishPayloadParser.h>
#include <boost/lexical_cast.hpp>
#include <Swiften/Parser/PayloadParserFactoryCollection.h>
#include <Swiften/Parser/PayloadParserFactory.h>
#include <Swiften/Base/foreach.h>
#include <Swiften/Elements/MUCOccupant.h>
#include <Swiften/Parser/Tree/TreeReparser.h>
namespace Swift {
void PubSubPublishPayloadParser::handleTree(ParserElement::ref root) {
std::string node = root->getAttributes().getAttribute("node");
if (!node.empty()) {
getPayloadInternal()->setNode(node);
}
foreach (ParserElement::ref child, root->getAllChildren()) {
getPayloadInternal()->addItem(TreeReparser::parseTree(child, factories));
}
}
}

View file

@ -0,0 +1,24 @@
/*
* Copyright (c) 2012 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#pragma once
#include <boost/optional.hpp>
#include <Swiften/Elements/PubSubPublishPayload.h>
#include <Swiften/Parser/GenericPayloadTreeParser.h>
#include <Swiften/Parser/PayloadParsers/MUCItemParser.h>
namespace Swift {
class PayloadParserFactoryCollection;
class PubSubPublishPayloadParser : public GenericPayloadTreeParser<PubSubPublishPayload> {
public:
PubSubPublishPayloadParser(PayloadParserFactoryCollection* collection) : factories(collection) {}
virtual void handleTree(ParserElement::ref root);
private:
PayloadParserFactoryCollection* factories;
};
}

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2012 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <Swiften/Parser/PayloadParsers/PubSubSubscribePayloadParser.h>
#include <boost/lexical_cast.hpp>
#include <Swiften/Parser/PayloadParserFactoryCollection.h>
#include <Swiften/Parser/PayloadParserFactory.h>
#include <Swiften/Base/foreach.h>
#include <Swiften/Elements/MUCOccupant.h>
#include <Swiften/Parser/Tree/TreeReparser.h>
namespace Swift {
void PubSubSubscribePayloadParser::handleTree(ParserElement::ref root) {
std::string node = root->getAttributes().getAttribute("node");
if (!node.empty()) {
getPayloadInternal()->setNode(node);
}
std::string jid = root->getAttributes().getAttribute("jid");
if (!jid.empty()) {
getPayloadInternal()->setJID(jid);
}
}
}

View file

@ -0,0 +1,24 @@
/*
* Copyright (c) 2012 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#pragma once
#include <boost/optional.hpp>
#include <Swiften/Elements/PubSubSubscribePayload.h>
#include <Swiften/Parser/GenericPayloadTreeParser.h>
#include <Swiften/Parser/PayloadParsers/MUCItemParser.h>
namespace Swift {
class PayloadParserFactoryCollection;
class PubSubSubscribePayloadParser : public GenericPayloadTreeParser<PubSubSubscribePayload> {
public:
PubSubSubscribePayloadParser(PayloadParserFactoryCollection* collection) : factories(collection) {}
virtual void handleTree(ParserElement::ref root);
private:
PayloadParserFactoryCollection* factories;
};
}

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 2012 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <Swiften/Parser/PayloadParsers/PubSubSubscriptionPayloadParser.h>
#include <boost/lexical_cast.hpp>
#include <Swiften/Parser/PayloadParserFactoryCollection.h>
#include <Swiften/Parser/PayloadParserFactory.h>
#include <Swiften/Base/foreach.h>
#include <Swiften/Elements/MUCOccupant.h>
#include <Swiften/Parser/Tree/TreeReparser.h>
namespace Swift {
void PubSubSubscriptionPayloadParser::handleTree(ParserElement::ref root) {
std::string node = root->getAttributes().getAttribute("node");
if (!node.empty()) {
getPayloadInternal()->setNode(node);
}
std::string jid = root->getAttributes().getAttribute("jid");
if (!jid.empty()) {
getPayloadInternal()->setJID(jid);
}
std::string id = root->getAttributes().getAttribute("subid");
if (!id.empty()) {
getPayloadInternal()->setId(id);
}
std::string type = root->getAttributes().getAttribute("subscription");
if (type == "none") {
getPayloadInternal()->setType(PubSubSubscriptionPayload::None);
}
else if (type == "subscribed") {
getPayloadInternal()->setType(PubSubSubscriptionPayload::Subscribed);
}
else if (type == "pending") {
getPayloadInternal()->setType(PubSubSubscriptionPayload::Pending);
}
else if (type == "unconfigured") {
getPayloadInternal()->setType(PubSubSubscriptionPayload::Unconfigured);
}
}
}

View file

@ -0,0 +1,24 @@
/*
* Copyright (c) 2012 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#pragma once
#include <boost/optional.hpp>
#include <Swiften/Elements/PubSubSubscriptionPayload.h>
#include <Swiften/Parser/GenericPayloadTreeParser.h>
#include <Swiften/Parser/PayloadParsers/MUCItemParser.h>
namespace Swift {
class PayloadParserFactoryCollection;
class PubSubSubscriptionPayloadParser : public GenericPayloadTreeParser<PubSubSubscriptionPayload> {
public:
PubSubSubscriptionPayloadParser(PayloadParserFactoryCollection* collection) : factories(collection) {}
virtual void handleTree(ParserElement::ref root);
private:
PayloadParserFactoryCollection* factories;
};
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2011 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <Swiften/Serializer/PayloadSerializers/GatewayPayloadSerializer.h>
#include <Swiften/Base/foreach.h>
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
#include <Swiften/Serializer/XML/XMLTextNode.h>
#include <Swiften/Serializer/XML/XMLElement.h>
#include <Swiften/Serializer/PayloadSerializerCollection.h>
namespace Swift {
GatewayPayloadSerializer::GatewayPayloadSerializer()
: GenericPayloadSerializer<GatewayPayload>() {
}
std::string GatewayPayloadSerializer::serializePayload(boost::shared_ptr<GatewayPayload> payload) const {
XMLElement query("query", "jabber:iq:gateway");
if (payload->getJID().isValid()) {
boost::shared_ptr<XMLElement> jid(new XMLElement("jid", "", payload->getJID().toBare().toString()));
query.addNode(jid);
}
if (!payload->getDesc().empty()) {
boost::shared_ptr<XMLElement> desc(new XMLElement("desc", "", payload->getDesc()));
query.addNode(desc);
}
if (!payload->getPrompt().empty()) {
boost::shared_ptr<XMLElement> prompt(new XMLElement("prompt", "", payload->getPrompt()));
query.addNode(prompt);
}
return query.serialize();
}
}

View file

@ -0,0 +1,19 @@
/*
* Copyright (c) 2011 Jan Kaluza
* 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/GatewayPayload.h>
namespace Swift {
class GatewayPayloadSerializer : public GenericPayloadSerializer<GatewayPayload> {
public:
GatewayPayloadSerializer();
virtual std::string serializePayload(boost::shared_ptr<GatewayPayload> item) const;
};
}

View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2011 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.h>
#include <Swiften/Base/foreach.h>
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
#include <Swiften/Serializer/XML/XMLTextNode.h>
#include <Swiften/Serializer/XML/XMLElement.h>
#include <Swiften/Serializer/PayloadSerializerCollection.h>
namespace Swift {
PubSubItemSerializer::PubSubItemSerializer(PayloadSerializerCollection *serializers) :
GenericPayloadSerializer<PubSubItem>(), serializers(serializers) {
}
std::string PubSubItemSerializer::serializePayload(boost::shared_ptr<PubSubItem> payload) const {
XMLElement item("item");
if (!payload->getId().empty()) {
item.setAttribute("id", payload->getId());
}
if (!payload->getPayloads().empty()) {
foreach(boost::shared_ptr<Payload> subPayload, payload->getPayloads()) {
PayloadSerializer* serializer = serializers->getPayloadSerializer(subPayload);
if (serializer) {
item.addNode(boost::shared_ptr<XMLRawTextNode>(new XMLRawTextNode(serializer->serialize(subPayload))));
}
}
}
return item.serialize();
}
}

View file

@ -0,0 +1,22 @@
/*
* Copyright (c) 2011 Jan Kaluza
* 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/PubSubItem.h>
namespace Swift {
class PayloadSerializerCollection;
class PubSubItemSerializer : public GenericPayloadSerializer<PubSubItem> {
public:
PubSubItemSerializer(PayloadSerializerCollection *serializers);
virtual std::string serializePayload(boost::shared_ptr<PubSubItem> item) const;
private:
PayloadSerializerCollection *serializers;
};
}

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2011 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <Swiften/Serializer/PayloadSerializers/PubSubPayloadSerializer.h>
#include <Swiften/Base/foreach.h>
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
#include <Swiften/Serializer/XML/XMLTextNode.h>
#include <Swiften/Serializer/XML/XMLElement.h>
#include <Swiften/Serializer/PayloadSerializerCollection.h>
namespace Swift {
PubSubPayloadSerializer::PubSubPayloadSerializer(PayloadSerializerCollection *serializers)
: GenericPayloadSerializer<PubSubPayload>(),
serializers(serializers) {
}
std::string PubSubPayloadSerializer::serializePayload(boost::shared_ptr<PubSubPayload> payload) const {
XMLElement pubsub("pubsub", "http://jabber.org/protocol/pubsub");
if (!payload->getPayloads().empty()) {
foreach(boost::shared_ptr<Payload> subPayload, payload->getPayloads()) {
PayloadSerializer* serializer = serializers->getPayloadSerializer(subPayload);
if (serializer) {
pubsub.addNode(boost::shared_ptr<XMLRawTextNode>(new XMLRawTextNode(serializer->serialize(subPayload))));
}
}
}
return pubsub.serialize();
}
}

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2011 Jan Kaluza
* 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/PubSubPayload.h>
namespace Swift {
class PayloadSerializerCollection;
class PubSubPayloadSerializer : public GenericPayloadSerializer<PubSubPayload> {
public:
PubSubPayloadSerializer(PayloadSerializerCollection *serializers);
virtual std::string serializePayload(boost::shared_ptr<PubSubPayload> item) const;
private:
PayloadSerializerCollection *serializers;
};
}

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2011 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <Swiften/Serializer/PayloadSerializers/PubSubPublishPayloadSerializer.h>
#include <Swiften/Base/foreach.h>
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
#include <Swiften/Serializer/XML/XMLTextNode.h>
#include <Swiften/Serializer/XML/XMLElement.h>
#include <Swiften/Serializer/PayloadSerializerCollection.h>
namespace Swift {
PubSubPublishPayloadSerializer::PubSubPublishPayloadSerializer(PayloadSerializerCollection *serializers)
: GenericPayloadSerializer<PubSubPublishPayload>(),
serializers(serializers) {
}
std::string PubSubPublishPayloadSerializer::serializePayload(boost::shared_ptr<PubSubPublishPayload> payload) const {
XMLElement publish("publish");
if (!payload->getNode().empty()) {
publish.setAttribute("node", payload->getNode());
}
if (!payload->getItems().empty()) {
foreach(boost::shared_ptr<Payload> subPayload, payload->getItems()) {
PayloadSerializer* serializer = serializers->getPayloadSerializer(subPayload);
if (serializer) {
publish.addNode(boost::shared_ptr<XMLRawTextNode>(new XMLRawTextNode(serializer->serialize(subPayload))));
}
}
}
return publish.serialize();
}
}

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2011 Jan Kaluza
* 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/PubSubPublishPayload.h>
namespace Swift {
class PayloadSerializerCollection;
class PubSubPublishPayloadSerializer : public GenericPayloadSerializer<PubSubPublishPayload> {
public:
PubSubPublishPayloadSerializer(PayloadSerializerCollection *serializers);
virtual std::string serializePayload(boost::shared_ptr<PubSubPublishPayload> item) const;
private:
PayloadSerializerCollection *serializers;
};
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2011 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <Swiften/Serializer/PayloadSerializers/PubSubSubscribePayloadSerializer.h>
#include <Swiften/Base/foreach.h>
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
#include <Swiften/Serializer/XML/XMLTextNode.h>
#include <Swiften/Serializer/XML/XMLElement.h>
#include <Swiften/Serializer/PayloadSerializerCollection.h>
namespace Swift {
PubSubSubscribePayloadSerializer::PubSubSubscribePayloadSerializer()
: GenericPayloadSerializer<PubSubSubscribePayload>() {
}
std::string PubSubSubscribePayloadSerializer::serializePayload(boost::shared_ptr<PubSubSubscribePayload> payload) const {
XMLElement subscribe("subscribe");
if (!payload->getJID().isValid()) {
subscribe.setAttribute("jid", payload->getJID().toBare().toString());
}
if (!payload->getNode().empty()) {
subscribe.setAttribute("node", payload->getNode());
}
return subscribe.serialize();
}
}

View file

@ -0,0 +1,19 @@
/*
* Copyright (c) 2011 Jan Kaluza
* 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/PubSubSubscribePayload.h>
namespace Swift {
class PubSubSubscribePayloadSerializer : public GenericPayloadSerializer<PubSubSubscribePayload> {
public:
PubSubSubscribePayloadSerializer();
virtual std::string serializePayload(boost::shared_ptr<PubSubSubscribePayload> item) const;
};
}

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2011 Jan Kaluza
* Licensed under the Simplified BSD license.
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <Swiften/Serializer/PayloadSerializers/PubSubSubscriptionPayloadSerializer.h>
#include <Swiften/Base/foreach.h>
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
#include <Swiften/Serializer/XML/XMLTextNode.h>
#include <Swiften/Serializer/XML/XMLElement.h>
#include <Swiften/Serializer/PayloadSerializerCollection.h>
namespace Swift {
PubSubSubscriptionPayloadSerializer::PubSubSubscriptionPayloadSerializer()
: GenericPayloadSerializer<PubSubSubscriptionPayload>() {
}
std::string PubSubSubscriptionPayloadSerializer::serializePayload(boost::shared_ptr<PubSubSubscriptionPayload> payload) const {
XMLElement subscription("subscription");
if (!payload->getJID().isValid()) {
subscription.setAttribute("jid", payload->getJID().toBare().toString());
}
if (!payload->getNode().empty()) {
subscription.setAttribute("node", payload->getNode());
}
switch (payload->getType()) {
case PubSubSubscriptionPayload::None:
subscription.setAttribute("subscription", "none");
break;
case PubSubSubscriptionPayload::Subscribed:
subscription.setAttribute("subscription", "subscribed");
break;
case PubSubSubscriptionPayload::Unconfigured:
subscription.setAttribute("subscription", "unconfigured");
break;
case PubSubSubscriptionPayload::Pending:
subscription.setAttribute("subscription", "pending");
break;
}
return subscription.serialize();
}
}

View file

@ -0,0 +1,19 @@
/*
* Copyright (c) 2011 Jan Kaluza
* 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/PubSubSubscriptionPayload.h>
namespace Swift {
class PubSubSubscriptionPayloadSerializer : public GenericPayloadSerializer<PubSubSubscriptionPayload> {
public:
PubSubSubscriptionPayloadSerializer();
virtual std::string serializePayload(boost::shared_ptr<PubSubSubscriptionPayload> item) const;
};
}

View file

@ -14,12 +14,8 @@
#include <openssl/err.h>
#include <openssl/pkcs12.h>
#include "log4cxx/logger.h"
#include "log4cxx/consoleappender.h"
#include "log4cxx/patternlayout.h"
#include "log4cxx/propertyconfigurator.h"
using namespace log4cxx;
static LoggerPtr logger = Logger::getLogger("OpenSSLServerContext");
#include "transport/logging.h"
DEFINE_LOGGER(logger, "OpenSSLServerContext");
#include "Swiften/TLS/OpenSSL/OpenSSLServerContext.h"

View file

@ -1,11 +1,11 @@
if (PROTOBUF_FOUND)
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/protocol.pb.cc ${CMAKE_CURRENT_BINARY_DIR}/protocol.pb.h
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --cpp_out ${CMAKE_CURRENT_BINARY_DIR} --proto_path ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/protocol.proto
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/protocol.pb.cc ${CMAKE_CURRENT_SOURCE_DIR}/protocol.pb.h
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --cpp_out ${CMAKE_CURRENT_SOURCE_DIR} --proto_path ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/protocol.proto
COMMENT "Running C++ protocol buffer compiler on protocol.proto"
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/protocol.proto
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/protocol.proto
)
ADD_CUSTOM_TARGET(pb DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/protocol.pb.cc)
ADD_CUSTOM_TARGET(pb DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/protocol.pb.cc)
endif()
FILE(GLOB HEADERS *.h protocol.h)

View file

@ -39,6 +39,9 @@ typedef enum { BUDDY_NO_FLAG = 0,
/// Represents one legacy network Buddy.
class Buddy {
public:
typedef enum { Ask,
Both,
} Subscription;
/// Constructor.
/// \param rosterManager RosterManager associated with this buddy.
@ -93,12 +96,12 @@ class Buddy {
/// Sets current subscription.
/// \param subscription "to", "from", "both", "ask"
void setSubscription(const std::string &subscription);
void setSubscription(Subscription subscription);
/// Returns current subscription
/// \return subscription "to", "from", "both", "ask"
const std::string getSubscription();
Subscription getSubscription();
/// Sets this buddy's flags.
@ -172,6 +175,7 @@ class Buddy {
Swift::JID m_jid;
BuddyFlag m_flags;
RosterManager *m_rosterManager;
Subscription m_subscription;
};
}

View file

@ -28,13 +28,13 @@
#include <boost/bind.hpp>
#include <boost/signal.hpp>
#define CONFIG_HAS_KEY(PTR, KEY) (*PTR).hasKey(KEY)
#define CONFIG_STRING(PTR, KEY) (*PTR)[KEY].as<std::string>()
#define CONFIG_INT(PTR, KEY) (*PTR)[KEY].as<int>()
#define CONFIG_BOOL(PTR, KEY) (*PTR)[KEY].as<bool>()
#define CONFIG_LIST(PTR, KEY) (*PTR)[KEY].as<std::list<std::string> >()
#define CONFIG_VECTOR(PTR, KEY) (*PTR)[KEY].as<std::vector<std::string> >()
#define CONFIG_HAS_KEY(PTR, KEY) (*PTR).hasKey(KEY)
#define CONFIG_VECTOR(PTR, KEY) ((*PTR).hasKey(KEY) ? (*PTR)[KEY].as<std::vector<std::string> >() : std::vector<std::string>())
namespace Transport {
@ -50,7 +50,7 @@ typedef boost::program_options::variables_map Variables;
class Config {
public:
/// Constructor.
Config() {}
Config(int argc = 0, char **argv = NULL) : m_argc(argc), m_argv(argv) {}
/// Destructor
virtual ~Config() {}
@ -99,6 +99,8 @@ class Config {
boost::signal<void ()> onConfigReloaded;
private:
int m_argc;
char **m_argv;
Variables m_variables;
std::map<std::string, std::string> m_unregistered;
std::string m_file;

View file

@ -0,0 +1,43 @@
/**
* 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 <vector>
#include "Swiften/Swiften.h"
#include "Swiften/Queries/Responder.h"
#include "Swiften/Elements/GatewayPayload.h"
namespace Transport {
class UserManager;
class GatewayResponder : public Swift::Responder<Swift::GatewayPayload> {
public:
GatewayResponder(Swift::IQRouter *router, UserManager *userManager);
~GatewayResponder();
private:
virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::GatewayPayload> payload);
virtual bool handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::GatewayPayload> payload);
UserManager *m_userManager;
};
}

View file

@ -51,10 +51,15 @@ class LocalBuddy : public Buddy {
}
std::string getIconHash() { return m_iconHash; }
void setIconHash(const std::string &iconHash) { m_iconHash = iconHash; }
void setIconHash(const std::string &iconHash) {
bool changed = m_iconHash != iconHash;
m_iconHash = iconHash;
if (changed)
getRosterManager()->storeBuddy(this);
}
std::vector<std::string> getGroups() { return m_groups; }
void setGroups(const std::vector<std::string> &groups) { m_groups = groups; }
void setGroups(const std::vector<std::string> &groups);
private:
std::string m_name;

View file

@ -0,0 +1,63 @@
/**
* libtransport -- C++ library for easy XMPP Transports development
*
* Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <string>
#include <iostream>
#ifdef WITH_LOG4CXX
#include "log4cxx/logger.h"
#include "log4cxx/consoleappender.h"
#include "log4cxx/patternlayout.h"
#include "log4cxx/propertyconfigurator.h"
#include "log4cxx/helpers/properties.h"
#include "log4cxx/helpers/fileinputstream.h"
#include "log4cxx/helpers/transcoder.h"
#include "log4cxx/logger.h"
#include "log4cxx/logmanager.h"
#define DEFINE_LOGGER(VAR, NAME) static log4cxx::LoggerPtr VAR = log4cxx::Logger::getLogger(NAME);
using namespace log4cxx;
#else
#define DEFINE_LOGGER(VARIABLE, NAME) static const char *VARIABLE = NAME;
#define LOG4CXX_ERROR(LOGGER, DATA) std::cerr << "E: <" << LOGGER << "> " << DATA << "\n";
#define LOG4CXX_WARN(LOGGER, DATA) std::cout << "W: <" << LOGGER << "> " << DATA << "\n";
#define LOG4CXX_INFO(LOGGER, DATA) std::cout << "I: <" << LOGGER << "> " << DATA << "\n";
#endif
namespace Transport {
class Config;
namespace Logging {
void initBackendLogging(Config *config);
void initMainLogging(Config *config);
void shutdownLogging();
}
}

View file

@ -22,10 +22,14 @@
#include <vector>
#ifndef WIN32
#include "signal.h"
#endif
namespace Transport {
#ifndef WIN32
void process_mem_usage(double& shared, double& resident_set);
void process_mem_usage(double& shared, double& resident_set, pid_t pid = 0);
#endif
}

View file

@ -34,6 +34,22 @@ namespace Transport {
/// development.
class NetworkPlugin {
public:
class PluginConfig {
public:
PluginConfig() : m_needPassword(true) {}
virtual ~PluginConfig() {}
void setNeedPassword(bool needPassword = true) { m_needPassword = needPassword; }
void setExtraFields(const std::vector<std::string> &fields) { m_extraFields = fields; }
private:
bool m_needPassword;
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.
@ -43,6 +59,8 @@ class 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")
@ -211,6 +229,8 @@ class NetworkPlugin {
virtual void handleFTPauseRequest(unsigned long ftID) {}
virtual void handleFTContinueRequest(unsigned long ftID) {}
virtual void handleMemoryUsage(double &res, double &shared) {res = 0; shared = 0;}
virtual void handleExitRequest() { exit(1); }
void handleDataRead(std::string &data);
virtual void sendData(const std::string &string) {}

View file

@ -56,6 +56,7 @@ class NetworkPluginServer {
bool acceptUsers;
bool longRun;
bool willDie;
std::string id;
};
NetworkPluginServer(Component *component, Config *config, UserManager *userManager, FileTransferManager *ftManager);
@ -70,6 +71,10 @@ class NetworkPluginServer {
return m_clients;
}
const std::vector<std::string> &getCrashedBackends() {
return m_crashedBackends;
}
void collectBackend();
bool moveToLongRunBackend(User *user);
@ -137,6 +142,7 @@ class NetworkPluginServer {
bool m_isNextLongRun;
std::map<unsigned long, FileTransferManager::Transfer> m_filetransfers;
FileTransferManager *m_ftManager;
std::vector<std::string> m_crashedBackends;
};
}

View file

@ -44,6 +44,7 @@ message Login {
required string user = 1;
required string legacyName = 2;
required string password = 3;
repeated string extraFields = 4;
}
message Logout {
@ -106,6 +107,7 @@ message Stats {
required int32 res = 1;
required int32 init_res = 2;
required int32 shared = 3;
required string id = 4;
}
message File {
@ -121,6 +123,10 @@ message FileTransferData {
required bytes data = 2;
}
message BackendConfig {
required string config = 1;
}
message WrapperMessage {
enum Type {
TYPE_CONNECTED = 1;
@ -151,6 +157,7 @@ message WrapperMessage {
TYPE_FT_PAUSE = 27;
TYPE_FT_CONTINUE = 28;
TYPE_EXIT = 29;
TYPE_BACKEND_CONFIG = 30;
}
required Type type = 1;
optional bytes payload = 2;

View file

@ -80,6 +80,8 @@ struct BuddyInfo {
int flags;
};
class Config;
/// Abstract class defining storage backends.
class StorageBackend
{
@ -87,6 +89,8 @@ class StorageBackend
/// Virtual desctructor.
virtual ~StorageBackend() {}
static StorageBackend *createBackend(Config *config, std::string &error);
/// connect
virtual bool connect() = 0;

View file

@ -37,6 +37,7 @@
#include "transport/config.h"
#include "transport/factory.h"
#include "transport/presenceoracle.h"
#include <Swiften/Network/BoostConnectionServer.h>
namespace Transport {
// typedef enum { CLIENT_FEATURE_ROSTERX = 2,
@ -165,6 +166,7 @@ namespace Transport {
private:
void handleConnected();
void handleConnectionError(const Swift::ComponentError &error);
void handleServerStopped(boost::optional<Swift::BoostConnectionServer::Error> e);
void handlePresence(Swift::Presence::ref presence);
void handleDataRead(const Swift::SafeByteArray &data);
void handleDataWritten(const Swift::SafeByteArray &data);

View file

@ -104,6 +104,10 @@ class UserManager : public Swift::EntityCapsProvider {
return m_userRegistry;
}
Component *getComponent() {
return m_component;
}
/// Connects user manually.
/// \param user JID of user.
void connectUser(const Swift::JID &user);
@ -112,6 +116,13 @@ class UserManager : public Swift::EntityCapsProvider {
/// \param user JID of user.
void disconnectUser(const Swift::JID &user);
void messageToXMPPSent() { m_sentToXMPP++; }
void messageToBackendSent() { m_sentToBackend++; }
unsigned long getMessagesToXMPP() { return m_sentToXMPP; }
unsigned long getMessagesToBackend() { return m_sentToBackend; }
private:
void handlePresence(Swift::Presence::ref presence);
void handleMessageReceived(Swift::Message::ref message);
@ -130,6 +141,8 @@ class UserManager : public Swift::EntityCapsProvider {
StorageResponder *m_storageResponder;
UserRegistry *m_userRegistry;
Swift::Timer::ref m_removeTimer;
unsigned long m_sentToXMPP;
unsigned long m_sentToBackend;
friend class RosterResponder;
};

166
munin/spectrum2_ Executable file
View file

@ -0,0 +1,166 @@
#!/usr/bin/perl
# config:
# [spectrum2_*]
# env.admin_jid tradmin@host.org
# env.password jid_password
# env.transports icq.host.org xmpp.host.org
#
# symlinks:
# spectrum2_backends spectrum2_memory spectrum2_users spectrum2_messages spectrum2_messages_sec
#
#
use AnyEvent;
use AnyEvent::XMPP::Client;
use AnyEvent::XMPP::Component;
use AnyEvent::XMPP::Ext::Disco;
use AnyEvent::XMPP::Ext::Version;
use AnyEvent::XMPP::Namespaces qw/xmpp_ns/;
use AnyEvent::XMPP::Util qw/simxml/;
use XML::Simple;
use Time::HiRes qw ( setitimer ITIMER_REAL time );
use strict;
$|=1;
$SIG{ALRM} = sub { exit; };
setitimer(ITIMER_REAL, 30, 1);
my %config=(
users => {
title=>'Buddies online',
vlabel=>'users',
info=>'Number of users that currently use the spectrum transports.',
command=>'online_users_count',
base=>'--base 1000',
x=>'1',
},
backends => {
title=>'Backends running',
vlabel=>'backends',
info=>'Number of backends that currently running.',
command=>'backends_count',
base=>'--base 1000',
x=>'1',
},
memory => {
title=>'Memory usage of transports',
vlabel=>'megabytes',
info=>'Memory usage of spectrum transports.',
command=>'used_memory',
base=>'--base 1024',
x=>'1024',
},
messages => {
title=>'Messages send over transport',
vlabel=>'messages',
info=>'Messages send over spectrum transports.',
command=>'',
base=>'--base 1000',
x=>'1',
},
messages_sec => {
title=>'Messages send over transport',
vlabel=>'messages/sec',
info=>'Messages send per second over spectrum transports.',
command=>'',
base=>'--base 1000',
x=>'1',
},
);
my @queue=('_out','_in');
$0 =~ /spectrum2_(.+)*$/;
my $func = $1;
exit 2 unless defined $func;
my %tr;
my $count=0;
foreach (split(' ',$ENV{'transports'})){
if ($func=~/messages/)
{
$tr{$_."_in"}=$count;
$count++;
$tr{$_."_out"}=$count;
$count++;
}
else
{
$tr{$_}=$count;
$count++;
}
}
if (exists $ARGV[0] and $ARGV[0] eq "config")
{
print "graph_title ".$config{$func}->{'title'}."\n";
print "graph_vlabel ".$config{$func}->{'vlabel'}."\n";
print "graph_category spectrum2\n";
foreach (keys (%tr)){
print "r".$tr{$_}.".label ".$_."\n";
if ($func eq 'messages_sec')
{
print "r".$tr{$_}.".type DERIVE\n";
print "r".$tr{$_}.".min 0\n";
}
}
print "graph_args ".$config{$func}->{'base'}."\n";
print "graph_info ".$config{$func}->{'info'}."\n";
exit 0;
}
binmode( STDOUT);
my $xs=new XML::Simple;
my $cl=AnyEvent::XMPP::Client->new(debug=>0);
my $j=AnyEvent->condvar;
$cl->add_account($ENV{'admin_jid'}.'/'.time,$ENV{'password'});
$cl->reg_cb(
session_ready => \&cl_sess,
disconnect => \&cl_disc,
message => \&cl_msg,
);
$cl->start;
$j->wait;
sub cl_disc
{
my ($cl,$acc,$h,$p,$reas)=@_;
print "disc ($h:$p) $reas\n";
}
sub cl_sess
{
my($cl,$acc)=@_;
foreach (keys (%tr)){
if ($func=~/messages/)
{
if (s/_in$//)
{
$cl->send_message("messages_from_xmpp",$_,undef,'chat');
};
if (s/_out$//)
{
$cl->send_message("messages_to_xmpp",$_,undef,'chat');
}
}
else
{
$cl->send_message($config{$func}->{'command'},$_,undef,'chat');
}
}
}
sub cl_msg
{
my ($cl,$acc,$msg)=@_;
if ($func=~/messages/)
{
print "r".$tr{$msg->from.$queue[-1]}.".value ".int($msg->any_body/$config{$func}->{'x'})."\n";
delete( $tr{$msg->from.$queue[-1]});
pop(@queue);
if ($#queue==-1){@queue=("_out","_in");}
}
else
{
print "r".$tr{$msg->from}.".value ".int($msg->any_body/$config{$func}->{'x'})."\n";
delete( $tr{$msg->from});
}
exit if (scalar(keys %tr)==0);
}

View file

@ -1 +1,2 @@
ADD_SUBDIRECTORY(src)
ADD_SUBDIRECTORY(cpp)
ADD_SUBDIRECTORY(python)

35
plugin/cpp/CMakeLists.txt Normal file
View file

@ -0,0 +1,35 @@
cmake_minimum_required(VERSION 2.6)
FILE(GLOB SRC *.cpp *.h)
FILE(GLOB HEADERS ../include/transport/*.h)
set(EXTRA_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../../src/memoryusage.cpp)
set(EXTRA_SOURCES ${EXTRA_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/../../src/logging.cpp)
set(EXTRA_SOURCES ${EXTRA_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/../../src/config.cpp)
set(EXTRA_SOURCES ${EXTRA_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/../../include/transport/protocol.pb.cc)
if (NOT WIN32)
ADD_LIBRARY(transport-plugin SHARED ${HEADERS} ${SRC} ${PROTOBUF_SRC} ${PROTOBUF_HDRS} ${EXTRA_SOURCES})
else()
ADD_LIBRARY(transport-plugin STATIC ${HEADERS} ${SRC} ${PROTOBUF_SRC} ${PROTOBUF_HDRS} ${EXTRA_SOURCES})
endif()
ADD_DEPENDENCIES(transport-plugin pb)
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/../../include/transport/protocol.pb.cc PROPERTIES GENERATED 1)
if (CMAKE_COMPILER_IS_GNUCXX)
ADD_DEFINITIONS(-fPIC)
endif()
if (NOT WIN32)
TARGET_LINK_LIBRARIES(transport-plugin ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES} ${Boost_LIBRARIES})
else()
TARGET_LINK_LIBRARIES(transport-plugin ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES} ${Boost_LIBRARIES} ws2_32.lib)
endif()
SET_TARGET_PROPERTIES(transport-plugin PROPERTIES
VERSION ${TRANSPORT_VERSION} SOVERSION ${TRANSPORT_VERSION}
)
INSTALL(TARGETS transport-plugin LIBRARY DESTINATION ${LIB_INSTALL_DIR} ARCHIVE DESTINATION ${LIB_INSTALL_DIR} COMPONENT libraries)
#CONFIGURE_FILE(transport.pc.in "${CMAKE_CURRENT_SOURCE_DIR}/transport.pc")
#INSTALL(FILES "${CMAKE_CURRENT_SOURCE_DIR}/transport.pc" DESTINATION lib/pkgconfig)

View file

@ -19,19 +19,21 @@
*/
#include "transport/networkplugin.h"
#include "log4cxx/logger.h"
#include "log4cxx/basicconfigurator.h"
#include "transport/memoryusage.h"
#include "transport/logging.h"
#include <sstream>
#ifndef WIN32
#include <arpa/inet.h>
#else
#include <winsock2.h>
#include <stdint.h>
#include <process.h>
#define getpid _getpid
#endif
using namespace log4cxx;
static LoggerPtr logger = Logger::getLogger("NetworkPlugin");
DEFINE_LOGGER(logger, "NetworkPlugin");
namespace Transport {
@ -40,6 +42,12 @@ namespace Transport {
wrap.set_payload(MESSAGE); \
wrap.SerializeToString(&MESSAGE);
template <class T> std::string stringOf(T object) {
std::ostringstream os;
os << object;
return (os.str());
}
NetworkPlugin::NetworkPlugin() {
m_pingReceived = false;
@ -52,6 +60,25 @@ NetworkPlugin::NetworkPlugin() {
NetworkPlugin::~NetworkPlugin() {
}
void NetworkPlugin::sendConfig(const PluginConfig &cfg) {
std::string data = "[registration]";
data += std::string("needPassword=") + (cfg.m_needPassword ? "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";
}
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) {
pbnetwork::ConversationMessage m;
m.set_username(user);
@ -559,8 +586,8 @@ void NetworkPlugin::handleDataRead(std::string &data) {
}
void NetworkPlugin::send(const std::string &data) {
char header[4];
*((int*)(header)) = htonl(data.size());
uint32_t size = htonl(data.size());
char *header = (char *) &size;
sendData(std::string(header, 4) + data);
}
@ -586,13 +613,19 @@ void NetworkPlugin::sendMemoryUsage() {
pbnetwork::Stats stats;
stats.set_init_res(m_init_res);
double res;
double shared;
double res = 0;
double shared = 0;
#ifndef WIN32
process_mem_usage(shared, res);
#endif
stats.set_res(res);
stats.set_shared(shared);
double e_res;
double e_shared;
handleMemoryUsage(e_res, e_shared);
stats.set_res(res + e_res);
stats.set_shared(shared + e_shared);
stats.set_id(stringOf(getpid()));
std::string message;
stats.SerializeToString(&message);

View file

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 2.6)
if (PROTOBUF_FOUND)
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/protocol_pb2.py
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --python_out ${CMAKE_CURRENT_SOURCE_DIR} --proto_path ${CMAKE_CURRENT_SOURCE_DIR}/../../include/transport/ ${CMAKE_CURRENT_SOURCE_DIR}/../../include/transport/protocol.proto
COMMENT "Running Python protocol buffer compiler on protocol.proto"
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../../include/transport/protocol.proto
)
ADD_CUSTOM_TARGET(pb-python ALL DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/protocol_pb2.py)
endif()

View file

@ -0,0 +1,524 @@
import protocol_pb2, socket, struct, sys, os
def WRAP(MESSAGE, TYPE):
wrap = protocol_pb2.WrapperMessage()
wrap.type = TYPE
wrap.payload = MESSAGE
return wrap.SerializeToString()
class NetworkPlugin:
"""
Creates new NetworkPlugin and connects the Spectrum2 NetworkPluginServer.
@param loop: Event loop.
@param host: Host where Spectrum2 NetworkPluginServer runs.
@param port: Port.
"""
def __init__(self):
self.m_pingReceived = False
self.m_data = ""
self.m_init_res = 0
def handleMessage(self, user, legacyName, msg, nickname = "", xhtml = ""):
m = protocol_pb2.ConversationMessage()
m.userName = user
m.buddyName = legacyName
m.message = msg
m.nickname = nickname
m.xhtml = xhtml
message = WRAP(m.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_CONV_MESSAGE)
self.send(message)
def handleAttention(self, user, buddyName, msg):
m = protocol_pb2.ConversationMessage()
m.userName = user
m.buddyName = buddyName
m.message = msg
message = WRAP(m.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_ATTENTION)
self.send(message)
def handleVCard(self, user, ID, legacyName, fullName, nickname, photo):
vcard = protocol_pb2.VCard()
vcard.userName = user
vcard.buddyName = legacyName
vcard.id = ID
vcard.fullname = fullName
vcard.nickname = nickname
vcard.photo = photo
message = WRAP(vcard.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_VCARD)
self.send(message)
def handleSubject(self, user, legacyName, msg, nickname = ""):
m = protocol_pb2.ConversationMessage()
m.userName = user
m.buddyName = legacyName
m.message = msg
m.nickname = nickname
message = WRAP(m.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_ROOM_SUBJECT_CHANGED)
#print "SENDING MESSAGE"
self.send(message)
def handleBuddyChanged(self, user, buddyName, alias, groups, status, statusMessage = "", iconHash = "", blocked = False):
buddy = protocol_pb2.Buddy()
buddy.userName = user
buddy.buddyName = buddyName
buddy.alias = alias
buddy.group.extend(groups)
buddy.status = status
buddy.statusMessage = statusMessage
buddy.iconHash = iconHash
buddy.blocked = blocked
message = WRAP(buddy.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_BUDDY_CHANGED)
self.send(message)
def handleBuddyTyping(self, user, buddyName):
buddy = protocol_pb2.Buddy()
buddy.userName = user
buddy.buddyName = buddyName
message = WRAP(buddy.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_BUDDY_TYPING)
self.send(message);
def handleBuddyTyped(self, user, buddyName):
buddy = protocol_pb2.Buddy()
buddy.userName = user
buddy.buddyName = buddyName
message = WRAP(buddy.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_BUDDY_TYPED)
self.send(message);
def handleBuddyStoppedTyping(self, user, buddyName):
buddy = protocol_pb2.Buddy()
buddy.userName = user
buddy.buddyName = buddyName
message = WRAP(buddy.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_BUDDY_STOPPED_TYPING)
self.send(message)
def handleAuthorization(self, user, buddyName):
buddy = protocol_pb2.Buddy()
buddy.userName = user
buddy.buddyName = buddyName
message = WRAP(buddy.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_AUTH_REQUEST)
self.send(message)
def handleConnected(self, user):
d = protocol_pb2.Connected()
d.user = user
message = WRAP(d.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_CONNECTED)
self.send(message);
def handleDisconnected(self, user, error = 0, msg = ""):
d = protocol_pb2.Disconnected()
d.user = user
d.error = error
d.message = msg
message = WRAP(d.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_DISCONNECTED)
self.send(message);
def handleParticipantChanged(self, user, nickname, room, flags, status, statusMessage = "", newname = ""):
d = protocol_pb2.Participant()
d.userName = user
d.nickname = nickname
d.room = room
d.flag = flags
d.newname = newname
d.status = status
d.statusMessage = statusMessage
message = WRAP(d.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_PARTICIPANT_CHANGED)
self.send(message);
def handleRoomNicknameChanged(self, user, r, nickname):
room = protocol_pb2.Room()
room.userName = user
room.nickname = nickname
room.room = r
room.password = ""
message = WRAP(room.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_ROOM_NICKNAME_CHANGED)
self.send(message);
def handleFTStart(self, user, buddyName, fileName, size):
room = protocol_pb2.File()
room.userName = user
room.buddyName = buddyName
room.fileName = fileName
room.size = size
message = WRAP(room.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_FT_START)
self.send(message);
def handleFTFinish(self, user, buddyName, fileName, size, ftid):
room = protocol_pb2.File()
room.userName = user
room.buddyName = buddyName
room.fileName = fileName
room.size = size
# Check later
if ftid != 0:
room.ftID = ftid
message = WRAP(room.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_FT_FINISH)
self.send(message)
def handleFTData(self, ftID, data):
d = protocol_pb2.FileTransferData()
d.ftid = ftID
d.data = data
message = WRAP(d.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_FT_DATA);
self.send(message)
def handleLoginPayload(self, data):
payload = protocol_pb2.Login()
if (payload.ParseFromString(data) == False):
#TODO: ERROR
return
self.handleLoginRequest(payload.user, payload.legacyName, payload.password)
def handleLogoutPayload(self, data):
payload = protocol_pb2.Logout()
if (payload.ParseFromString(data) == False):
#TODO: ERROR
return
self.handleLogoutRequest(self, payload.user, payload.legacyName)
def handleStatusChangedPayload(data):
payload = protocol_pb2.Status()
if (payload.ParseFromString(data) == False):
#TODO: ERROR
return
self.handleStatusChangeRequest(payload.userName, payload.status, payload.statusMessage)
def handleConvMessagePayload(self, data):
payload = protocol_pb2.ConversationMessage()
if (payload.ParseFromString(data) == False):
#TODO: ERROR
return
self.handleMessageSendRequest(payload.userName, payload.buddyName, payload.message, payload.xhtml)
def handleAttentionPayload(self, data):
payload = protocol_pb2.ConversationMessage()
if (payload.ParseFromString(data) == False):
#TODO: ERROR
return
self.handleAttentionRequest(payload.userName, payload.buddyName, payload.message)
def handleFTStartPayload(self, data):
payload = protocol_pb2.File()
if (payload.ParseFromString(data) == False):
#TODO: ERROR
return
self.handleFTStartRequest(payload.userName, payload.buddyName, payload.fileName, payload.size, payload.ftID);
def handleFTFinishPayload(self, data):
payload = protocol_pb2.File()
if (payload.ParseFromString(data) == False):
#TODO: ERROR
return
self.handleFTFinishRequest(payload.userName, payload.buddyName, payload.fileName, payload.size, payload.ftID)
def handleFTPausePayload(self, data):
payload = protocol_pb2.FileTransferData()
if (payload.ParseFromString(data) == False):
#TODO: ERROR
return
self.handleFTPauseRequest(payload.ftID)
def handleFTContinuePayload(self, data):
payload = protocol_pb2.FileTransferData()
if (payload.ParseFromString(data) == False):
#TODO: ERROR
return
self.handleFTContinueRequest(payload.ftID)
def handleJoinRoomPayload(self, data):
payload = protocol_pb2.Room()
if (payload.ParseFromString(data) == False):
#TODO: ERROR
return
self.handleJoinRoomRequest(payload.userName, payload.room, payload.nickname, payload.password)
def handleLeaveRoomPayload(self, data):
payload = protocol_pb2.Room()
if (payload.ParseFromString(data) == False):
#TODO: ERROR
return
self.handleLeaveRoomRequest(payload.userName, payload.room)
def handleVCardPayload(self, data):
payload = protocol_pb2.VCard()
if (payload.ParseFromString(data) == False):
#TODO: ERROR
return
if payload.HasField('photo'):
self.handleVCardUpdatedRequest(payload.userName, payload.photo, payload.nickname)
elif len(payload.buddyName) > 0:
self.handleVCardRequest(payload.userName, payload.buddyName, payload.id)
def handleBuddyChangedPayload(self, data):
payload = protocol_pb2.Buddy()
if (payload.ParseFromString(data) == False):
#TODO: ERROR
return
if payload.HasField('blocked'):
self.handleBuddyBlockToggled(payload.userName, payload.buddyName, payload.blocked)
else:
groups = [g for g in payload.group]
self.handleBuddyUpdatedRequest(payload.userName, payload.buddyName, payload.alias, groups);
def handleBuddyRemovedPayload(self, data):
payload = protocol_pb2.Buddy()
if (payload.ParseFromString(data) == False):
#TODO: ERROR
return
groups = [g for g in payload.group]
self.handleBuddyRemovedRequest(payload.userName, payload.buddyName, groups);
def handleChatStatePayload(self, data, msgType):
payload = protocol_pb2.Buddy()
if (payload.ParseFromString(data) == False):
#TODO: ERROR
return
if msgType == protocol_pb2.WrapperMessage.TYPE_BUDDY_TYPING:
self.handleTypingRequest(payload.userName, payload.buddyName)
elif msgType == protocol_pb2.WrapperMessage.TYPE_BUDDY_TYPED:
self.handleTypedRequest(payload.userName, payload.buddyName)
elif msgType == protocol_pb2.WrapperMessage.TYPE_BUDDY_STOPPED_TYPING:
self.handleStoppedTypingRequest(payload.userName, payload.buddyName)
def handleDataRead(self, data):
self.m_data += data
while len(self.m_data) != 0:
expected_size = 0
if (len(self.m_data) >= 4):
expected_size = struct.unpack('!I', self.m_data[0:4])[0]
if (len(self.m_data) - 4 < expected_size):
return
else:
return
wrapper = protocol_pb2.WrapperMessage()
if (wrapper.ParseFromString(self.m_data[4:]) == False):
self.m_data = self.m_data[expected_size+4:]
return
self.m_data = self.m_data[4+expected_size:]
if wrapper.type == protocol_pb2.WrapperMessage.TYPE_LOGIN:
self.handleLoginPayload(wrapper.payload)
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_LOGOUT:
self.handleLogoutPayload(wrapper.payload)
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_PING:
self.sendPong()
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_CONV_MESSAGE:
self.handleConvMessagePayload(wrapper.payload)
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_JOIN_ROOM:
self.handleJoinRoomPayload(wrapper.payload)
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_LEAVE_ROOM:
self.handleLeaveRoomPayload(wrapper.payload)
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_VCARD:
self.handleVCardPayload(wrapper.payload)
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_BUDDY_CHANGED:
self.handleBuddyChangedPayload(wrapper.payload)
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_BUDDY_REMOVED:
self.handleBuddyRemovedPayload(wrapper.payload)
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_STATUS_CHANGED:
self.handleStatusChangedPayload(wrapper.payload)
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_BUDDY_TYPING:
self.handleChatStatePayload(wrapper.payload, protocol_pb2.WrapperMessage.TYPE_BUDDY_TYPING)
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_BUDDY_TYPED:
self.handleChatStatePayload(wrapper.payload, protocol_pb2.WrapperMessage.TYPE_BUDDY_TYPED)
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_BUDDY_STOPPED_TYPING:
self.handleChatStatePayload(wrapper.payload, protocol_pb2.WrapperMessage.TYPE_BUDDY_STOPPED_TYPING)
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_ATTENTION:
self.handleAttentionPayload(wrapper.payload)
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_FT_START:
self.handleFTStartPayload(wrapper.payload)
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_FT_FINISH:
self.handleFTFinishPayload(wrapper.payload)
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_FT_PAUSE:
self.handleFTPausePayload(wrapper.payload)
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_FT_CONTINUE:
self.handleFTContinuePayload(wrapper.payload)
elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_EXIT:
self.handleExitRequest()
def send(self, data):
header = struct.pack('!I',len(data))
self.sendData(header + data)
def checkPing(self):
if (self.m_pingReceived == False):
self.handleExitRequest()
self.m_pingReceived = False
def sendPong(self):
self.m_pingReceived = True
wrap = protocol_pb2.WrapperMessage()
wrap.type = protocol_pb2.WrapperMessage.TYPE_PONG
message = wrap.SerializeToString()
self.send(message)
self.sendMemoryUsage()
def sendMemoryUsage(self):
stats = protocol_pb2.Stats()
stats.init_res = self.m_init_res
res = 0
shared = 0
e_res, e_shared = self.handleMemoryUsage()
stats.res = res + e_res
stats.shared = shared + e_shared
stats.id = str(os.getpid())
message = WRAP(stats.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_STATS)
self.send(message)
def handleLoginRequest(self, user, legacyName, password):
"""
Called when XMPP user wants to connect legacy network.
You should connect him to legacy network and call handleConnected or handleDisconnected function later.
@param user: XMPP JID of user for which this event occurs.
@param legacyName: Legacy network name of this user used for login.
@param password: Legacy network password of this user.
"""
#\msc
#NetworkPlugin,YourNetworkPlugin,LegacyNetwork;
#NetworkPlugin->YourNetworkPlugin [label="handleLoginRequest(...)", URL="\ref NetworkPlugin::handleLoginRequest()"];
#YourNetworkPlugin->LegacyNetwork [label="connect the legacy network"];
#--- [label="If password was valid and user is connected and logged in"];
#YourNetworkPlugin<-LegacyNetwork [label="connected"];
#YourNetworkPlugin->NetworkPlugin [label="handleConnected()", URL="\ref NetworkPlugin::handleConnected()"];
#--- [label="else"];
#YourNetworkPlugin<-LegacyNetwork [label="disconnected"];
#YourNetworkPlugin->NetworkPlugin [label="handleDisconnected()", URL="\ref NetworkPlugin::handleDisconnected()"];
#\endmsc
raise NotImplementedError, "Implement me"
def handleLogoutRequest(self, user, legacyName):
"""
Called when XMPP user wants to disconnect legacy network.
You should disconnect him from legacy network.
@param user: XMPP JID of user for which this event occurs.
@param legacyName: Legacy network name of this user used for login.
"""
raise NotImplementedError, "Implement me"
def handleMessageSendRequest(self, user, legacyName, message, xhtml = ""):
"""
Called when XMPP user sends message to legacy network.
@param user: XMPP JID of user for which this event occurs.
@param legacyName: Legacy network name of buddy or room.
@param message: Plain text message.
@param xhtml: XHTML message.
"""
raise NotImplementedError, "Implement me"
def handleVCardRequest(self, user, legacyName, ID):
""" Called when XMPP user requests VCard of buddy.
@param user: XMPP JID of user for which this event occurs.
@param legacyName: Legacy network name of buddy whose VCard is requested.
@param ID: ID which is associated with this request. You have to pass it to handleVCard function when you receive VCard."""
#\msc
#NetworkPlugin,YourNetworkPlugin,LegacyNetwork;
#NetworkPlugin->YourNetworkPlugin [label="handleVCardRequest(...)", URL="\ref NetworkPlugin::handleVCardRequest()"];
#YourNetworkPlugin->LegacyNetwork [label="start VCard fetching"];
#YourNetworkPlugin<-LegacyNetwork [label="VCard fetched"];
#YourNetworkPlugin->NetworkPlugin [label="handleVCard()", URL="\ref NetworkPlugin::handleVCard()"];
#\endmsc
pass
def handleVCardUpdatedRequest(self, user, photo, nickname):
"""
Called when XMPP user updates his own VCard.
You should update the VCard in legacy network too.
@param user: XMPP JID of user for which this event occurs.
@param photo: Raw photo data.
"""
pass
def handleJoinRoomRequest(self, user, room, nickname, pasword):
pass
def handleLeaveRoomRequest(self, user, room):
pass
def handleStatusChangeRequest(self, user, status, statusMessage):
pass
def handleBuddyUpdatedRequest(self, user, buddyName, alias, groups):
pass
def handleBuddyRemovedRequest(self, user, buddyName, groups):
pass
def handleBuddyBlockToggled(self, user, buddyName, blocked):
pass
def handleTypingRequest(self, user, buddyName):
pass
def handleTypedRequest(self, user, buddyName):
pass
def handleStoppedTypingRequest(self, user, buddyName):
pass
def handleAttentionRequest(self, user, buddyName, message):
pass
def handleFTStartRequest(self, user, buddyName, fileName, size, ftID):
pass
def handleFTFinishRequest(self, user, buddyName, fileName, size, ftID):
pass
def handleFTPauseRequest(self, ftID):
pass
def handleFTContinueRequest(self, ftID):
pass
def handleMemoryUsage(self):
return (0,0)
def handleExitRequest(self):
sys.exit(1)
def sendData(self, data):
pass

View file

@ -1,30 +0,0 @@
cmake_minimum_required(VERSION 2.6)
FILE(GLOB SRC *.cpp *.h)
FILE(GLOB HEADERS ../include/transport/*.h)
if (NOT WIN32)
ADD_LIBRARY(transport-plugin SHARED ${HEADERS} ${SRC} ${PROTOBUF_SRC} ${PROTOBUF_HDRS} ../../src/memoryusage.cpp ${CMAKE_CURRENT_BINARY_DIR}/../../include/transport/protocol.pb.cc)
else()
ADD_LIBRARY(transport-plugin STATIC ${HEADERS} ${SRC} ${PROTOBUF_SRC} ${PROTOBUF_HDRS} ../../src/memoryusage.cpp ${CMAKE_CURRENT_BINARY_DIR}/../../include/transport/protocol.pb.cc)
endif()
ADD_DEPENDENCIES(transport-plugin pb)
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/../../include/transport/protocol.pb.cc PROPERTIES GENERATED 1)
if (CMAKE_COMPILER_IS_GNUCXX)
ADD_DEFINITIONS(-fPIC)
endif()
if (NOT WIN32)
TARGET_LINK_LIBRARIES(transport-plugin ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES})
else()
TARGET_LINK_LIBRARIES(transport-plugin ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES} ws2_32.lib)
endif()
SET_TARGET_PROPERTIES(transport-plugin PROPERTIES
VERSION ${TRANSPORT_VERSION} SOVERSION ${TRANSPORT_VERSION}
)
INSTALL(TARGETS transport-plugin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib COMPONENT libraries)
#CONFIGURE_FILE(transport.pc.in "${CMAKE_CURRENT_BINARY_DIR}/transport.pc")
#INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/transport.pc" DESTINATION lib/pkgconfig)

View file

@ -1,137 +0,0 @@
package pbnetwork;
enum StatusType {
STATUS_ONLINE = 0;
STATUS_AWAY = 1;
STATUS_FFC = 2;
STATUS_XA = 3;
STATUS_DND = 4;
STATUS_NONE = 5;
STATUS_INVISIBLE = 6;
}
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;
}
message Logout {
required string user = 1;
required string legacyName = 2;
}
message Buddy {
required string userName = 1;
required string buddyName = 2;
optional string alias = 3;
optional string groups = 4;
optional StatusType status = 5;
optional string statusMessage = 6;
optional string iconHash = 7;
optional bool blocked = 8;
}
message ConversationMessage {
required string userName = 1;
required string buddyName = 2;
required string message = 3;
optional string nickname = 4;
optional string xhtml = 5;
}
message Room {
required string userName = 1;
required string nickname = 2;
required string room = 3;
optional string password = 4;
}
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;
}
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 {
required string userName = 1;
required StatusType status = 3;
optional string statusMessage = 4;
}
message Stats {
required int32 res = 1;
required int32 init_res = 2;
required int32 shared = 3;
}
message File {
required string userName = 1;
required string buddyName = 2;
required string fileName = 3;
required int32 size = 4;
optional int32 ftID = 5;
}
message FileTransferData {
required int32 ftID = 1;
required bytes data = 2;
}
message WrapperMessage {
enum Type {
TYPE_CONNECTED = 1;
TYPE_DISCONNECTED = 2;
TYPE_LOGIN = 3;
TYPE_LOGOUT = 4;
TYPE_BUDDY_CHANGED = 6;
TYPE_BUDDY_REMOVED = 7;
TYPE_CONV_MESSAGE = 8;
TYPE_PING = 9;
TYPE_PONG = 10;
TYPE_JOIN_ROOM = 11;
TYPE_LEAVE_ROOM = 12;
TYPE_PARTICIPANT_CHANGED = 13;
TYPE_ROOM_NICKNAME_CHANGED = 14;
TYPE_ROOM_SUBJECT_CHANGED = 15;
TYPE_VCARD = 16;
TYPE_STATUS_CHANGED = 17;
TYPE_BUDDY_TYPING = 18;
TYPE_BUDDY_STOPPED_TYPING = 19;
TYPE_BUDDY_TYPED = 20;
TYPE_AUTH_REQUEST = 21;
TYPE_ATTENTION = 22;
TYPE_STATS = 23;
TYPE_FT_START = 24;
TYPE_FT_FINISH = 25;
TYPE_FT_DATA = 26;
TYPE_FT_PAUSE = 27;
TYPE_FT_CONTINUE = 28;
}
required Type type = 1;
optional bytes payload = 2;
}
;

View file

@ -12,6 +12,8 @@
#include "transport/statsresponder.h"
#include "transport/usersreconnecter.h"
#include "transport/util.h"
#include "transport/gatewayresponder.h"
#include "transport/logging.h"
#include "Swiften/EventLoop/SimpleEventLoop.h"
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
@ -24,20 +26,11 @@
#else
#include <windows.h>
#endif
#include "log4cxx/logger.h"
#include "log4cxx/consoleappender.h"
#include "log4cxx/patternlayout.h"
#include "log4cxx/propertyconfigurator.h"
#include "log4cxx/helpers/properties.h"
#include "log4cxx/helpers/transcoder.h"
#include "log4cxx/helpers/fileinputstream.h"
#include <sys/stat.h>
using namespace log4cxx;
using namespace Transport;
static LoggerPtr logger = log4cxx::Logger::getLogger("Spectrum");
DEFINE_LOGGER(logger, "Spectrum");
Swift::SimpleEventLoop *eventLoop_ = NULL;
Component *component_ = NULL;
@ -121,7 +114,7 @@ static void daemonize(const char *cwd, const char *lock_file) {
int main(int argc, char **argv)
{
Config config;
Config config(argc, argv);
boost::program_options::variables_map vm;
bool no_daemon = false;
@ -154,7 +147,7 @@ int main(int argc, char **argv)
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).run(), vm);
options(desc).positional(p).allow_unregistered().run(), vm);
boost::program_options::notify(vm);
if (vm.count("version")) {
@ -234,71 +227,7 @@ int main(int argc, char **argv)
}
#endif
if (CONFIG_STRING(&config, "logging.config").empty()) {
LoggerPtr root = log4cxx::Logger::getRootLogger();
#ifdef WIN32
root->addAppender(new ConsoleAppender(new PatternLayout(L"%d %-5p %c: %m%n")));
#else
root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n")));
#endif
}
else {
log4cxx::helpers::Properties p;
log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(&config, "logging.config"));
p.load(istream);
LogString pid, jid;
log4cxx::helpers::Transcoder::decode(boost::lexical_cast<std::string>(getpid()), pid);
log4cxx::helpers::Transcoder::decode(CONFIG_STRING(&config, "service.jid"), jid);
#ifdef WIN32
p.setProperty(L"pid", pid);
p.setProperty(L"jid", jid);
#else
p.setProperty("pid", pid);
p.setProperty("jid", jid);
#endif
std::string dir;
BOOST_FOREACH(const log4cxx::LogString &prop, p.propertyNames()) {
if (boost::ends_with(prop, ".File")) {
log4cxx::helpers::Transcoder::encode(p.get(prop), dir);
boost::replace_all(dir, "${jid}", jid);
break;
}
}
if (!dir.empty()) {
// create directories
try {
boost::filesystem::create_directories(
boost::filesystem::path(dir).parent_path().string()
);
}
catch (...) {
std::cerr << "Can't create logging directory directory " << boost::filesystem::path(dir).parent_path().string() << ".\n";
return 1;
}
#ifndef WIN32
if (!CONFIG_STRING(&config, "service.group").empty() && !CONFIG_STRING(&config, "service.user").empty()) {
struct group *gr;
if ((gr = getgrnam(CONFIG_STRING(&config, "service.group").c_str())) == NULL) {
std::cerr << "Invalid service.group name " << CONFIG_STRING(&config, "service.group") << "\n";
return 1;
}
struct passwd *pw;
if ((pw = getpwnam(CONFIG_STRING(&config, "service.user").c_str())) == NULL) {
std::cerr << "Invalid service.user name " << CONFIG_STRING(&config, "service.user") << "\n";
return 1;
}
chown(dir.c_str(), pw->pw_uid, gr->gr_gid);
}
#endif
}
log4cxx::PropertyConfigurator::configure(p);
}
Logging::initMainLogging(&config);
#ifndef WIN32
if (!CONFIG_STRING(&config, "service.group").empty() ||!CONFIG_STRING(&config, "service.user").empty() ) {
@ -348,57 +277,17 @@ int main(int argc, char **argv)
component_ = &transport;
// Logger logger(&transport);
StorageBackend *storageBackend = NULL;
#ifdef WITH_SQLITE
if (CONFIG_STRING(&config, "database.type") == "sqlite3") {
storageBackend = new SQLite3Backend(&config);
if (!storageBackend->connect()) {
std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
return -1;
std::string error;
StorageBackend *storageBackend = StorageBackend::createBackend(&config, error);
if (storageBackend == NULL) {
if (!error.empty()) {
std::cerr << error << "\n";
return -2;
}
}
#else
if (CONFIG_STRING(&config, "database.type") == "sqlite3") {
std::cerr << "Spectrum2 is not compiled with mysql backend.\n";
return -2;
}
#endif
#ifdef WITH_MYSQL
if (CONFIG_STRING(&config, "database.type") == "mysql") {
storageBackend = new MySQLBackend(&config);
if (!storageBackend->connect()) {
std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
return -1;
}
}
#else
if (CONFIG_STRING(&config, "database.type") == "mysql") {
std::cerr << "Spectrum2 is not compiled with mysql backend.\n";
return -2;
}
#endif
#ifdef WITH_PQXX
if (CONFIG_STRING(&config, "database.type") == "pqxx") {
storageBackend = new PQXXBackend(&config);
if (!storageBackend->connect()) {
std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
return -1;
}
}
#else
if (CONFIG_STRING(&config, "database.type") == "pqxx") {
std::cerr << "Spectrum2 is not compiled with pqxx backend.\n";
return -2;
}
#endif
if (CONFIG_STRING(&config, "database.type") != "mysql" && CONFIG_STRING(&config, "database.type") != "sqlite3"
&& CONFIG_STRING(&config, "database.type") != "pqxx" && CONFIG_STRING(&config, "database.type") != "none") {
std::cerr << "Unknown storage backend " << CONFIG_STRING(&config, "database.type") << "\n";
return -2;
else if (!storageBackend->connect()) {
std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
return -1;
}
UserManager userManager(&transport, &userRegistry, storageBackend);
@ -421,6 +310,9 @@ int main(int argc, char **argv)
StatsResponder statsResponder(&transport, &userManager, &plugin, storageBackend);
statsResponder.start();
GatewayResponder gatewayResponder(transport.getIQRouter(), &userManager);
gatewayResponder.start();
eventLoop_ = &eventLoop;
eventLoop.run();
@ -436,4 +328,5 @@ int main(int argc, char **argv)
delete storageBackend;
delete factories;
return 0;
}

View file

@ -7,38 +7,35 @@ server_mode = 1
backend_host=localhost
pidfile=./test.pid
# < this option doesn't work yet
backend_port=10001
admin_username=admin
#backend_port=10001
#admin_jid=admin@localhost
admin_password=test
#cert=server.pfx #patch to PKCS#12 certificate
#cert_password=test #password to that certificate if any
users_per_backend=10
#backend=/home/hanzz/code/libtransport/backends/libpurple/spectrum2_libpurple_backend
backend=/home/hanzz/code/libtransport/backends/smstools3/spectrum2_smstools3_backend
#backend=/usr/bin/mono /home/hanzz/code/networkplugin-csharp/msnp-sharp-backend/bin/Debug/msnp-sharp-backend.exe
#backend=/home/hanzz/code/libtransport/backends/frotz/spectrum2_frotz_backend
#backend=/home/hanzz/code/libtransport/backends/libircclient-qt/spectrum2_libircclient-qt_backend
backend=../..//backends/libpurple/spectrum2_libpurple_backend
#backend=../../backends/template/template_backend.py
protocol=prpl-jabber
#protocol=prpl-msn
protocol=any
#protocol=any
#protocol=prpl-icq
irc_server=irc.freenode.org
working_dir=./
[backend]
#default_avatar=catmelonhead.jpg
#no_vcard_fetch=true
incoming_dir=/var/spool/sms/incoming
[logging]
#config=logging.cfg # log4cxx/log4j logging configuration file
#backend_config=/home/hanzz/code/libtransport/spectrum/src/backend-logging.cfg # log4cxx/log4j logging configuration file for backends
[database]
#type = sqlite3 # or "none" without database backend
#database = test.sql
#prefix=icq
type = mysql # or "none" without database backend.......................................................................................................................
database = test
prefix=
user=root
password=yourrootsqlpassword
type = none # or "none" without database backend
database = test.sql
prefix=icq
#type = mysql # or "none" without database backend.......................................................................................................................
#database = test
#prefix=
#user=root
#password=yourrootsqlpassword
#encryption_key=hanzzik

BIN
spectrum/src/server.p12 Normal file

Binary file not shown.

View file

@ -310,12 +310,12 @@ static void ask_local_servers(ManagerConfig *config, Swift::BoostNetworkFactorie
std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n";
}
if (CONFIG_STRING(&cfg, "service.admin_jid").empty() || CONFIG_STRING(&cfg, "service.admin_password").empty()) {
if (CONFIG_VECTOR(&cfg, "service.admin_jid").empty() || CONFIG_STRING(&cfg, "service.admin_password").empty()) {
std::cerr << itr->path().string() << ": service.admin_jid or service.admin_password empty. This server can't be queried over XMPP.\n";
}
finished++;
Swift::Client *client = new Swift::Client(CONFIG_STRING(&cfg, "service.admin_jid"), CONFIG_STRING(&cfg, "service.admin_password"), &networkFactories);
Swift::Client *client = new Swift::Client(CONFIG_VECTOR(&cfg, "service.admin_jid")[0], CONFIG_STRING(&cfg, "service.admin_password"), &networkFactories);
client->setAlwaysTrustCertificates();
client->onConnected.connect(boost::bind(&handleConnected, client, CONFIG_STRING(&cfg, "service.jid")));
client->onDisconnected.connect(bind(&handleDisconnected, client, _1, CONFIG_STRING(&cfg, "service.jid")));

View file

@ -68,6 +68,10 @@ class ManagerConfig {
return m_variables[key];
}
bool hasKey(const std::string &key) {
return m_variables.find(key) != m_variables.end();
}
/// Returns path to config file from which data were loaded.
const std::string &getManagerConfigFile() { return m_file; }

View file

@ -1,6 +1,12 @@
cmake_minimum_required(VERSION 2.6)
FILE(GLOB SRC *.cpp *.h)
FILE(GLOB_RECURSE SWIFTEN_SRC ../include/Swiften/*.cpp)
# Build without openssl on windows
if (WIN32)
string(REGEX REPLACE "[^;]+;?/OpenSSL/[^;]+;?" "" SWIFTEN_SRC "${SWIFTEN_SRC}")
endif()
FILE(GLOB HEADERS ../include/transport/*.h)
if (CPPUNIT_FOUND)
@ -35,16 +41,16 @@ if (CMAKE_COMPILER_IS_GNUCXX)
endif()
if (WIN32)
TARGET_LINK_LIBRARIES(transport transport-plugin ${PQXX_LIBRARY} ${PQ_LIBRARY} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES})
TARGET_LINK_LIBRARIES(transport transport-plugin ${PQXX_LIBRARY} ${PQ_LIBRARY} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
else (WIN32)
TARGET_LINK_LIBRARIES(transport transport-plugin ${PQXX_LIBRARY} ${PQ_LIBRARY} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES} ${POPT_LIBRARY})
TARGET_LINK_LIBRARIES(transport transport-plugin ${PQXX_LIBRARY} ${PQ_LIBRARY} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES} ${POPT_LIBRARY})
endif(WIN32)
SET_TARGET_PROPERTIES(transport PROPERTIES
VERSION ${TRANSPORT_VERSION} SOVERSION ${TRANSPORT_VERSION}
)
INSTALL(TARGETS transport LIBRARY DESTINATION lib ARCHIVE DESTINATION lib COMPONENT libraries)
INSTALL(TARGETS transport LIBRARY DESTINATION ${LIB_INSTALL_DIR} ARCHIVE DESTINATION ${LIB_INSTALL_DIR} COMPONENT libraries)
#CONFIGURE_FILE(transport.pc.in "${CMAKE_CURRENT_BINARY_DIR}/transport.pc")
#INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/transport.pc" DESTINATION lib/pkgconfig)

View file

@ -26,16 +26,14 @@
#include "transport/rostermanager.h"
#include "transport/usermanager.h"
#include "transport/networkpluginserver.h"
#include "transport/logging.h"
#include "storageresponder.h"
#include "log4cxx/logger.h"
#include "transport/memoryusage.h"
#include <boost/foreach.hpp>
using namespace log4cxx;
namespace Transport {
static LoggerPtr logger = Logger::getLogger("AdminInterface");
DEFINE_LOGGER(logger, "AdminInterface");
static std::string getArg(const std::string &body) {
std::string ret;
@ -61,11 +59,13 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
if (!message->getTo().getNode().empty())
return;
if (message->getFrom().toBare().toString() != CONFIG_STRING(m_component->getConfig(), "service.admin_jid")) {
LOG4CXX_WARN(logger, "Message not from admin user, but from " << message->getFrom().toBare().toString());
return;
std::vector<std::string> const &x = CONFIG_VECTOR(m_component->getConfig(),"service.admin_jid");
if (std::find(x.begin(), x.end(), message->getFrom().toBare().toString()) == x.end()) {
LOG4CXX_WARN(logger, "Message not from admin user, but from " << message->getFrom().toBare().toString());
return;
}
// Ignore empty messages
if (message->getBody().empty()) {
return;
@ -112,7 +112,7 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
for (std::list <NetworkPluginServer::Backend *>::const_iterator b = backends.begin(); b != backends.end(); b++) {
NetworkPluginServer::Backend *backend = *b;
lst += "Backend " + boost::lexical_cast<std::string>(id);
lst += "Backend " + boost::lexical_cast<std::string>(id) + " (ID=" + backend->id + ")";
lst += backend->acceptUsers ? "" : " - not-accepting";
lst += backend->longRun ? " - long-running" : "";
lst += ":\n";
@ -204,7 +204,7 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
int id = 1;
const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
lst += "Backend " + boost::lexical_cast<std::string>(id) + ": " + boost::lexical_cast<std::string>(backend->res) + "\n";
lst += "Backend " + boost::lexical_cast<std::string>(id) + " (ID=" + backend->id + "): " + boost::lexical_cast<std::string>(backend->res) + "\n";
id++;
}
@ -215,7 +215,7 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
int id = 1;
const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
lst += "Backend " + boost::lexical_cast<std::string>(id) + ": " + boost::lexical_cast<std::string>(backend->shared) + "\n";
lst += "Backend " + boost::lexical_cast<std::string>(id) + " (ID=" + backend->id + "): " + boost::lexical_cast<std::string>(backend->shared) + "\n";
id++;
}
@ -226,7 +226,7 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
int id = 1;
const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
lst += "Backend " + boost::lexical_cast<std::string>(id) + ": " + boost::lexical_cast<std::string>(backend->res - backend->shared) + "\n";
lst += "Backend " + boost::lexical_cast<std::string>(id) + " (ID=" + backend->id + "): " + boost::lexical_cast<std::string>(backend->res - backend->shared) + "\n";
id++;
}
@ -238,10 +238,10 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
if (backend->users.size() == 0) {
lst += "Backend " + boost::lexical_cast<std::string>(id) + ": 0\n";
lst += "Backend " + boost::lexical_cast<std::string>(id) + " (ID=" + backend->id + "): 0\n";
}
else {
lst += "Backend " + boost::lexical_cast<std::string>(id) + ": " + boost::lexical_cast<std::string>((backend->res - backend->init_res) / backend->users.size()) + "\n";
lst += "Backend " + boost::lexical_cast<std::string>(id) + " (ID=" + backend->id + "): " + boost::lexical_cast<std::string>((backend->res - backend->init_res) / backend->users.size()) + "\n";
}
id++;
}
@ -251,6 +251,22 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
else if (message->getBody() == "collect_backend") {
m_server->collectBackend();
}
else if (message->getBody() == "crashed_backends") {
std::string lst;
const std::vector<std::string> &backends = m_server->getCrashedBackends();
BOOST_FOREACH(const std::string &backend, backends) {
lst += backend + "\n";
}
message->setBody(lst);
}
else if (message->getBody() == "messages_from_xmpp") {
int msgCount = m_userManager->getMessagesToBackend();
message->setBody(boost::lexical_cast<std::string>(msgCount));
}
else if (message->getBody() == "messages_to_xmpp") {
int msgCount = m_userManager->getMessagesToXMPP();
message->setBody(boost::lexical_cast<std::string>(msgCount));
}
else if (message->getBody().find("help") == 0) {
std::string help;
help += "General:\n";
@ -261,8 +277,12 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
help += " online_users_count - number of online users\n";
help += " online_users_per_backend - shows online users per backends\n";
help += " has_online_user <bare_JID> - returns 1 if user is online\n";
help += "Messages:\n";
help += " messages_from_xmpp - get number of messages received from XMPP users\n";
help += " messages_to_xmpp - get number of messages sent to XMPP users\n";
help += "Backends:\n";
help += " backends_count - number of active backends\n";
help += " crashed_backends - returns IDs of crashed backends\n";
help += "Memory:\n";
help += " res_memory - Total RESident memory spectrum2 and its backends use in KB\n";
help += " shr_memory - Total SHaRed memory spectrum2 backends share together in KB\n";

View file

@ -29,16 +29,14 @@
#include "transport/user.h"
#include "transport/buddy.h"
#include "transport/rostermanager.h"
#include "log4cxx/logger.h"
using namespace log4cxx;
#include "transport/logging.h"
using namespace Swift;
using namespace boost;
namespace Transport {
static LoggerPtr logger = Logger::getLogger("BlockResponder");
DEFINE_LOGGER(logger, "BlockResponder");
BlockResponder::BlockResponder(Swift::IQRouter *router, UserManager *userManager) : Swift::SetResponder<BlockPayload>(router) {
m_userManager = userManager;

View file

@ -26,7 +26,8 @@
namespace Transport {
Buddy::Buddy(RosterManager *rosterManager, long id) : m_id(id), m_flags(BUDDY_NO_FLAG), m_rosterManager(rosterManager){
Buddy::Buddy(RosterManager *rosterManager, long id) : m_id(id), m_flags(BUDDY_NO_FLAG), m_rosterManager(rosterManager),
m_subscription(Ask) {
// m_rosterManager->setBuddy(this);
}
@ -64,12 +65,12 @@ const Swift::JID &Buddy::getJID() {
return m_jid;
}
void Buddy::setSubscription(const std::string &subscription) {
// m_subscription = subscription;
void Buddy::setSubscription(Subscription subscription) {
m_subscription = subscription;
}
const std::string Buddy::getSubscription() {
return "ask";
Buddy::Subscription Buddy::getSubscription() {
return m_subscription;
}
Swift::Presence::ref Buddy::generatePresenceStanza(int features, bool only_new) {
@ -147,7 +148,6 @@ void Buddy::handleBuddyChanged() {
if (presence) {
m_rosterManager->getUser()->getComponent()->getStanzaChannel()->sendPresence(presence);
}
m_rosterManager->handleBuddyChanged(this);
}
void Buddy::handleVCardReceived(const std::string &id, Swift::VCard::ref vcard) {

View file

@ -19,7 +19,6 @@
*/
#include "transport/config.h"
#include "transport/util.h"
#include <fstream>
#ifdef _MSC_VER
#include <direct.h>
@ -28,9 +27,23 @@
#define PATH_MAX MAX_PATH
#endif
#include "iostream"
#include "boost/version.hpp"
#define BOOST_MAJOR_VERSION BOOST_VERSION / 100000
#define BOOST_MINOR_VERSION BOOST_VERSION / 100 % 1000
using namespace boost::program_options;
namespace Transport {
static int getRandomPort(const std::string &s) {
unsigned long r = 0;
BOOST_FOREACH(char c, s) {
r += (int) c;
}
srand(time(NULL) + r);
return 30000 + rand() % 10000;
}
bool Config::load(const std::string &configfile, boost::program_options::options_description &opts, const std::string &jid) {
std::ifstream ifs(configfile.c_str());
@ -63,14 +76,14 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
("service.protocol", value<std::string>()->default_value(""), "Protocol")
("service.pidfile", value<std::string>()->default_value("/var/run/spectrum2/$jid.pid"), "Full path to pid file")
("service.working_dir", value<std::string>()->default_value("/var/lib/spectrum2/$jid"), "Working dir")
("service.allowed_servers", value<std::string>()->default_value(""), "Only users from these servers can connect")
("service.allowed_servers", value<std::vector<std::string> >()->multitoken(), "Only users from these servers can connect")
("service.server_mode", value<bool>()->default_value(false), "True if Spectrum should behave as server")
("service.users_per_backend", value<int>()->default_value(100), "Number of users per one legacy network backend")
("service.backend_host", value<std::string>()->default_value("localhost"), "Host to bind backend server to")
("service.backend_port", value<std::string>()->default_value("0"), "Port to bind backend server to")
("service.cert", value<std::string>()->default_value(""), "PKCS#12 Certificate.")
("service.cert_password", value<std::string>()->default_value(""), "PKCS#12 Certificate password.")
("service.admin_jid", value<std::string>()->default_value(""), "Administrator jid.")
("service.admin_jid", value<std::vector<std::string> >()->multitoken(), "Administrator jid.")
("service.admin_password", value<std::string>()->default_value(""), "Administrator password.")
("service.reuse_old_backends", value<bool>()->default_value(true), "True if Spectrum should use old backends which were full in the past.")
("service.idle_reconnect_time", value<int>()->default_value(0), "Time in seconds after which idle users are reconnected to let their backend die.")
@ -86,11 +99,14 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
("registration.instructions", value<std::string>()->default_value("Enter your legacy network username and password."), "Instructions showed to user in registration form")
("registration.username_label", value<std::string>()->default_value("Legacy network username:"), "Label for username field")
("registration.username_mask", value<std::string>()->default_value(""), "Username mask")
("registration.auto_register", value<bool>()->default_value(false), "Register new user automatically when the presence arrives.")
("registration.encoding", value<std::string>()->default_value("utf8"), "Default encoding in registration form")
("registration.require_local_account", value<bool>()->default_value(false), "True if users have to have a local account to register to this transport from remote servers.")
("registration.local_username_label", value<std::string>()->default_value("Local username:"), "Label for local usernme field")
("registration.local_account_server", value<std::string>()->default_value("localhost"), "The server on which the local accounts will be checked for validity")
("registration.local_account_server_timeout", value<int>()->default_value(10000), "Timeout when checking local user on local_account_server (msecs)")
("gateway_responder.prompt", value<std::string>()->default_value("Contact ID"), "Value of <prompt> </promt> field")
("gateway_responder.label", value<std::string>()->default_value("Enter legacy network contact ID."), "Label for add contact ID field")
("database.type", value<std::string>()->default_value("none"), "Database type.")
("database.database", value<std::string>()->default_value("/var/lib/spectrum2/$jid/database.sql"), "Database used to store data")
("database.server", value<std::string>()->default_value("localhost"), "Database server.")
@ -106,6 +122,13 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
("backend.no_vcard_fetch", value<bool>()->default_value(false), "True if VCards for buddies should not be fetched. Only avatars will be forwarded.")
;
// 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();
store(parsed, m_variables);
}
parsed_options parsed = parse_config_file(ifs, opts, true);
bool found_working = false;
@ -126,7 +149,7 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
else if (opt.string_key == "service.backend_port") {
found_backend_port = true;
if (opt.value[0] == "0") {
opt.value[0] = boost::lexical_cast<std::string>(Util::getRandomPort(_jid.empty() ? jid : _jid));
opt.value[0] = boost::lexical_cast<std::string>(getRandomPort(_jid.empty() ? jid : _jid));
}
}
else if (opt.string_key == "service.working_dir") {
@ -152,7 +175,7 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
}
if (!found_backend_port) {
std::vector<std::string> value;
std::string p = boost::lexical_cast<std::string>(Util::getRandomPort(_jid.empty() ? jid : _jid));
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));
}
@ -185,8 +208,17 @@ bool Config::load(std::istream &ifs) {
}
bool Config::load(const std::string &configfile, const std::string &jid) {
options_description opts("Transport options");
return load(configfile, opts, jid);
try {
options_description opts("Transport options");
return load(configfile, opts, jid);
} catch ( const boost::program_options::multiple_occurrences& e ) {
#if (BOOST_MAJOR_VERSION >= 1 && BOOST_MINOR_VERSION >= 42)
std::cerr << configfile << " parsing error: " << e.what() << " from option: " << e.get_option_name() << std::endl;
#else
std::cerr << configfile << " parsing error: " << e.what() << std::endl;
#endif
return false;
}
}
bool Config::reload() {

View file

@ -25,14 +25,9 @@
#include "transport/transport.h"
#include "transport/buddy.h"
#include "transport/rostermanager.h"
#include "log4cxx/logger.h"
using namespace log4cxx;
namespace Transport {
// static LoggerPtr logger = Logger::getLogger("Conversation");
Conversation::Conversation(ConversationManager *conversationManager, const std::string &legacyName, bool isMUC) : m_conversationManager(conversationManager) {
m_legacyName = legacyName;
m_conversationManager->addConversation(this);

View file

@ -24,16 +24,14 @@
#include "transport/buddy.h"
#include "transport/factory.h"
#include "transport/user.h"
#include "transport/logging.h"
#include "Swiften/Roster/SetRosterRequest.h"
#include "Swiften/Elements/RosterPayload.h"
#include "Swiften/Elements/RosterItemPayload.h"
#include "log4cxx/logger.h"
using namespace log4cxx;
namespace Transport {
static LoggerPtr logger = Logger::getLogger("ConversationManager");
DEFINE_LOGGER(logger, "ConversationManager");
ConversationManager::ConversationManager(User *user, Component *component){
m_user = user;

View file

@ -88,11 +88,15 @@ bool DiscoInfoResponder::handleGetRequest(const Swift::JID& from, const Swift::J
// presence for transport
if (to.getNode().empty()) {
sendResponse(from, id, boost::shared_ptr<DiscoInfo>(new DiscoInfo(m_transportInfo)));
boost::shared_ptr<DiscoInfo> res(new DiscoInfo(m_transportInfo));
res->setNode(info->getNode());
sendResponse(from, id, res);
}
// presence for buddy
else {
sendResponse(from, to, id, boost::shared_ptr<DiscoInfo>(new DiscoInfo(m_buddyInfo)));
boost::shared_ptr<DiscoInfo> res(new DiscoInfo(m_buddyInfo));
res->setNode(info->getNode());
sendResponse(from, to, id, res);
}
return true;
}

View file

@ -23,13 +23,11 @@
#include "transport/usermanager.h"
#include "transport/user.h"
#include "transport/buddy.h"
#include "log4cxx/logger.h"
using namespace log4cxx;
#include "transport/logging.h"
namespace Transport {
static LoggerPtr logger = Logger::getLogger("FileTransferManager");
DEFINE_LOGGER(logger, "FileTransferManager");
FileTransferManager::FileTransferManager(Component *component, UserManager *userManager) {
m_component = component;

63
src/gatewayresponder.cpp Normal file
View file

@ -0,0 +1,63 @@
/**
* 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 "transport/gatewayresponder.h"
#include <iostream>
#include <boost/bind.hpp>
#include "Swiften/Queries/IQRouter.h"
#include "Swiften/Elements/RawXMLPayload.h"
#include "Swiften/Swiften.h"
#include "transport/usermanager.h"
#include "transport/user.h"
#include "transport/transport.h"
#include "transport/logging.h"
using namespace Swift;
using namespace boost;
namespace Transport {
DEFINE_LOGGER(logger, "GatewayResponder");
GatewayResponder::GatewayResponder(Swift::IQRouter *router, UserManager *userManager) : Swift::Responder<GatewayPayload>(router) {
m_userManager = userManager;
}
GatewayResponder::~GatewayResponder() {
}
bool GatewayResponder::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::GatewayPayload> payload) {
std::string prompt = CONFIG_STRING(m_userManager->getComponent()->getConfig(), "gateway_responder.prompt");
std::string label = CONFIG_STRING(m_userManager->getComponent()->getConfig(), "gateway_responder.label");
sendResponse(from, id, boost::shared_ptr<GatewayPayload>(new GatewayPayload(Swift::JID(), label, prompt)));
return true;
}
bool GatewayResponder::handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::GatewayPayload> payload) {
std::string prompt = payload->getPrompt();
std::string escaped = Swift::JID::getEscapedNode(prompt);
std::string jid = escaped + "@" + m_userManager->getComponent()->getJID().toBare().toString();
sendResponse(from, id, boost::shared_ptr<GatewayPayload>(new GatewayPayload(jid)));
return true;
}
}

View file

@ -32,11 +32,11 @@ LocalBuddy::~LocalBuddy() {
}
void LocalBuddy::setAlias(const std::string &alias) {
if (m_firstSet) {
m_firstSet = false;
m_alias = alias;
return;
}
// if (m_firstSet) {
// m_firstSet = false;
// m_alias = alias;
// return;
// }
bool changed = m_alias != alias;
m_alias = alias;
@ -48,4 +48,24 @@ void LocalBuddy::setAlias(const std::string &alias) {
}
}
void LocalBuddy::setGroups(const std::vector<std::string> &groups) {
bool changed = m_groups.size() != groups.size();
if (!changed) {
for (int i = 0; i != m_groups.size(); i++) {
if (m_groups[i] != groups[i]) {
changed = true;
break;
}
}
}
m_groups = groups;
if (changed) {
if (getRosterManager()->getUser()->getComponent()->inServerMode() || getRosterManager()->isRemoteRosterSupported()) {
getRosterManager()->sendBuddyRosterPush(this);
}
getRosterManager()->storeBuddy(this);
}
}
}

Some files were not shown because too many files have changed in this diff Show more