diff --git a/backends/libircclient-qt/main.cpp b/backends/libircclient-qt/main.cpp index 83723532..f5af84fb 100644 --- a/backends/libircclient-qt/main.cpp +++ b/backends/libircclient-qt/main.cpp @@ -15,11 +15,22 @@ #include #include "Swiften/EventLoop/Qt/QtEventLoop.h" #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; -IRCNetworkPlugin * np = NULL; +using namespace log4cxx; + +NetworkPlugin * np = NULL; int main (int argc, char* argv[]) { std::string host; @@ -72,8 +83,39 @@ 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(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); + } + Swift::QtEventLoop eventLoop; - np = new IRCNetworkPlugin(&config, &eventLoop, host, port); + + if (config.getUnregistered().find("service.irc_server") == config.getUnregistered().end()) { + np = new IRCNetworkPlugin(&config, &eventLoop, host, port); + } + else { + np = new SingleIRCNetworkPlugin(&config, &eventLoop, host, port); + } return app.exec(); } diff --git a/backends/libircclient-qt/session.cpp b/backends/libircclient-qt/session.cpp index 792bceed..1d216016 100644 --- a/backends/libircclient-qt/session.cpp +++ b/backends/libircclient-qt/session.cpp @@ -13,6 +13,12 @@ #include #include "Swiften/Elements/StatusShow.h" +#include "log4cxx/logger.h" + +using namespace log4cxx; + +static LoggerPtr logger = log4cxx::Logger::getLogger("IRCSession"); + MyIrcSession::MyIrcSession(const std::string &user, NetworkPlugin *np, const std::string &suffix, QObject* parent) : Irc::Session(parent) { this->np = np; @@ -23,24 +29,24 @@ MyIrcSession::MyIrcSession(const std::string &user, NetworkPlugin *np, const std } void MyIrcSession::on_connected(){ - std::cout << "connected:\n"; +// std::cout << "connected:\n"; } void MyIrcSession::on_disconnected() { - std::cout << "disconnected:\n"; +// std::cout << "disconnected:\n"; if (suffix.empty()) np->handleDisconnected(user, 0, ""); } void MyIrcSession::on_bufferAdded(Irc::Buffer* buffer) { - qDebug() << "buffer added:" << buffer->receiver(); +// qDebug() << "buffer added:" << buffer->receiver(); } void MyIrcSession::on_bufferRemoved(Irc::Buffer* buffer) { - qDebug() << "buffer removed:" << buffer->receiver(); +// qDebug() << "buffer removed:" << buffer->receiver(); } Irc::Buffer* MyIrcSession::createBuffer(const QString& receiver) @@ -80,7 +86,7 @@ MyIrcBuffer::MyIrcBuffer(const QString& receiver, const std::string &user, Netwo void MyIrcBuffer::on_receiverChanged(const QString& receiver) { - qDebug() << "receiver changed:" << receiver; +// qDebug() << "receiver changed:" << receiver; } bool MyIrcBuffer::correctNickname(std::string &nickname) { @@ -94,7 +100,7 @@ bool MyIrcBuffer::correctNickname(std::string &nickname) { } void MyIrcBuffer::on_joined(const QString& origin) { - qDebug() << "joined:" << receiver() << origin; + LOG4CXX_INFO(logger, user << ": " << origin.toStdString() << " joined " << receiver().toStdString() + suffix); bool flags = 0; std::string nickname = origin.toStdString(); flags = correctNickname(nickname); @@ -102,6 +108,7 @@ void MyIrcBuffer::on_joined(const QString& origin) { } void MyIrcBuffer::on_parted(const QString& origin, const QString& message) { + LOG4CXX_INFO(logger, user << ": " << origin.toStdString() << " parted " << receiver().toStdString() + suffix); qDebug() << "parted:" << receiver() << origin << message; bool flags = 0; std::string nickname = origin.toStdString(); @@ -109,14 +116,12 @@ void MyIrcBuffer::on_parted(const QString& origin, const QString& message) { np->handleParticipantChanged(user, nickname, receiver().toStdString() + suffix,(int) flags, pbnetwork::STATUS_NONE, message.toStdString()); } -void MyIrcBuffer::on_quit(const QString& origin, const QString& message) -{ - qDebug() << "quit:" << receiver() << origin << message; +void MyIrcBuffer::on_quit(const QString& origin, const QString& message) { on_parted(origin, message); } void MyIrcBuffer::on_nickChanged(const QString& origin, const QString& nick) { - qDebug() << "nick changed:" << receiver() << origin << nick; + LOG4CXX_INFO(logger, user << ": " << origin.toStdString() << " changed nickname to " << nick.toStdString()); std::string nickname = origin.toStdString(); bool flags = p->m_modes[receiver().toStdString() + nickname]; // std::cout << receiver().toStdString() + nickname << " " << flags << "\n"; @@ -125,10 +130,10 @@ void MyIrcBuffer::on_nickChanged(const QString& origin, const QString& nick) { void MyIrcBuffer::on_modeChanged(const QString& origin, const QString& mode, const QString& args) { // mode changed: "#testik" "HanzZ" "+o" "hanzz_k" - qDebug() << "mode changed:" << receiver() << origin << mode << args; std::string nickname = args.toStdString(); if (nickname.empty()) return; + LOG4CXX_INFO(logger, user << ": " << nickname << " changed mode to " << mode.toStdString()); if (mode == "+o") { p->m_modes[receiver().toStdString() + nickname] = 1; } @@ -141,29 +146,28 @@ void MyIrcBuffer::on_modeChanged(const QString& origin, const QString& mode, con void MyIrcBuffer::on_topicChanged(const QString& origin, const QString& topic) { //topic changed: "#testik" "HanzZ" "test" - qDebug() << "topic changed:" << receiver() << origin << topic; - np->handleSubject(user, receiver().toStdString() + suffix, topic.toStdString(), origin.toStdString()); + LOG4CXX_INFO(logger, user << ": " << origin.toStdString() << " topic changed to " << topic.toStdString()); + np->handleSubject(user, receiver().toStdString() + suffix, topic.toStdString(), origin.toStdString()); } -void MyIrcBuffer::on_invited(const QString& origin, const QString& receiver, const QString& channel) -{ - qDebug() << "invited:" << Irc::Buffer::receiver() << origin << receiver << channel; +void MyIrcBuffer::on_invited(const QString& origin, const QString& receiver, const QString& channel) { + qDebug() << "invited:" << Irc::Buffer::receiver() << origin << receiver << channel; } -void MyIrcBuffer::on_kicked(const QString& origin, const QString& nick, const QString& message) -{ - qDebug() << "kicked:" << receiver() << origin << nick << message; +void MyIrcBuffer::on_kicked(const QString& origin, const QString& nick, const QString& message) { + qDebug() << "kicked:" << receiver() << origin << nick << message; } void MyIrcBuffer::on_messageReceived(const QString& origin, const QString& message, Irc::Buffer::MessageFlags flags) { - qDebug() << "message received:" << receiver() << origin << message << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)"); + // qDebug() << "message received:" << receiver() << origin << message << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)"); + if (!receiver().startsWith("#") && (flags & Irc::Buffer::EchoFlag)) return; std::string r = receiver().toStdString(); // if (!suffix.empty()) { // r = receiver().replace('@', '%').toStdString(); // } - + LOG4CXX_INFO(logger, user << ": Message from " << r); if (r.find("#") == 0) { np->handleMessage(user, r + suffix, message.toStdString(), origin.toStdString()); } @@ -223,7 +227,8 @@ void MyIrcBuffer::on_numericMessageReceived(const QString& origin, uint code, co } break; } - qDebug() << "numeric message received:" << receiver() << origin << code << params; + LOG4CXX_INFO(logger, user << ": Numeric message received " << receiver().toStdString() << " " << origin.toStdString() << " " << code); + //qDebug() << "numeric message received:" << receiver() << origin << code << params; } void MyIrcBuffer::on_unknownMessageReceived(const QString& origin, const QStringList& params) diff --git a/backends/libircclient-qt/singleircnetworkplugin.cpp b/backends/libircclient-qt/singleircnetworkplugin.cpp new file mode 100644 index 00000000..64260a23 --- /dev/null +++ b/backends/libircclient-qt/singleircnetworkplugin.cpp @@ -0,0 +1,104 @@ +#include "singleircnetworkplugin.h" +#include "log4cxx/logger.h" + +using namespace log4cxx; + +static LoggerPtr logger = log4cxx::Logger::getLogger("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); + connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData())); + + LOG4CXX_INFO(logger, "SingleIRCNetworkPlugin for server " << m_server << " initialized."); +} + +void SingleIRCNetworkPlugin::readData() { + size_t availableBytes = m_socket->bytesAvailable(); + if (availableBytes == 0) + return; + + std::string d = std::string(m_socket->readAll().data(), availableBytes); + handleDataRead(d); +} + +void SingleIRCNetworkPlugin::sendData(const std::string &string) { + m_socket->write(string.c_str(), string.size()); +} + +void SingleIRCNetworkPlugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) { + // legacy name is users nickname + if (m_sessions[user] != NULL) { + LOG4CXX_WARN(logger, user << ": Already logged in."); + return; + } + LOG4CXX_INFO(logger, user << ": Connecting " << m_server << " as " << legacyName); + + MyIrcSession *session = new MyIrcSession(user, this); + session->setNick(QString::fromStdString(legacyName)); + session->connectToServer(QString::fromStdString(m_server), 6667); + m_sessions[user] = session; +} + +void SingleIRCNetworkPlugin::handleLogoutRequest(const std::string &user, const std::string &legacyName) { + if (m_sessions[user] == NULL) { + LOG4CXX_WARN(logger, user << ": Already disconnected."); + return; + } + LOG4CXX_INFO(logger, user << ": Disconnecting."); + + m_sessions[user]->disconnectFromServer(); + m_sessions[user]->deleteLater(); + m_sessions.erase(user); +} + +void SingleIRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &/*xhtml*/) { + if (m_sessions[user] == NULL) { + LOG4CXX_WARN(logger, user << ": Message received for unconnected user"); + return; + } + + // handle PMs + std::string r = legacyName; + if (legacyName.find("/") == std::string::npos) { + r = legacyName.substr(0, r.find("@")); + } + else { + r = legacyName.substr(legacyName.find("/") + 1); + } + + LOG4CXX_INFO(logger, user << ": Forwarding message to " << r); + m_sessions[user]->message(QString::fromStdString(r), QString::fromStdString(message)); +} + +void SingleIRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) { + if (m_sessions[user] == NULL) { + LOG4CXX_WARN(logger, user << ": Join room requested for unconnected user"); + return; + } + + LOG4CXX_INFO(logger, user << ": Joining " << room); + m_sessions[user]->addAutoJoinChannel(QString::fromStdString(room)); + m_sessions[user]->join(QString::fromStdString(room), QString::fromStdString(password)); + m_sessions[user]->rooms += 1; + + // update nickname, because we have nickname per session, no nickname per room. + handleRoomNicknameChanged(user, room, m_sessions[user]->nick().toStdString()); +} + +void SingleIRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std::string &room) { + std::string r = room; + std::string u = user; + + if (m_sessions[u] == NULL) { + LOG4CXX_WARN(logger, user << ": Leave room requested for unconnected user"); + return; + } + + LOG4CXX_INFO(logger, user << ": Leaving " << room); + m_sessions[u]->part(QString::fromStdString(r)); + m_sessions[u]->removeAutoJoinChannel(QString::fromStdString(r)); + m_sessions[u]->rooms -= 1; +} diff --git a/backends/libircclient-qt/singleircnetworkplugin.h b/backends/libircclient-qt/singleircnetworkplugin.h new file mode 100644 index 00000000..e59499d5 --- /dev/null +++ b/backends/libircclient-qt/singleircnetworkplugin.h @@ -0,0 +1,39 @@ + +#pragma once + +#include "transport/config.h" +#include "transport/networkplugin.h" +#include "session.h" +#include +#include +#include "Swiften/EventLoop/Qt/QtEventLoop.h" +#include "ircnetworkplugin.h" + + +class SingleIRCNetworkPlugin : public QObject, public NetworkPlugin { + Q_OBJECT + + public: + SingleIRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port); + + void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password); + + 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*/); + + void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password); + + void handleLeaveRoomRequest(const std::string &user, const std::string &room); + + std::map m_sessions; + + public slots: + void readData(); + void sendData(const std::string &string); + + private: + Config *config; + QTcpSocket *m_socket; + std::string m_server; +}; diff --git a/spectrum/src/sample.cfg b/spectrum/src/sample.cfg index 71b1d23b..3fdca1d1 100644 --- a/spectrum/src/sample.cfg +++ b/spectrum/src/sample.cfg @@ -5,6 +5,7 @@ server = 127.0.0.1 port = 5222 server_mode = 1 backend_host=localhost +pidfile=./test.pid # < this option doesn't work yet backend_port=10001 admin_username=admin @@ -12,13 +13,14 @@ 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/libpurple/spectrum2_libpurple_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=/home/hanzz/code/libtransport/backends/libircclient-qt/spectrum2_libircclient-qt_backend #protocol=prpl-msn protocol=any #protocol=prpl-icq +irc_server=irc.freenode.org [backend] #default_avatar=catmelonhead.jpg diff --git a/src/userregistration.cpp b/src/userregistration.cpp index e1a1731a..646722ed 100644 --- a/src/userregistration.cpp +++ b/src/userregistration.cpp @@ -329,10 +329,7 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID } // Register or change password - if (payload->getUsername()->empty() || - (payload->getPassword()->empty() && CONFIG_STRING(m_config, "service.protocol") != "twitter" && CONFIG_STRING(m_config, "service.protocol") != "bonjour") - ) - { + if (payload->getUsername()->empty()) { sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify); return true; }