diff --git a/CMakeLists.txt b/CMakeLists.txt index c5e63bc5..60544139 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,7 @@ option(ENABLE_TWITTER "Build Twitter plugin" ON) option(ENABLE_YAHOO2 "Build Libyahoo2 plugin" ON) option(ENABLE_DOCS "Build Docs" ON) -option(ENABLE_LOG "Build with logging using Log4cxx" ON) +# option(ENABLE_LOG "Build with logging using Log4cxx" ON) option(ENABLE_TESTS "Build Tests using CppUnit" OFF) MACRO(LIST_CONTAINS var value) @@ -225,7 +225,7 @@ if(ENABLE_DOCS) find_package(Doxygen) endif() -if(ENABLE_LOG) +# if(ENABLE_LOG) if(LOG4CXX_INCLUDE_DIR AND LOG4CXX_LIBRARY) set(LOG4CXX_LIBRARIES ${LOG4CXX_LIBRARY}) set(LOG4CXX_FOUND 1) @@ -234,7 +234,7 @@ if(ENABLE_LOG) set(log4cxx_DIR "${CMAKE_SOURCE_DIR}/cmake_modules") find_package(log4cxx) endif() -endif() +# endif() # FIND CPPUNIT if(ENABLE_TESTS) @@ -423,10 +423,10 @@ if (LOG4CXX_FOUND) ADD_DEFINITIONS(-DWITH_LOG4CXX) else() set(LOG4CXX_LIBRARIES "") - if(ENABLE_LOG) + if (WIN32) message("Log4cxx : no (install log4cxx-devel)") - else(ENABLE_LOG) - message("Log4cxx : no (user disabled)") + else() + message(FATAL_ERROR "Log4cxx : no (install log4cxx-devel)") endif() endif() diff --git a/backends/libcommuni/ircnetworkplugin.cpp b/backends/libcommuni/ircnetworkplugin.cpp index 2eea86cb..4996a874 100644 --- a/backends/libcommuni/ircnetworkplugin.cpp +++ b/backends/libcommuni/ircnetworkplugin.cpp @@ -56,6 +56,7 @@ void IRCNetworkPlugin::readData() { if (m_servers.empty()) { NetworkPlugin::PluginConfig cfg; cfg.setNeedRegistration(false); + cfg.setSupportMUC(true); sendConfig(cfg); } } diff --git a/backends/libcommuni/main.cpp b/backends/libcommuni/main.cpp index 99b3bc58..d2013b50 100644 --- a/backends/libcommuni/main.cpp +++ b/backends/libcommuni/main.cpp @@ -33,10 +33,10 @@ int main (int argc, char* argv[]) { return 1; } - QCoreApplication app(argc, argv); - Logging::initBackendLogging(cfg); + QCoreApplication app(argc, argv); + Swift::QtEventLoop eventLoop; diff --git a/backends/libcommuni/session.cpp b/backends/libcommuni/session.cpp index c8b271f6..c13297ff 100644 --- a/backends/libcommuni/session.cpp +++ b/backends/libcommuni/session.cpp @@ -86,6 +86,9 @@ bool MyIrcSession::correctNickname(std::string &nickname) { switch(nickname.at(0)) { case '@': nickname = nickname.substr(1); flags = 1; break; case '+': nickname = nickname.substr(1); break; + case '~': nickname = nickname.substr(1); break; + case '&': nickname = nickname.substr(1); break; + case '%': nickname = nickname.substr(1); break; default: break; } return flags; @@ -96,9 +99,9 @@ void MyIrcSession::on_joined(IrcMessage *message) { bool op = 0; std::string nickname = TO_UTF8(m->sender().name()); op = correctNickname(nickname); - getIRCBuddy(TO_UTF8(m->channel()), nickname).setOp(op); - np->handleParticipantChanged(user, nickname, TO_UTF8(m->channel()) + suffix, op, pbnetwork::STATUS_ONLINE); - LOG4CXX_INFO(logger, user << ": " << nickname << " joined " << TO_UTF8(m->channel()) + suffix); + getIRCBuddy(TO_UTF8(m->channel().toLower()), nickname).setOp(op); + np->handleParticipantChanged(user, nickname, TO_UTF8(m->channel().toLower()) + suffix, op, pbnetwork::STATUS_ONLINE); + LOG4CXX_INFO(logger, user << ": " << nickname << " joined " << TO_UTF8(m->channel().toLower()) + suffix); } @@ -107,9 +110,9 @@ void MyIrcSession::on_parted(IrcMessage *message) { bool op = 0; std::string nickname = TO_UTF8(m->sender().name()); op = correctNickname(nickname); - removeIRCBuddy(TO_UTF8(m->channel()), nickname); - LOG4CXX_INFO(logger, user << ": " << nickname << " parted " << TO_UTF8(m->channel()) + suffix); - np->handleParticipantChanged(user, nickname, TO_UTF8(m->channel()) + suffix, op, pbnetwork::STATUS_NONE, TO_UTF8(m->reason())); + removeIRCBuddy(TO_UTF8(m->channel().toLower()), nickname); + LOG4CXX_INFO(logger, user << ": " << nickname << " parted " << TO_UTF8(m->channel().toLower()) + suffix); + np->handleParticipantChanged(user, nickname, TO_UTF8(m->channel().toLower()) + suffix, op, pbnetwork::STATUS_NONE, TO_UTF8(m->reason())); } void MyIrcSession::on_quit(IrcMessage *message) { @@ -172,7 +175,7 @@ void MyIrcSession::on_topicChanged(IrcMessage *message) { correctNickname(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); + np->handleSubject(user, TO_UTF8(m->channel().toLower()) + suffix, TO_UTF8(m->topic()), nickname); } void MyIrcSession::on_messageReceived(IrcMessage *message) { @@ -190,7 +193,7 @@ void MyIrcSession::on_messageReceived(IrcMessage *message) { msg = QString("/me ") + msg; } - std::string target = TO_UTF8(m->target()); + std::string target = TO_UTF8(m->target().toLower()); LOG4CXX_INFO(logger, user << ": Message from " << target); if (target.find("#") == 0) { std::string nickname = TO_UTF8(m->sender().name()); @@ -229,10 +232,10 @@ void MyIrcSession::on_numericMessageReceived(IrcMessage *message) { if (nick.find("/") != std::string::npos) { nick = nick.substr(0, nick.find("/")); } - np->handleSubject(user, TO_UTF8(parameters[1]) + suffix, m_topicData, nick); + np->handleSubject(user, TO_UTF8(parameters[1].toLower()) + suffix, m_topicData, nick); break; case 352: { - channel = parameters[1]; + channel = parameters[1].toLower(); nick = TO_UTF8(parameters[5]); IRCBuddy &buddy = getIRCBuddy(TO_UTF8(channel), nick); @@ -249,7 +252,7 @@ void MyIrcSession::on_numericMessageReceived(IrcMessage *message) { break; } case 353: - channel = parameters[2]; + channel = parameters[2].toLower(); members = parameters[3].split(" "); LOG4CXX_INFO(logger, user << ": Received members for " << TO_UTF8(channel) << suffix); @@ -265,13 +268,33 @@ void MyIrcSession::on_numericMessageReceived(IrcMessage *message) { break; case 366: // ask /who to get away states - channel = parameters[1]; + channel = parameters[1].toLower(); LOG4CXX_INFO(logger, user << "Asking /who for channel " << TO_UTF8(channel)); sendCommand(IrcCommand::createWho(channel)); break; case 432: np->handleDisconnected(user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Erroneous Nickname"); break; + case 433: + for(AutoJoinMap::iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) { + np->handleParticipantChanged(user, TO_UTF8(nickName()), it->second->getChannel() + suffix, pbnetwork::PARTICIPANT_FLAG_CONFLICT); + } + if (suffix.empty()) { + np->handleDisconnected(user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Nickname is already in use"); + } + break; + case 436: + for(AutoJoinMap::iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) { + np->handleParticipantChanged(user, TO_UTF8(nickName()), it->second->getChannel() + suffix, pbnetwork::PARTICIPANT_FLAG_CONFLICT); + } + np->handleDisconnected(user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Nickname collision KILL"); + case 464: + for(AutoJoinMap::iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) { + np->handleParticipantChanged(user, TO_UTF8(nickName()), it->second->getChannel() + suffix, pbnetwork::PARTICIPANT_FLAG_NOT_AUTHORIZED); + } + if (suffix.empty()) { + np->handleDisconnected(user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Password incorrect"); + } case 321: m_rooms.clear(); m_names.clear(); @@ -287,6 +310,10 @@ void MyIrcSession::on_numericMessageReceived(IrcMessage *message) { break; } + if (m->code() >= 400 && m->code() < 500) { + LOG4CXX_INFO(logger, user << ": Error message received: " << message->toData().data()); + } + //qDebug() << "numeric message received:" << receiver() << origin << code << params; } diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index b232f8bf..36e2df3f 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -43,6 +43,7 @@ DEFINE_LOGGER(logger, "backend"); int main_socket; static int writeInput; +bool firstPing = true; using namespace Transport; @@ -549,6 +550,7 @@ class SpectrumNetworkPlugin : public NetworkPlugin { } purple_blist_add_buddy_wrapped(buddy, NULL, group ,NULL); purple_account_add_buddy_wrapped(account, buddy); + LOG4CXX_INFO(logger, "Adding new buddy " << buddyName.c_str() << " to legacy network roster"); } } } @@ -908,10 +910,6 @@ static void conv_write_im(PurpleConversation *conv, const char *who, const char // std::string msg = striped; // g_free(striped); - std::string w = purple_normalize_wrapped(account, who); - size_t pos = w.find("/"); - if (pos != std::string::npos) - w.erase((int) pos, w.length() - (int) pos); // Escape HTML characters. char *newline = purple_strdup_withhtml_wrapped(msg); @@ -948,11 +946,15 @@ static void conv_write_im(PurpleConversation *conv, const char *who, const char // LOG4CXX_INFO(logger, "Received message body='" << message_ << "' xhtml='" << xhtml_ << "'"); if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_IM) { + std::string w = purple_normalize_wrapped(account, who); + size_t pos = w.find("/"); + if (pos != std::string::npos) + w.erase((int) pos, w.length() - (int) pos); np->handleMessage(np->m_accounts[account], w, message_, "", xhtml_, timestamp); } else { - LOG4CXX_INFO(logger, "Received message body='" << message_ << "' name='" << purple_conversation_get_name_wrapped(conv) << "' " << w); - np->handleMessage(np->m_accounts[account], purple_conversation_get_name_wrapped(conv), message_, w, xhtml_, timestamp); + LOG4CXX_INFO(logger, "Received message body='" << message_ << "' name='" << purple_conversation_get_name_wrapped(conv) << "' " << who); + np->handleMessage(np->m_accounts[account], purple_conversation_get_name_wrapped(conv), message_, who, xhtml_, timestamp); } } @@ -1655,6 +1657,14 @@ static void transportDataReceived(gpointer data, gint source, PurpleInputConditi exit(errno); } std::string d = std::string(buffer, n); + + if (firstPing) { + firstPing = false; + NetworkPlugin::PluginConfig cfg; + cfg.setSupportMUC(true); + np->sendConfig(cfg); + } + np->handleDataRead(d); } else { diff --git a/backends/skype/main.cpp b/backends/skype/main.cpp index 1b09ef78..6e700132 100644 --- a/backends/skype/main.cpp +++ b/backends/skype/main.cpp @@ -202,6 +202,7 @@ class SpectrumNetworkPlugin : public NetworkPlugin { Skype *skype = m_sessions[user]; if (skype) { skype->send_command("SET USER " + buddyName + " BUDDYSTATUS 1"); + skype->send_command("SET USER " + buddyName + " ISAUTHORIZED FALSE"); } } @@ -605,10 +606,12 @@ bool Skype::loadSkypeBuddies() { void Skype::logout() { if (m_pid != 0) { - send_command("SET USERSTATUS INVISIBLE"); - send_command("SET USERSTATUS OFFLINE"); - sleep(2); - g_object_unref(m_proxy); + if (m_proxy) { + send_command("SET USERSTATUS INVISIBLE"); + send_command("SET USERSTATUS OFFLINE"); + sleep(2); + g_object_unref(m_proxy); + } LOG4CXX_INFO(logger, m_username << ": Terminating Skype instance (SIGTERM)"); kill((int) m_pid, SIGTERM); // Give skype a chance @@ -695,20 +698,9 @@ static void handle_skype_message(std::string &message, Skype *sk) { std::vector groups; np->handleBuddyChanged(sk->getUser(), cmd[1], alias, groups, status, mood_text); } - //TODO: handle RECEIVEDAUTHREQUEST and reply it with: -// void -// skype_auth_allow(gpointer sender) -// { -// skype_send_message("SET USER %s ISAUTHORIZED TRUE", sender); -// g_free(sender); -// } -// -// void -// skype_auth_deny(gpointer sender) -// { -// skype_send_message("SET USER %s ISAUTHORIZED FALSE", sender); -// g_free(sender); -// } + else if(cmd[2] == "RECEIVEDAUTHREQUEST") { + np->handleAuthorization(sk->getUser(), cmd[1]); + } } else if (cmd[0] == "CHATMESSAGE") { if (cmd[3] == "RECEIVED") { diff --git a/backends/swiften/main.cpp b/backends/swiften/main.cpp index 97368436..93137352 100644 --- a/backends/swiften/main.cpp +++ b/backends/swiften/main.cpp @@ -3,6 +3,8 @@ #include "transport/networkplugin.h" #include "transport/logging.h" +#include "boost/date_time/posix_time/posix_time.hpp" + // Swiften #include "Swiften/Swiften.h" @@ -32,7 +34,83 @@ Swift::SimpleEventLoop *loop_; // Plugins class SwiftenPlugin; -SwiftenPlugin *np = NULL; +NetworkPlugin *np = NULL; + +class MUCController { + public: + MUCController(const std::string &user, boost::shared_ptr client, const std::string &room, const std::string &nickname, const std::string &password) { + m_user = user; + m_room = room; + muc = client->getMUCManager()->createMUC(room); + if (!password.empty()) { + muc->setPassword(password); + } + + muc->onJoinComplete.connect(boost::bind(&MUCController::handleJoinComplete, this, _1)); + muc->onJoinFailed.connect(boost::bind(&MUCController::handleJoinFailed, this, _1)); + muc->onOccupantJoined.connect(boost::bind(&MUCController::handleOccupantJoined, this, _1)); + muc->onOccupantPresenceChange.connect(boost::bind(&MUCController::handleOccupantPresenceChange, this, _1)); + muc->onOccupantLeft.connect(boost::bind(&MUCController::handleOccupantLeft, this, _1, _2, _3)); + muc->onOccupantRoleChanged.connect(boost::bind(&MUCController::handleOccupantRoleChanged, this, _1, _2, _3)); + muc->onOccupantAffiliationChanged.connect(boost::bind(&MUCController::handleOccupantAffiliationChanged, this, _1, _2, _3)); + + muc->joinAs(nickname); + } + + virtual ~MUCController() { + muc->onJoinComplete.disconnect(boost::bind(&MUCController::handleJoinComplete, this, _1)); + muc->onJoinFailed.disconnect(boost::bind(&MUCController::handleJoinFailed, this, _1)); + muc->onOccupantJoined.disconnect(boost::bind(&MUCController::handleOccupantJoined, this, _1)); + muc->onOccupantPresenceChange.disconnect(boost::bind(&MUCController::handleOccupantPresenceChange, this, _1)); + muc->onOccupantLeft.disconnect(boost::bind(&MUCController::handleOccupantLeft, this, _1, _2, _3)); + muc->onOccupantRoleChanged.disconnect(boost::bind(&MUCController::handleOccupantRoleChanged, this, _1, _2, _3)); + muc->onOccupantAffiliationChanged.disconnect(boost::bind(&MUCController::handleOccupantAffiliationChanged, this, _1, _2, _3)); + } + + const std::string &getNickname() { + //return muc->getCurrentNick(); + return m_nick; + } + + void handleOccupantJoined(const Swift::MUCOccupant& occupant) { + np->handleParticipantChanged(m_user, occupant.getNick(), m_room, occupant.getRole() == Swift::MUCOccupant::Moderator, pbnetwork::STATUS_ONLINE); + } + + void handleOccupantLeft(const Swift::MUCOccupant& occupant, Swift::MUC::LeavingType type, const std::string& reason) { + np->handleParticipantChanged(m_user, occupant.getNick(), m_room, occupant.getRole() == Swift::MUCOccupant::Moderator, pbnetwork::STATUS_NONE); + } + + void handleOccupantPresenceChange(boost::shared_ptr presence) { + const Swift::MUCOccupant& occupant = muc->getOccupant(presence->getFrom().getResource()); + np->handleParticipantChanged(m_user, presence->getFrom().getResource(), m_room, (int) occupant.getRole() == Swift::MUCOccupant::Moderator, (pbnetwork::StatusType) presence->getShow(), presence->getStatus()); + } + + void handleOccupantRoleChanged(const std::string& nick, const Swift::MUCOccupant& occupant, const Swift::MUCOccupant::Role& oldRole) { + + } + + void handleOccupantAffiliationChanged(const std::string& nick, const Swift::MUCOccupant::Affiliation& affiliation, const Swift::MUCOccupant::Affiliation& oldAffiliation) { +// np->handleParticipantChanged(m_user, occupant->getNick(), m_room, (int) occupant.getRole() == Swift::MUCOccupant::Moderator, pbnetwork::STATUS_ONLINE); + } + + void handleJoinComplete(const std::string& nick) { + m_nick = nick; + } + + void handleJoinFailed(boost::shared_ptr error) { + + } + + void part() { + muc->part(); + } + + private: + Swift::MUC::ref muc; + std::string m_user; + std::string m_room; + std::string m_nick; +}; class SwiftenPlugin : public NetworkPlugin { public: @@ -106,6 +184,7 @@ class SwiftenPlugin : public NetworkPlugin { client->onDisconnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftDisconnected, this, user, _1)); client->onMessageReceived.disconnect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1)); m_users.erase(user); + m_mucs.erase(user); } #ifndef WIN32 @@ -136,6 +215,11 @@ class SwiftenPlugin : public NetworkPlugin { } void handleSwiftPresenceChanged(const std::string &user, Swift::Presence::ref presence) { + boost::shared_ptr client = m_users[user]; + if (client->getMUCRegistry()->isMUC(presence->getFrom().toBare())) { + return; + } + LOG4CXX_INFO(logger, user << ": " << presence->getFrom().toBare().toString() << " presence changed"); std::string message = presence->getStatus(); @@ -160,7 +244,22 @@ class SwiftenPlugin : public NetworkPlugin { std::string body = message->getBody(); boost::shared_ptr client = m_users[user]; if (client) { - handleMessage(user, message->getFrom().toBare().toString(), body, "", ""); + if (message->getType() == Swift::Message::Groupchat) { + boost::shared_ptr delay = message->getPayload(); + std::string timestamp = ""; + if (delay) { + timestamp = boost::posix_time::to_iso_string(delay->getStamp()); + } + handleMessage(user, message->getFrom().toBare().toString(), body, message->getFrom().getResource(), "", timestamp); + } + else { + if (client->getMUCRegistry()->isMUC(message->getFrom().toBare())) { + handleMessage(user, message->getFrom().toBare().toString(), body, message->getFrom().getResource(), "", "", false, true); + } + else { + handleMessage(user, message->getFrom().toBare().toString(), body, "", ""); + } + } } } @@ -199,6 +298,8 @@ class SwiftenPlugin : public NetworkPlugin { client->getRoster()->onInitialRosterPopulated.disconnect(boost::bind(&SwiftenPlugin::handleSwiftRosterReceived, this, user)); client->getPresenceOracle()->onPresenceChange.disconnect(boost::bind(&SwiftenPlugin::handleSwiftPresenceChanged, this, user, _1)); client->disconnect(); + m_mucs.erase(user); + m_users.erase(user); } } @@ -210,6 +311,11 @@ class SwiftenPlugin : public NetworkPlugin { message->setTo(Swift::JID(legacyName)); message->setFrom(client->getJID()); message->setBody(msg); + if (client->getMUCRegistry()->isMUC(legacyName)) { + message->setType(Swift::Message::Groupchat); + boost::shared_ptr muc = m_mucs[user][legacyName]; + handleMessage(user, legacyName, msg, muc->getNickname(), xhtml); + } client->sendMessage(message); } @@ -226,17 +332,81 @@ class SwiftenPlugin : public NetworkPlugin { } void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector &groups) { - LOG4CXX_INFO(logger, user << ": Added/Updated buddy " << buddyName << "."); -// handleBuddyChanged(user, buddyName, alias, groups, pbnetwork::STATUS_ONLINE); + boost::shared_ptr client = m_users[user]; + if (client) { + LOG4CXX_INFO(logger, user << ": Added/Updated buddy " << buddyName << "."); + if (!client->getRoster()->containsJID(buddyName)) { + Swift::RosterItemPayload item; + item.setName(alias); + item.setJID(buddyName); + item.setGroups(groups); + boost::shared_ptr roster(new Swift::RosterPayload()); + roster->addItem(item); + Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(roster, client->getIQRouter()); +// request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster)); + request->send(); + client->getSubscriptionManager()->requestSubscription(buddyName); + } + else { + Swift::JID contact(buddyName); + Swift::RosterItemPayload item(contact, alias, client->getRoster()->getSubscriptionStateForJID(contact)); + item.setGroups(groups); + boost::shared_ptr roster(new Swift::RosterPayload()); + roster->addItem(item); + Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(roster, client->getIQRouter()); +// request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster)); + request->send(); + } + + } } void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector &groups) { + boost::shared_ptr client = m_users[user]; + if (client) { + Swift::RosterItemPayload item(buddyName, "", Swift::RosterItemPayload::Remove); + boost::shared_ptr roster(new Swift::RosterPayload()); + roster->addItem(item); + Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(roster, client->getIQRouter()); +// request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster)); + request->send(); + } + } + void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) { + boost::shared_ptr client = m_users[user]; + if (client) { + if (client->getMUCRegistry()->isMUC(room)) { + return; + } + + boost::shared_ptr muc = boost::shared_ptr( new MUCController(user, client, room, nickname, password)); + m_mucs[user][room] = muc; + } + } + + void handleLeaveRoomRequest(const std::string &user, const std::string &room) { + boost::shared_ptr client = m_users[user]; + if (client) { + if (!client->getMUCRegistry()->isMUC(room)) { + return; + } + + boost::shared_ptr muc = m_mucs[user][room]; + if (!muc) { + m_mucs[user].erase(room); + return; + } + + muc->part(); + m_mucs[user].erase(room); + } } private: Config *config; std::map > m_users; + std::map > > m_mucs; }; #ifndef WIN32 diff --git a/include/transport/adhoccommand.h b/include/transport/adhoccommand.h index 24dbe8e6..df38d913 100644 --- a/include/transport/adhoccommand.h +++ b/include/transport/adhoccommand.h @@ -23,7 +23,10 @@ #include #include #include -#include "Swiften/Swiften.h" +#include + +#include "Swiften/Elements/FormField.h" +#include "Swiften/Elements/Command.h" namespace Transport { diff --git a/include/transport/adhoccommandfactory.h b/include/transport/adhoccommandfactory.h index 93c9d4a5..859421c5 100644 --- a/include/transport/adhoccommandfactory.h +++ b/include/transport/adhoccommandfactory.h @@ -24,7 +24,6 @@ #include #include #include "transport/adhoccommand.h" -#include "Swiften/Swiften.h" namespace Transport { diff --git a/include/transport/adhocmanager.h b/include/transport/adhocmanager.h index 8b418640..b8f77f87 100644 --- a/include/transport/adhocmanager.h +++ b/include/transport/adhocmanager.h @@ -23,7 +23,10 @@ #include #include #include -#include "Swiften/Swiften.h" + +#include "Swiften/Queries/Responder.h" +#include "Swiften/Elements/Command.h" +#include "Swiften/Network/Timer.h" namespace Transport { diff --git a/include/transport/admininterface.h b/include/transport/admininterface.h index 48f85dc1..3ab03941 100644 --- a/include/transport/admininterface.h +++ b/include/transport/admininterface.h @@ -22,7 +22,8 @@ #include #include -#include "Swiften/Swiften.h" + +#include "Swiften/Elements/Message.h" namespace Transport { diff --git a/include/transport/buddy.h b/include/transport/buddy.h index e11ed425..06792dc8 100644 --- a/include/transport/buddy.h +++ b/include/transport/buddy.h @@ -23,8 +23,8 @@ #include #include #include "transport/transport.h" +#include "Swiften/Elements/VCard.h" -#include "Swiften/Swiften.h" namespace Transport { diff --git a/include/transport/conversation.h b/include/transport/conversation.h index 121794d6..cda549cb 100644 --- a/include/transport/conversation.h +++ b/include/transport/conversation.h @@ -24,7 +24,6 @@ #include #include "transport/transport.h" -#include "Swiften/Swiften.h" #include "Swiften/Elements/Message.h" namespace Transport { @@ -34,15 +33,22 @@ class ConversationManager; /// Represents one XMPP-Legacy network conversation. class Conversation { public: + typedef enum { + PARTICIPANT_FLAG_NONE = 0, + PARTICIPANT_FLAG_MODERATOR = 1, + PARTICIPANT_FLAG_CONFLICT = 2, + PARTICIPANT_FLAG_BANNED = 4, + PARTICIPANT_FLAG_NOT_AUTHORIZED = 8, + PARTICIPANT_FLAG_ME = 16, + PARTICIPANT_FLAG_KICKED = 32 + } ParticipantFlag; + typedef struct _Participant { - int flag; + ParticipantFlag flag; int status; std::string statusMessage; } Participant; - /// Type of participants in MUC rooms. - enum ParticipantFlag {None, Moderator}; - /// Creates new conversation. /// \param conversationManager ConversationManager associated with this Conversation. @@ -71,7 +77,7 @@ class Conversation { /// \param status Current status of this participant. /// \param statusMessage Current status message of this participant. /// \param newname If participant was renamed, this variable contains his new name. - void handleParticipantChanged(const std::string &nickname, int flag, int status = Swift::StatusShow::None, const std::string &statusMessage = "", const std::string &newname = ""); + void handleParticipantChanged(const std::string &nickname, ParticipantFlag flag, int status = Swift::StatusShow::None, const std::string &statusMessage = "", const std::string &newname = ""); /// Sets XMPP user nickname in MUC rooms. diff --git a/include/transport/conversationmanager.h b/include/transport/conversationmanager.h index 0ef2842f..7aa606bf 100644 --- a/include/transport/conversationmanager.h +++ b/include/transport/conversationmanager.h @@ -23,7 +23,8 @@ #include #include #include -#include "Swiften/Swiften.h" + +#include "Swiften/Elements/Message.h" namespace Transport { diff --git a/include/transport/discoitemsresponder.h b/include/transport/discoitemsresponder.h index ddc1a2af..ff12cdcf 100644 --- a/include/transport/discoitemsresponder.h +++ b/include/transport/discoitemsresponder.h @@ -21,9 +21,9 @@ #pragma once #include -#include "Swiften/Swiften.h" #include "Swiften/Queries/GetResponder.h" #include "Swiften/Elements/DiscoItems.h" +#include "Swiften/Elements/CapsInfo.h" namespace Transport { diff --git a/include/transport/factory.h b/include/transport/factory.h index 0c4595d7..7df6e252 100644 --- a/include/transport/factory.h +++ b/include/transport/factory.h @@ -24,7 +24,6 @@ #include #include "transport/transport.h" -#include "Swiften/Swiften.h" #include "Swiften/Elements/Message.h" #include "transport/conversation.h" #include "transport/buddy.h" diff --git a/include/transport/gatewayresponder.h b/include/transport/gatewayresponder.h index 8cefedbe..59b765ea 100644 --- a/include/transport/gatewayresponder.h +++ b/include/transport/gatewayresponder.h @@ -21,7 +21,6 @@ #pragma once #include -#include "Swiften/Swiften.h" #include "Swiften/Queries/Responder.h" #include "Swiften/Elements/GatewayPayload.h" diff --git a/include/transport/memoryreadbytestream.h b/include/transport/memoryreadbytestream.h index 0f423a55..cb36389f 100644 --- a/include/transport/memoryreadbytestream.h +++ b/include/transport/memoryreadbytestream.h @@ -22,7 +22,8 @@ #include #include -#include "Swiften/Swiften.h" + +#include "Swiften/FileTransfer/ReadBytestream.h" namespace Transport { diff --git a/include/transport/mysqlbackend.h b/include/transport/mysqlbackend.h index eeb0a65f..60733240 100644 --- a/include/transport/mysqlbackend.h +++ b/include/transport/mysqlbackend.h @@ -24,7 +24,6 @@ #include #include -#include "Swiften/Swiften.h" #include "transport/storagebackend.h" #include "transport/config.h" #include "mysql.h" diff --git a/include/transport/networkplugin.h b/include/transport/networkplugin.h index c8e238c6..279a3c5d 100644 --- a/include/transport/networkplugin.h +++ b/include/transport/networkplugin.h @@ -39,16 +39,18 @@ class NetworkPlugin { class PluginConfig { public: - PluginConfig() : m_needPassword(true), m_needRegistration(false) {} + PluginConfig() : m_needPassword(true), m_needRegistration(false), m_supportMUC(false) {} virtual ~PluginConfig() {} void setNeedRegistration(bool needRegistration = false) { m_needRegistration = needRegistration; } void setNeedPassword(bool needPassword = true) { m_needPassword = needPassword; } + void setSupportMUC(bool supportMUC = true) { m_supportMUC = supportMUC; } void setExtraFields(const std::vector &fields) { m_extraFields = fields; } private: bool m_needPassword; bool m_needRegistration; + bool m_supportMUC; std::vector m_extraFields; friend class NetworkPlugin; @@ -111,7 +113,7 @@ class NetworkPlugin { /// \param message Plain text message. /// \param nickname Nickname of buddy in room. Empty if it's normal chat message. /// \param xhtml XHTML message. - void handleMessage(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &nickname = "", const std::string &xhtml = "", const std::string ×tamp = "", bool headline = false); + void handleMessage(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &nickname = "", const std::string &xhtml = "", const std::string ×tamp = "", bool headline = false, bool pm = false); void handleMessageAck(const std::string &user, const std::string &legacyName, const std::string &id); diff --git a/include/transport/networkpluginserver.h b/include/transport/networkpluginserver.h index b5aa0b71..2aea0fc9 100644 --- a/include/transport/networkpluginserver.h +++ b/include/transport/networkpluginserver.h @@ -21,11 +21,13 @@ #pragma once #include -#include "Swiften/Swiften.h" #include "Swiften/Presence/PresenceOracle.h" #include "Swiften/Disco/EntityCapsManager.h" #include "Swiften/Network/BoostConnectionServer.h" #include "Swiften/Network/Connection.h" +#include "Swiften/Elements/ChatState.h" +#include "Swiften/Elements/RosterItemPayload.h" +#include "Swiften/Elements/VCard.h" #include "storagebackend.h" #include "transport/filetransfermanager.h" @@ -125,6 +127,8 @@ class NetworkPluginServer { void handleBuddyUpdated(Buddy *buddy, const Swift::RosterItemPayload &item); void handleBuddyRemoved(Buddy *buddy); void handleBuddyAdded(Buddy *buddy, const Swift::RosterItemPayload &item); + void handleUserBuddyAdded(User *user, Buddy *buddy); + void handleUserBuddyRemoved(User *user, Buddy *buddy); void handleBlockToggled(Buddy *buddy); diff --git a/include/transport/pqxxbackend.h b/include/transport/pqxxbackend.h index bf5abf25..5ec0c409 100644 --- a/include/transport/pqxxbackend.h +++ b/include/transport/pqxxbackend.h @@ -24,7 +24,6 @@ #include #include -#include "Swiften/Swiften.h" #include "transport/storagebackend.h" #include "transport/config.h" #include diff --git a/include/transport/protocol.proto b/include/transport/protocol.proto index 316b164e..796b656c 100644 --- a/include/transport/protocol.proto +++ b/include/transport/protocol.proto @@ -72,6 +72,7 @@ message ConversationMessage { optional string timestamp = 6; optional bool headline = 7; optional string id = 8; + optional bool pm = 9; } message Room { @@ -86,6 +87,16 @@ message RoomList { repeated string name = 2; } +enum ParticipantFlag { + PARTICIPANT_FLAG_NONE = 0; + PARTICIPANT_FLAG_MODERATOR = 1; + PARTICIPANT_FLAG_CONFLICT = 2; + PARTICIPANT_FLAG_BANNED = 4; + PARTICIPANT_FLAG_NOT_AUTHORIZED = 8; + PARTICIPANT_FLAG_ME = 16; + PARTICIPANT_FLAG_KICKED = 32; +} + message Participant { required string userName = 1; required string room = 2; diff --git a/include/transport/rostermanager.h b/include/transport/rostermanager.h index fd649b57..fbd652ff 100644 --- a/include/transport/rostermanager.h +++ b/include/transport/rostermanager.h @@ -25,8 +25,12 @@ #include #include #include -#include "Swiften/Swiften.h" // #include "rosterstorage.h" +#include "Swiften/Elements/RosterPayload.h" +#include "Swiften/Queries/GenericRequest.h" +#include "Swiften/Roster/SetRosterRequest.h" +#include "Swiften/Elements/Presence.h" +#include "Swiften/Network/Timer.h" namespace Transport { diff --git a/include/transport/rosterresponder.h b/include/transport/rosterresponder.h index f716ddcd..4aaa2138 100644 --- a/include/transport/rosterresponder.h +++ b/include/transport/rosterresponder.h @@ -21,10 +21,11 @@ #pragma once #include -#include "Swiften/Swiften.h" #include "Swiften/Queries/Responder.h" #include "Swiften/Elements/RosterPayload.h" +#include + namespace Transport { class UserManager; diff --git a/include/transport/rosterstorage.h b/include/transport/rosterstorage.h index 726425c4..21703442 100644 --- a/include/transport/rosterstorage.h +++ b/include/transport/rosterstorage.h @@ -22,7 +22,9 @@ #include #include -#include "Swiften/Swiften.h" +#include + +#include "Swiften/Network/Timer.h" namespace Transport { diff --git a/include/transport/settingsadhoccommand.h b/include/transport/settingsadhoccommand.h index 3a2450a1..02eff3d9 100644 --- a/include/transport/settingsadhoccommand.h +++ b/include/transport/settingsadhoccommand.h @@ -23,7 +23,6 @@ #include #include #include -#include "Swiften/Swiften.h" #include "transport/adhoccommand.h" #include "transport/adhoccommandfactory.h" diff --git a/include/transport/sqlite3backend.h b/include/transport/sqlite3backend.h index d654ffa6..3c6411ca 100644 --- a/include/transport/sqlite3backend.h +++ b/include/transport/sqlite3backend.h @@ -24,7 +24,6 @@ #include #include -#include "Swiften/Swiften.h" #include "transport/storagebackend.h" #include "transport/config.h" #include "sqlite3.h" diff --git a/include/transport/statsresponder.h b/include/transport/statsresponder.h index ecdd331f..8f7fd8b6 100644 --- a/include/transport/statsresponder.h +++ b/include/transport/statsresponder.h @@ -21,7 +21,6 @@ #pragma once #include -#include "Swiften/Swiften.h" #include "Swiften/Queries/SetResponder.h" #include "Swiften/Elements/StatsPayload.h" diff --git a/include/transport/threadpool.h b/include/transport/threadpool.h index 6f498afa..27cb1a08 100644 --- a/include/transport/threadpool.h +++ b/include/transport/threadpool.h @@ -7,7 +7,7 @@ #include #include #include "transport/logging.h" -#include "Swiften/Swiften.h" +#include "Swiften/EventLoop/EventLoop.h" /* diff --git a/include/transport/transport.h b/include/transport/transport.h index c69ca396..b27ddd37 100644 --- a/include/transport/transport.h +++ b/include/transport/transport.h @@ -21,7 +21,6 @@ #pragma once #include -#include "Swiften/Swiften.h" #include "Swiften/Server/Server.h" #include "Swiften/Disco/GetDiscoInfoRequest.h" #include "Swiften/Disco/EntityCapsManager.h" @@ -32,6 +31,8 @@ #include "Swiften/Server/UserRegistry.h" #include "Swiften/Base/SafeByteArray.h" #include "Swiften/Jingle/JingleSessionManager.h" +#include "Swiften/Component/ComponentError.h" +#include "Swiften/Component/Component.h" #include #include "transport/config.h" @@ -40,12 +41,6 @@ #include namespace Transport { - // typedef enum { CLIENT_FEATURE_ROSTERX = 2, - // CLIENT_FEATURE_XHTML_IM = 4, - // CLIENT_FEATURE_FILETRANSFER = 8, - // CLIENT_FEATURE_CHATSTATES = 16 - // } SpectrumImportantFeatures; - // class StorageBackend; class Factory; class UserRegistry; @@ -68,7 +63,9 @@ namespace Transport { /// - service.server /// - service.port /// - service.server_mode + /// \param factories Swift::NetworkFactories. /// \param factory Transport Abstract factory used to create basic transport structures. + /// \param userRegistery UserRegistry class instance. It's needed only when running transport in server-mode. Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories, Config *config, Factory *factory, Transport::UserRegistry *userRegistry = NULL); /// Component destructor. @@ -96,9 +93,13 @@ namespace Transport { /// \return True if the component is in server mode. bool inServerMode() { return m_server != NULL; } - /// Connects the Jabber server. - + /// Starts the Component. + + /// In server-mode, it starts listening on particular port for new client connections. + /// In gateway-mode, it connects the XMPP server. void start(); + + /// Stops the component. void stop(); /// Returns Jabber ID of this transport. @@ -139,14 +140,17 @@ namespace Transport { /// This signal is emitted when presence from XMPP user is received. /// It's emitted only for presences addressed to transport itself - /// (for example to="j2j.domain.tld"). - /// \param presence presence data + /// (for example to="j2j.domain.tld") and for presences comming to + /// MUC (for example to="#chat%irc.freenode.org@irc.domain.tld") + /// \param presence Presence. boost::signal onUserPresenceReceived; + /// Component class asks the XMPP clients automatically for their capabilities. + /// This signal is emitted when capabilities have been received or changed. + /// \param jid JID of the client for which we received capabilities + /// \param info disco#info with response. boost::signal info)> onUserDiscoInfoReceived; -// boost::signal info, Swift::ErrorPayload::ref error, const Swift::JID& jid)> onDiscoInfoResponse; - private: void handleConnected(); void handleConnectionError(const Swift::ComponentError &error); diff --git a/include/transport/user.h b/include/transport/user.h index f7752f07..580fda41 100644 --- a/include/transport/user.h +++ b/include/transport/user.h @@ -21,12 +21,13 @@ #pragma once #include -#include "Swiften/Swiften.h" #include "Swiften/Disco/EntityCapsManager.h" #include "Swiften/Disco/EntityCapsProvider.h" #include "storagebackend.h" #include #include "Swiften/Elements/SpectrumErrorPayload.h" +#include "Swiften/Network/Timer.h" +#include "Swiften/Network/Connection.h" namespace Transport { diff --git a/include/transport/usermanager.h b/include/transport/usermanager.h index 38a5c7bc..b0fd7605 100644 --- a/include/transport/usermanager.h +++ b/include/transport/usermanager.h @@ -22,8 +22,12 @@ #include #include -#include "Swiften/Swiften.h" #include "transport/userregistry.h" +#include "Swiften/Elements/Message.h" +#include "Swiften/Elements/Presence.h" +#include "Swiften/Disco/EntityCapsProvider.h" +#include "Swiften/Elements/DiscoInfo.h" +#include "Swiften/Network/Timer.h" namespace Transport { @@ -133,6 +137,7 @@ class UserManager : public Swift::EntityCapsProvider { void handleProbePresence(Swift::Presence::ref presence); void handleErrorPresence(Swift::Presence::ref presence); void handleSubscription(Swift::Presence::ref presence); + void handleMUCPresence(Swift::Presence::ref presence); void handleRemoveTimeout(const std::string jid, User *user, bool reconnect); void handleDiscoInfo(const Swift::JID& jid, boost::shared_ptr info); void addUser(User *user); diff --git a/include/transport/userregistration.h b/include/transport/userregistration.h index 2e9b6136..1c994423 100644 --- a/include/transport/userregistration.h +++ b/include/transport/userregistration.h @@ -20,9 +20,10 @@ #pragma once -#include "Swiften/Swiften.h" #include "Swiften/Queries/Responder.h" #include "Swiften/Elements/InBandRegistrationPayload.h" +#include "Swiften/Elements/RosterPayload.h" +#include namespace Transport { diff --git a/include/transport/userregistry.h b/include/transport/userregistry.h index 0b6cac14..58590a01 100644 --- a/include/transport/userregistry.h +++ b/include/transport/userregistry.h @@ -22,8 +22,10 @@ #include #include -#include "Swiften/Swiften.h" #include "Swiften/Server/UserRegistry.h" +#include "Swiften/Network/NetworkFactories.h" +#include "Swiften/Network/Timer.h" +#include "Swiften/Network/TimerFactory.h" #include "transport/config.h" namespace Transport { diff --git a/include/transport/usersreconnecter.h b/include/transport/usersreconnecter.h index 52497e64..0c813b0c 100644 --- a/include/transport/usersreconnecter.h +++ b/include/transport/usersreconnecter.h @@ -23,7 +23,8 @@ #include #include #include -#include "Swiften/Swiften.h" + +#include "Swiften/Network/Timer.h" namespace Transport { diff --git a/include/transport/vcardresponder.h b/include/transport/vcardresponder.h index 156a95e4..852500e2 100644 --- a/include/transport/vcardresponder.h +++ b/include/transport/vcardresponder.h @@ -21,9 +21,11 @@ #pragma once #include -#include "Swiften/Swiften.h" #include "Swiften/Queries/Responder.h" #include "Swiften/Elements/VCard.h" +#include "Swiften/Network/NetworkFactories.h" +#include "Swiften/Network/Timer.h" +#include namespace Transport { diff --git a/plugin/cpp/networkplugin.cpp b/plugin/cpp/networkplugin.cpp index 06393bf4..45e39e99 100644 --- a/plugin/cpp/networkplugin.cpp +++ b/plugin/cpp/networkplugin.cpp @@ -71,6 +71,9 @@ void NetworkPlugin::sendConfig(const PluginConfig &cfg) { data += std::string("extraField=") + (*it) + "\n"; } + data += "[features]\n"; + data += std::string("muc=") + (cfg.m_supportMUC ? "1" : "0") + "\n"; + pbnetwork::BackendConfig m; m.set_config(data); @@ -82,7 +85,7 @@ void NetworkPlugin::sendConfig(const PluginConfig &cfg) { send(message); } -void NetworkPlugin::handleMessage(const std::string &user, const std::string &legacyName, const std::string &msg, const std::string &nickname, const std::string &xhtml, const std::string ×tamp, bool headline) { +void NetworkPlugin::handleMessage(const std::string &user, const std::string &legacyName, const std::string &msg, const std::string &nickname, const std::string &xhtml, const std::string ×tamp, bool headline, bool pm) { pbnetwork::ConversationMessage m; m.set_username(user); m.set_buddyname(legacyName); @@ -91,6 +94,7 @@ void NetworkPlugin::handleMessage(const std::string &user, const std::string &le m.set_xhtml(xhtml); m.set_timestamp(timestamp); m.set_headline(headline); + m.set_pm(pm); std::string message; m.SerializeToString(&message); diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index a024138e..176c618d 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -17,6 +17,7 @@ #include "transport/adhocmanager.h" #include "transport/settingsadhoccommand.h" #include "Swiften/EventLoop/SimpleEventLoop.h" +#include "Swiften/Network/BoostNetworkFactories.h" #include #include #ifndef WIN32 diff --git a/spectrum/src/sample.cfg b/spectrum/src/sample.cfg index d795b60e..75735b97 100644 --- a/spectrum/src/sample.cfg +++ b/spectrum/src/sample.cfg @@ -13,15 +13,15 @@ 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=../..//backends/swiften/spectrum2_swiften_backend +#backend=../..//backends/swiften/spectrum2_swiften_backend #backend=../../backends/twitter/spectrum2_twitter_backend -#backend=/home/hanzz/code/libtransport/backends/libcommuni/spectrum2_libcommuni_backend +backend=/home/hanzz/code/libtransport/backends/libcommuni/spectrum2_libcommuni_backend protocol=prpl-jabber #protocol=prpl-msn #protocol=any #protocol=prpl-icq working_dir=./ -portfile=$jid.port +portfile=./$jid.port irc_server=irc.freenode.org [backend] diff --git a/spectrum/src/sample2.cfg b/spectrum/src/sample2.cfg index cc0a7aef..6cad8d9d 100644 --- a/spectrum/src/sample2.cfg +++ b/spectrum/src/sample2.cfg @@ -41,7 +41,7 @@ users_per_backend=10 backend=/usr/bin/spectrum2_libpurple_backend #backend=/usr/bin/spectrum2_libcommuni_backend # For skype: -#backend=/usr/bin/xvfb-run -n BACKEND_ID -s "-screen 0 10x10x8" -f /tmp/x-skype-gw /usr/bin/spectrum2_skype_backend +#backend=/usr/bin/xvfb-run -a -s "-screen 0 10x10x8" -f /tmp/x-skype-gw /usr/bin/spectrum2_skype_backend # Libpurple protocol-id for spectrum_libpurple_backend protocol=prpl-jabber diff --git a/spectrum_manager/src/main.cpp b/spectrum_manager/src/main.cpp index 9f09d2af..58581be2 100644 --- a/spectrum_manager/src/main.cpp +++ b/spectrum_manager/src/main.cpp @@ -138,6 +138,9 @@ int main(int argc, char **argv) else if (command[0] == "list") { std::vector list = show_list(&config); } + else if (command[0] == "restart") { + return restart_instances(&config); + } else if (command[0] == "server") { Server server(&config); if (server.start() == false) { diff --git a/src/blockresponder.cpp b/src/blockresponder.cpp index 708fec43..6a5ad41c 100644 --- a/src/blockresponder.cpp +++ b/src/blockresponder.cpp @@ -24,7 +24,6 @@ #include #include "Swiften/Queries/IQRouter.h" #include "transport/BlockPayload.h" -#include "Swiften/Swiften.h" #include "transport/usermanager.h" #include "transport/user.h" #include "transport/buddy.h" diff --git a/src/blockresponder.h b/src/blockresponder.h index 8f77bea8..ed415502 100644 --- a/src/blockresponder.h +++ b/src/blockresponder.h @@ -21,9 +21,9 @@ #pragma once #include -#include "Swiften/Swiften.h" #include "Swiften/Queries/SetResponder.h" #include "transport/BlockPayload.h" +#include namespace Transport { diff --git a/src/buddy.cpp b/src/buddy.cpp index eb5388f5..300053cf 100644 --- a/src/buddy.cpp +++ b/src/buddy.cpp @@ -26,6 +26,8 @@ #include "transport/usermanager.h" #include "transport/discoitemsresponder.h" +#include "Swiften/Elements/VCardUpdate.h" + namespace Transport { Buddy::Buddy(RosterManager *rosterManager, long id, BuddyFlag flags) : m_id(id), m_flags(flags), m_rosterManager(rosterManager), diff --git a/src/config.cpp b/src/config.cpp index a30a01e1..1a5902e4 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -314,6 +314,7 @@ void Config::updateBackendConfig(const std::string &backendConfig) { ("registration.needRegistration", value()->default_value(false), "") ("registration.extraField", value >()->multitoken(), "") ("features.receipts", value()->default_value(false), "") + ("features.muc", value()->default_value(false), "") ; std::stringstream ifs(backendConfig); diff --git a/src/conversation.cpp b/src/conversation.cpp index 1a8b8383..4073d8e6 100644 --- a/src/conversation.cpp +++ b/src/conversation.cpp @@ -26,6 +26,12 @@ #include "transport/buddy.h" #include "transport/rostermanager.h" +#include "Swiften/Elements/MUCItem.h" +#include "Swiften/Elements/MUCOccupant.h" +#include "Swiften/Elements/MUCUserPayload.h" +#include "Swiften/Elements/Delay.h" +#include "Swiften/Elements/MUCPayload.h" + namespace Transport { Conversation::Conversation(ConversationManager *conversationManager, const std::string &legacyName, bool isMUC) : m_conversationManager(conversationManager) { @@ -124,7 +130,11 @@ void Conversation::handleMessage(boost::shared_ptr &message, con message->setFrom(Swift::JID(n, m_conversationManager->getComponent()->getJID().toBare(), "user")); } else { - message->setFrom(Swift::JID(m_room, m_conversationManager->getComponent()->getJID().toBare(), n)); + std::string legacyName = m_room; + if (legacyName.find_last_of("@") != std::string::npos) { + legacyName.replace(legacyName.find_last_of("@"), 1, "%"); // OK + } + message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), n)); } } @@ -225,19 +235,35 @@ Swift::Presence::ref Conversation::generatePresence(const std::string &nick, int Swift::MUCUserPayload *p = new Swift::MUCUserPayload (); if (m_nickname == nickname) { - Swift::MUCUserPayload::StatusCode c; - c.code = 110; - p->addStatusCode(c); - m_sentInitialPresence = true; + if (flag & PARTICIPANT_FLAG_CONFLICT) { + delete p; + presence->setType(Swift::Presence::Error); + presence->addPayload(boost::shared_ptr(new Swift::MUCPayload())); + presence->addPayload(boost::shared_ptr(new Swift::ErrorPayload(Swift::ErrorPayload::Conflict))); + return presence; + } + else if (flag & PARTICIPANT_FLAG_NOT_AUTHORIZED) { + delete p; + presence->setType(Swift::Presence::Error); + presence->addPayload(boost::shared_ptr(new Swift::MUCPayload())); + presence->addPayload(boost::shared_ptr(new Swift::ErrorPayload(Swift::ErrorPayload::NotAuthorized, Swift::ErrorPayload::Auth))); + return presence; + } + else { + Swift::MUCUserPayload::StatusCode c; + c.code = 110; + p->addStatusCode(c); + m_sentInitialPresence = true; + } } - + Swift::MUCItem item; item.affiliation = Swift::MUCOccupant::Member; item.role = Swift::MUCOccupant::Participant; - if (flag & Moderator) { + if (flag & PARTICIPANT_FLAG_MODERATOR) { item.affiliation = Swift::MUCOccupant::Admin; item.role = Swift::MUCOccupant::Moderator; } @@ -249,13 +275,13 @@ Swift::Presence::ref Conversation::generatePresence(const std::string &nick, int p->addStatusCode(c); presence->setType(Swift::Presence::Unavailable); } - + p->addItem(item); presence->addPayload(boost::shared_ptr(p)); return presence; } -void Conversation::handleParticipantChanged(const std::string &nick, int flag, int status, const std::string &statusMessage, const std::string &newname) { +void Conversation::handleParticipantChanged(const std::string &nick, Conversation::ParticipantFlag flag, int status, const std::string &statusMessage, const std::string &newname) { Swift::Presence::ref presence = generatePresence(nick, flag, status, statusMessage, newname); if (presence->getType() == Swift::Presence::Unavailable) { diff --git a/src/discoinforesponder.cpp b/src/discoinforesponder.cpp index 15ce1544..d3ea87da 100644 --- a/src/discoinforesponder.cpp +++ b/src/discoinforesponder.cpp @@ -26,9 +26,9 @@ #include "Swiften/Disco/DiscoInfoResponder.h" #include "Swiften/Queries/IQRouter.h" #include "Swiften/Elements/DiscoInfo.h" -#include "Swiften/Swiften.h" #include "transport/config.h" #include "transport/logging.h" +#include "Swiften/Disco/CapsInfoGenerator.h" using namespace Swift; using namespace boost; @@ -39,28 +39,31 @@ namespace Transport { DiscoInfoResponder::DiscoInfoResponder(Swift::IQRouter *router, Config *config) : Swift::GetResponder(router) { m_config = config; - m_config->onBackendConfigUpdated.connect(boost::bind(&DiscoInfoResponder::updateBuddyFeatures, this)); + m_config->onBackendConfigUpdated.connect(boost::bind(&DiscoInfoResponder::updateFeatures, this)); m_buddyInfo = NULL; m_transportInfo.addIdentity(DiscoInfo::Identity(CONFIG_STRING(m_config, "identity.name"), CONFIG_STRING(m_config, "identity.category"), CONFIG_STRING(m_config, "identity.type"))); - std::list features; - features.push_back("jabber:iq:register"); - features.push_back("jabber:iq:gateway"); - features.push_back("jabber:iq:private"); - features.push_back("http://jabber.org/protocol/disco#info"); - features.push_back("http://jabber.org/protocol/commands"); - setTransportFeatures(features); - - updateBuddyFeatures(); + updateFeatures(); } DiscoInfoResponder::~DiscoInfoResponder() { delete m_buddyInfo; } -void DiscoInfoResponder::updateBuddyFeatures() { +void DiscoInfoResponder::updateFeatures() { + std::list features2; + features2.push_back("jabber:iq:register"); + features2.push_back("jabber:iq:gateway"); + features2.push_back("jabber:iq:private"); + features2.push_back("http://jabber.org/protocol/disco#info"); + features2.push_back("http://jabber.org/protocol/commands"); + if (CONFIG_BOOL_DEFAULTED(m_config, "features.muc", false)) { + features2.push_back("http://jabber.org/protocol/muc"); + } + setTransportFeatures(features2); + std::list features; features.push_back("http://jabber.org/protocol/disco#items"); features.push_back("http://jabber.org/protocol/disco#info"); diff --git a/src/discoinforesponder.h b/src/discoinforesponder.h index 0ce5883b..08b0656e 100644 --- a/src/discoinforesponder.h +++ b/src/discoinforesponder.h @@ -21,7 +21,8 @@ #pragma once #include -#include "Swiften/Swiften.h" +#include +#include #include "Swiften/Queries/GetResponder.h" #include "Swiften/Elements/DiscoInfo.h" #include "Swiften/Elements/CapsInfo.h" @@ -51,7 +52,7 @@ class DiscoInfoResponder : public Swift::GetResponder { private: virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload); - void updateBuddyFeatures(); + void updateFeatures(); Swift::DiscoInfo m_transportInfo; Swift::DiscoInfo *m_buddyInfo; diff --git a/src/discoitemsresponder.cpp b/src/discoitemsresponder.cpp index 72ac8390..90c153ea 100644 --- a/src/discoitemsresponder.cpp +++ b/src/discoitemsresponder.cpp @@ -23,7 +23,6 @@ #include #include #include "Swiften/Queries/IQRouter.h" -#include "Swiften/Swiften.h" #include "transport/transport.h" #include "transport/logging.h" #include "discoinforesponder.h" diff --git a/src/filetransfermanager.cpp b/src/filetransfermanager.cpp index 73c08a86..dd893fb1 100644 --- a/src/filetransfermanager.cpp +++ b/src/filetransfermanager.cpp @@ -24,6 +24,7 @@ #include "transport/user.h" #include "transport/buddy.h" #include "transport/logging.h" +#include "Swiften/Network/ConnectionServerFactory.h" namespace Transport { diff --git a/src/gatewayresponder.cpp b/src/gatewayresponder.cpp index 5a268312..fa29711e 100644 --- a/src/gatewayresponder.cpp +++ b/src/gatewayresponder.cpp @@ -24,7 +24,6 @@ #include #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" @@ -53,7 +52,14 @@ bool GatewayResponder::handleGetRequest(const Swift::JID& from, const Swift::JID bool GatewayResponder::handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload) { std::string prompt = payload->getPrompt(); + std::string escaped = Swift::JID::getEscapedNode(prompt); + if (!CONFIG_BOOL_DEFAULTED(m_userManager->getComponent()->getConfig(), "service.jid_escaping", true)) { + escaped = prompt; + if (escaped.find_last_of("@") != std::string::npos) { + escaped.replace(escaped.find_last_of("@"), 1, "%"); + } + } // This code is here to workaround Gajim (and probably other clients bug too) bug // https://trac.gajim.org/ticket/7277 if (prompt.find("\\40") != std::string::npos) { diff --git a/src/logging.cpp b/src/logging.cpp index b5c080b2..947eb2bb 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -136,30 +136,38 @@ static void initLogging(Config *config, std::string key, bool only_create_dir = p.setProperty("id", id); #endif - std::string dir; + std::vector dirs; BOOST_FOREACH(const log4cxx::LogString &prop, p.propertyNames()) { -// if (boost::ends_with(prop, ".File")) { + if (boost::ends_with(prop, ".File")) { + std::string dir; log4cxx::helpers::Transcoder::encode(p.get(prop), dir); boost::replace_all(dir, "${jid}", jid); boost::replace_all(dir, "${pid}", pid); boost::replace_all(dir, "${id}", id); - break; -// } + dirs.push_back(dir); + } } mode_t old_cmask; - if (!dir.empty()) { - // create directories + // create directories #ifndef WIN32 - old_cmask = umask(0007); + old_cmask = umask(0007); #endif - try { - Transport::Util::createDirectories(config, boost::filesystem::path(dir).parent_path()); - } - catch (const boost::filesystem::filesystem_error &e) { - std::cerr << "Can't create logging directory directory " << boost::filesystem::path(dir).parent_path().string() << ": " << e.what() << ".\n"; + + BOOST_FOREACH(std::string &dir, dirs) { + if (!dir.empty()) { + try { + Transport::Util::createDirectories(config, boost::filesystem::path(dir).parent_path()); + } + catch (const boost::filesystem::filesystem_error &e) { + std::cerr << "Can't create logging directory directory " << boost::filesystem::path(dir).parent_path().string() << ": " << e.what() << ".\n"; + } } } +#ifndef WIN32 + umask(old_cmask); +#endif + if (only_create_dir) { return; } @@ -168,24 +176,20 @@ static void initLogging(Config *config, std::string key, bool only_create_dir = // Change owner of main log file #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"; + BOOST_FOREACH(std::string &dir, dirs) { + 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"; + } + 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"; + } + chown(dir.c_str(), pw->pw_uid, gr->gr_gid); } - 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"; - } - chown(dir.c_str(), pw->pw_uid, gr->gr_gid); } #endif - -#ifndef WIN32 - if (!dir.empty()) { - umask(old_cmask); - } -#endif } } diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index 2493d630..85747b23 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -34,18 +34,24 @@ #include "transport/logging.h" #include "transport/admininterface.h" #include "blockresponder.h" -#include "Swiften/Swiften.h" #include "Swiften/Server/ServerStanzaChannel.h" #include "Swiften/Elements/StreamError.h" #include "Swiften/Network/BoostConnectionServer.h" +#include "Swiften/Network/ConnectionServerFactory.h" #include "Swiften/Elements/AttentionPayload.h" #include "Swiften/Elements/XHTMLIMPayload.h" +#include "Swiften/Elements/Delay.h" +#include "Swiften/Elements/DeliveryReceipt.h" +#include "Swiften/Elements/DeliveryReceiptRequest.h" #include "Swiften/Elements/InvisiblePayload.h" #include "Swiften/Elements/SpectrumErrorPayload.h" #include "transport/protocol.pb.h" #include "transport/util.h" #include "transport/discoitemsresponder.h" +#include "boost/date_time/posix_time/posix_time.hpp" +#include "boost/signal.hpp" + #include "utf8.h" #include @@ -619,7 +625,7 @@ void NetworkPluginServer::handleParticipantChangedPayload(const std::string &dat return; } - conv->handleParticipantChanged(payload.nickname(), payload.flag(), payload.status(), payload.statusmessage(), payload.newname()); + conv->handleParticipantChanged(payload.nickname(), (Conversation::ParticipantFlag) payload.flag(), payload.status(), payload.statusmessage(), payload.newname()); } void NetworkPluginServer::handleRoomChangedPayload(const std::string &data) { @@ -680,7 +686,6 @@ void NetworkPluginServer::handleConvMessagePayload(const std::string &data, bool msg->addPayload(delay); } - NetworkConversation *conv = (NetworkConversation *) user->getConversationManager()->getConversation(payload.buddyname()); // We can't create Conversation for payload with nickname, because this means the message is from room, @@ -689,6 +694,19 @@ void NetworkPluginServer::handleConvMessagePayload(const std::string &data, bool return; } + if (conv && payload.pm()) { + conv = (NetworkConversation *) user->getConversationManager()->getConversation(payload.buddyname() + "/" + payload.nickname()); + if (!conv) { + conv = new NetworkConversation(user->getConversationManager(), payload.nickname()); + std::string name = payload.buddyname(); + conv->setRoom(name); + conv->setNickname(payload.buddyname() + "/" + payload.nickname()); + + user->getConversationManager()->addConversation(conv); + conv->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, this, _1, _2)); + } + } + // Create new Conversation if it does not exist if (!conv) { conv = new NetworkConversation(user->getConversationManager(), payload.buddyname()); @@ -1247,6 +1265,9 @@ void NetworkPluginServer::handleUserCreated(User *user) { user->onPresenceChanged.connect(boost::bind(&NetworkPluginServer::handleUserPresenceChanged, this, user, _1)); user->onRoomJoined.connect(boost::bind(&NetworkPluginServer::handleRoomJoined, this, user, _1, _2, _3, _4)); user->onRoomLeft.connect(boost::bind(&NetworkPluginServer::handleRoomLeft, this, user, _1)); + + user->getRosterManager()->onBuddyAdded.connect(boost::bind(&NetworkPluginServer::handleUserBuddyAdded, this, user, _1)); + user->getRosterManager()->onBuddyRemoved.connect(boost::bind(&NetworkPluginServer::handleUserBuddyRemoved, this, user, _1)); } void NetworkPluginServer::handleUserReadyToConnect(User *user) { @@ -1352,6 +1373,9 @@ void NetworkPluginServer::handleUserDestroyed(User *user) { user->onRoomJoined.disconnect(boost::bind(&NetworkPluginServer::handleRoomJoined, this, user, _1, _2, _3, _4)); user->onRoomLeft.disconnect(boost::bind(&NetworkPluginServer::handleRoomLeft, this, user, _1)); + user->getRosterManager()->onBuddyAdded.disconnect(boost::bind(&NetworkPluginServer::handleUserBuddyAdded, this, user, _1)); + user->getRosterManager()->onBuddyRemoved.disconnect(boost::bind(&NetworkPluginServer::handleUserBuddyRemoved, this, user, _1)); + pbnetwork::Logout logout; logout.set_user(user->getJID().toBare()); logout.set_legacyname(userInfo.uin); @@ -1532,6 +1556,32 @@ void NetworkPluginServer::handleBuddyAdded(Buddy *buddy, const Swift::RosterItem handleBuddyUpdated(buddy, item); } +void NetworkPluginServer::handleUserBuddyAdded(User *user, Buddy *b) { + pbnetwork::Buddy buddy; + buddy.set_username(user->getJID().toBare()); + buddy.set_buddyname(b->getName()); + buddy.set_alias(b->getAlias()); + BOOST_FOREACH(const std::string &g, b->getGroups()) { + buddy.add_group(g); + } + buddy.set_status(pbnetwork::STATUS_NONE); + + std::string message; + buddy.SerializeToString(&message); + + WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_BUDDY_CHANGED); + + Backend *c = (Backend *) user->getData(); + if (!c) { + return; + } + send(c->connection, message); +} + +void NetworkPluginServer::handleUserBuddyRemoved(User *user, Buddy *b) { + handleBuddyRemoved(b); +} + void NetworkPluginServer::handleBlockToggled(Buddy *b) { User *user = b->getRosterManager()->getUser(); diff --git a/src/presenceoracle.cpp b/src/presenceoracle.cpp index a846a061..f84b0a55 100644 --- a/src/presenceoracle.cpp +++ b/src/presenceoracle.cpp @@ -19,7 +19,7 @@ */ #include "transport/presenceoracle.h" -#include "Swiften/Swiften.h" +#include "Swiften/Elements/MUCPayload.h" #include @@ -52,9 +52,8 @@ void PresenceOracle::clearPresences(const Swift::JID& bareJID) { void PresenceOracle::handleIncomingPresence(Presence::ref presence) { // ignore presences for some contact, we're checking only presences for the transport itself here. - bool isMUC = presence->getPayload() != NULL || *presence->getTo().getNode().c_str() == '#'; // filter out login/logout presence spam - if (!presence->getTo().getNode().empty() && isMUC == false) + if (!presence->getTo().getNode().empty()) return; JID bareJID(presence->getFrom().toBare()); @@ -62,29 +61,27 @@ void PresenceOracle::handleIncomingPresence(Presence::ref presence) { } else { Presence::ref passedPresence = presence; - if (!isMUC) { - if (presence->getType() == Presence::Unsubscribe || presence->getType() == Presence::Unsubscribed) { - /* 3921bis says that we don't follow up with an unavailable, so simulate this ourselves */ - passedPresence = Presence::ref(new Presence()); - passedPresence->setType(Presence::Unavailable); - passedPresence->setFrom(bareJID); - passedPresence->setStatus(presence->getStatus()); - } - std::map > jidMap = entries_[bareJID]; - if (passedPresence->getFrom().isBare() && presence->getType() == Presence::Unavailable) { - /* Have a bare-JID only presence of offline */ - jidMap.clear(); - } else if (passedPresence->getType() == Presence::Available) { - /* Don't have a bare-JID only offline presence once there are available presences */ - jidMap.erase(bareJID); - } - if (passedPresence->getType() == Presence::Unavailable && jidMap.size() > 1) { - jidMap.erase(passedPresence->getFrom()); - } else { - jidMap[passedPresence->getFrom()] = passedPresence; - } - entries_[bareJID] = jidMap; + if (presence->getType() == Presence::Unsubscribe || presence->getType() == Presence::Unsubscribed) { + /* 3921bis says that we don't follow up with an unavailable, so simulate this ourselves */ + passedPresence = Presence::ref(new Presence()); + passedPresence->setType(Presence::Unavailable); + passedPresence->setFrom(bareJID); + passedPresence->setStatus(presence->getStatus()); } + std::map > jidMap = entries_[bareJID]; + if (passedPresence->getFrom().isBare() && presence->getType() == Presence::Unavailable) { + /* Have a bare-JID only presence of offline */ + jidMap.clear(); + } else if (passedPresence->getType() == Presence::Available) { + /* Don't have a bare-JID only offline presence once there are available presences */ + jidMap.erase(bareJID); + } + if (passedPresence->getType() == Presence::Unavailable && jidMap.size() > 1) { + jidMap.erase(passedPresence->getFrom()); + } else { + jidMap[passedPresence->getFrom()] = passedPresence; + } + entries_[bareJID] = jidMap; onPresenceChange(passedPresence); } } diff --git a/src/rostermanager.cpp b/src/rostermanager.cpp index 0967fe56..f9c47e77 100644 --- a/src/rostermanager.cpp +++ b/src/rostermanager.cpp @@ -30,7 +30,10 @@ #include "Swiften/Elements/RosterPayload.h" #include "Swiften/Elements/RosterItemPayload.h" #include "Swiften/Elements/RosterItemExchangePayload.h" +#include "Swiften/Elements/Nickname.h" +#include "Swiften/Queries/IQRouter.h" #include +#include #include #include @@ -151,12 +154,7 @@ void RosterManager::sendBuddyRosterPush(Buddy *buddy) { Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload()); Swift::RosterItemPayload item; item.setJID(buddy->getJID().toBare()); - if (buddy->getAlias().empty()) { - item.setName(buddy->getJID().toBare().toString()); - } - else { - item.setName(buddy->getAlias()); - } + item.setName(buddy->getAlias()); item.setGroups(buddy->getGroups()); item.setSubscription(Swift::RosterItemPayload::Both); @@ -280,6 +278,15 @@ void RosterManager::handleRemoteRosterResponse(boost::shared_ptrgetJID().toString() << ": This server supports remote roster protoXEP"); m_supportRemoteRoster = true; + + //If we receive empty RosterPayload on login (not register) initiate full RosterPush + if(!m_buddies.empty() && payload->getItems().empty()){ + LOG4CXX_INFO(logger, "Received empty Roster upon login. Pushing full Roster."); + for(std::map, boost::pool_allocator< std::pair > >::const_iterator c_it = m_buddies.begin(); + c_it != m_buddies.end(); c_it++) { + sendBuddyRosterPush(c_it->second); + } + } return; BOOST_FOREACH(const Swift::RosterItemPayload &item, payload->getItems()) { @@ -490,6 +497,7 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) { buddy = m_component->getFactory()->createBuddy(this, buddyInfo); setBuddy(buddy); onBuddyAdded(buddy); + LOG4CXX_INFO(logger, m_user->getJID().toString() << ": Subscription received for new buddy " << buddyInfo.legacyName << " => adding to legacy network"); response->setType(Swift::Presence::Subscribed); break; case Swift::Presence::Unsubscribe: diff --git a/src/rosterresponder.cpp b/src/rosterresponder.cpp index 6bc496c1..109f30c5 100644 --- a/src/rosterresponder.cpp +++ b/src/rosterresponder.cpp @@ -23,7 +23,6 @@ #include #include #include "Swiften/Queries/IQRouter.h" -#include "Swiften/Swiften.h" #include "transport/user.h" #include "transport/usermanager.h" #include "transport/rostermanager.h" diff --git a/src/rosterstorage.cpp b/src/rosterstorage.cpp index 34a40b3a..eacc205d 100644 --- a/src/rosterstorage.cpp +++ b/src/rosterstorage.cpp @@ -24,6 +24,8 @@ #include "transport/storagebackend.h" #include "transport/logging.h" +#include "Swiften/Network/NetworkFactories.h" + DEFINE_LOGGER(logger, "RosterStorage"); namespace Transport { diff --git a/src/statsresponder.cpp b/src/statsresponder.cpp index 4ba24e71..faed68b0 100644 --- a/src/statsresponder.cpp +++ b/src/statsresponder.cpp @@ -24,7 +24,6 @@ #include #include "Swiften/Queries/IQRouter.h" #include "transport/BlockPayload.h" -#include "Swiften/Swiften.h" #include "transport/usermanager.h" #include "transport/user.h" #include "transport/buddy.h" diff --git a/src/storagebackend.cpp b/src/storagebackend.cpp index ce27dfae..7714df36 100644 --- a/src/storagebackend.cpp +++ b/src/storagebackend.cpp @@ -4,8 +4,8 @@ #include "transport/sqlite3backend.h" #include "transport/mysqlbackend.h" #include "transport/pqxxbackend.h" +#include "Swiften/StringCodecs/Base64.h" -#include "Swiften/Swiften.h" namespace Transport { diff --git a/src/storageresponder.cpp b/src/storageresponder.cpp index 1b3d2aa9..607dca20 100644 --- a/src/storageresponder.cpp +++ b/src/storageresponder.cpp @@ -24,7 +24,9 @@ #include #include "Swiften/Queries/IQRouter.h" #include "Swiften/Elements/RawXMLPayload.h" -#include "Swiften/Swiften.h" +#include "Swiften/Elements/Storage.h" +#include "Swiften/Elements/Storage.h" +#include "Swiften/Serializer/PayloadSerializers/StorageSerializer.h" #include "transport/usermanager.h" #include "transport/user.h" #include "transport/logging.h" diff --git a/src/storageresponder.h b/src/storageresponder.h index 0bf033cb..c92691ba 100644 --- a/src/storageresponder.h +++ b/src/storageresponder.h @@ -21,9 +21,9 @@ #pragma once #include -#include "Swiften/Swiften.h" #include "Swiften/Queries/Responder.h" #include "Swiften/Elements/RosterPayload.h" +#include "Swiften/Elements/PrivateStorage.h" namespace Transport { diff --git a/src/tests/conversationmanager.cpp b/src/tests/conversationmanager.cpp index 5c9851ec..b8f2eb4e 100644 --- a/src/tests/conversationmanager.cpp +++ b/src/tests/conversationmanager.cpp @@ -35,6 +35,8 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe CPPUNIT_TEST(handleParticipantChangedTwoResources); CPPUNIT_TEST(handlePMFromXMPP); CPPUNIT_TEST(handleGroupchatRemoved); + CPPUNIT_TEST(handleNicknameConflict); + CPPUNIT_TEST(handleNotAuthorized); CPPUNIT_TEST_SUITE_END(); public: @@ -115,7 +117,7 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe CPPUNIT_ASSERT_EQUAL(0, (int) received.size()); // this user presence - status code 110 - conv->handleParticipantChanged("nickname", 1, Swift::StatusShow::Away, "my status message"); + conv->handleParticipantChanged("nickname", Conversation::PARTICIPANT_FLAG_MODERATOR, Swift::StatusShow::Away, "my status message"); loop->processEvents(); CPPUNIT_ASSERT_EQUAL(2, (int) received.size()); @@ -343,17 +345,17 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe injectPresence(response); loop->processEvents(); - CPPUNIT_ASSERT_EQUAL(4, (int) received.size()); + CPPUNIT_ASSERT_EQUAL(3, (int) received.size()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[1]))); + CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast(getStanza(received[1]))->getBody()); + CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[1]))->getTo().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received[1]))->getFrom().toString()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[2]))); - CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast(getStanza(received[2]))->getBody()); + CPPUNIT_ASSERT_EQUAL(std::string("hi there2!"), dynamic_cast(getStanza(received[2]))->getBody()); CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[2]))->getTo().toString()); CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received[2]))->getFrom().toString()); - CPPUNIT_ASSERT(dynamic_cast(getStanza(received[3]))); - CPPUNIT_ASSERT_EQUAL(std::string("hi there2!"), dynamic_cast(getStanza(received[3]))->getBody()); - CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[3]))->getTo().toString()); - CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received[3]))->getFrom().toString()); - } void handleGroupchatMessagesBouncerLeave() { @@ -408,17 +410,17 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe injectPresence(response); loop->processEvents(); - CPPUNIT_ASSERT_EQUAL(4, (int) received.size()); + CPPUNIT_ASSERT_EQUAL(3, (int) received.size()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[1]))); + CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast(getStanza(received[1]))->getBody()); + CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[1]))->getTo().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received[1]))->getFrom().toString()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[2]))); - CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast(getStanza(received[2]))->getBody()); + CPPUNIT_ASSERT_EQUAL(std::string("hi there2!"), dynamic_cast(getStanza(received[2]))->getBody()); CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[2]))->getTo().toString()); CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received[2]))->getFrom().toString()); - CPPUNIT_ASSERT(dynamic_cast(getStanza(received[3]))); - CPPUNIT_ASSERT_EQUAL(std::string("hi there2!"), dynamic_cast(getStanza(received[3]))->getBody()); - CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[3]))->getTo().toString()); - CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received[3]))->getFrom().toString()); - } void handleGroupchatMessagesTwoResources() { @@ -472,7 +474,7 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe conv->addJID("user@localhost/resource"); // normal presence - conv->handleParticipantChanged("anotheruser", 0, Swift::StatusShow::Away, "my status message"); + conv->handleParticipantChanged("anotheruser", Conversation::PARTICIPANT_FLAG_NONE, Swift::StatusShow::Away, "my status message"); loop->processEvents(); CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); @@ -487,7 +489,7 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe received.clear(); // this user presence - status code 110 - conv->handleParticipantChanged("nickname", 1, Swift::StatusShow::Away, "my status message"); + conv->handleParticipantChanged("nickname", Conversation::PARTICIPANT_FLAG_MODERATOR, Swift::StatusShow::Away, "my status message"); loop->processEvents(); CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); @@ -503,7 +505,7 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe received.clear(); // renamed - status code 303 - conv->handleParticipantChanged("anotheruser", 1, Swift::StatusShow::Away, "my status message", "hanzz"); + conv->handleParticipantChanged("anotheruser", Conversation::PARTICIPANT_FLAG_MODERATOR, Swift::StatusShow::Away, "my status message", "hanzz"); loop->processEvents(); CPPUNIT_ASSERT_EQUAL(2, (int) received.size()); @@ -530,7 +532,7 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe conv->addJID("user@localhost/resource2"); // normal presence - conv->handleParticipantChanged("anotheruser", 0, Swift::StatusShow::Away, "my status message"); + conv->handleParticipantChanged("anotheruser", Conversation::PARTICIPANT_FLAG_NONE, Swift::StatusShow::Away, "my status message"); loop->processEvents(); CPPUNIT_ASSERT_EQUAL(1, (int) received2.size()); @@ -551,7 +553,7 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe conv->setNickname("nickname"); conv->setJID("user@localhost/resource"); - conv->handleParticipantChanged("anotheruser", 0, Swift::StatusShow::Away, "my status message"); + conv->handleParticipantChanged("anotheruser", Conversation::PARTICIPANT_FLAG_NONE, Swift::StatusShow::Away, "my status message"); loop->processEvents(); received.clear(); @@ -593,6 +595,44 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe CPPUNIT_ASSERT_EQUAL(332, getStanza(received[0])->getPayload()->getStatusCodes()[0].code); } + void handleNicknameConflict() { + User *user = userManager->getUser("user@localhost"); + TestingConversation *conv = new TestingConversation(user->getConversationManager(), "#room", true); + + conv->onMessageToSend.connect(boost::bind(&ConversationManagerTest::handleMessageReceived, this, _1, _2)); + conv->setNickname("nickname"); + conv->addJID("user@localhost/resource"); + + // normal presence + conv->handleParticipantChanged("nickname", Conversation::PARTICIPANT_FLAG_CONFLICT, Swift::StatusShow::Away, "my status message"); + loop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[0]))); + CPPUNIT_ASSERT_EQUAL(Swift::Presence::Error, dynamic_cast(getStanza(received[0]))->getType()); + CPPUNIT_ASSERT(getStanza(received[0])->getPayload()); + CPPUNIT_ASSERT_EQUAL(Swift::ErrorPayload::Conflict, getStanza(received[0])->getPayload()->getCondition()); + } + + void handleNotAuthorized() { + User *user = userManager->getUser("user@localhost"); + TestingConversation *conv = new TestingConversation(user->getConversationManager(), "#room", true); + + conv->onMessageToSend.connect(boost::bind(&ConversationManagerTest::handleMessageReceived, this, _1, _2)); + conv->setNickname("nickname"); + conv->addJID("user@localhost/resource"); + + // normal presence + conv->handleParticipantChanged("nickname", Conversation::PARTICIPANT_FLAG_NOT_AUTHORIZED, Swift::StatusShow::Away, "my status message"); + loop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[0]))); + CPPUNIT_ASSERT_EQUAL(Swift::Presence::Error, dynamic_cast(getStanza(received[0]))->getType()); + CPPUNIT_ASSERT(getStanza(received[0])->getPayload()); + CPPUNIT_ASSERT_EQUAL(Swift::ErrorPayload::NotAuthorized, getStanza(received[0])->getPayload()->getCondition()); + } + }; CPPUNIT_TEST_SUITE_REGISTRATION (ConversationManagerTest); diff --git a/src/tests/rostermanager.cpp b/src/tests/rostermanager.cpp index 35d2d444..b9df7a0f 100644 --- a/src/tests/rostermanager.cpp +++ b/src/tests/rostermanager.cpp @@ -23,6 +23,7 @@ using namespace Transport; class RosterManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest { CPPUNIT_TEST_SUITE(RosterManagerTest); CPPUNIT_TEST(setBuddy); + CPPUNIT_TEST(setBuddyNoAlias); CPPUNIT_TEST(sendCurrentPresences); CPPUNIT_TEST(sendUnavailablePresences); CPPUNIT_TEST(sendCurrentPresence); @@ -72,6 +73,25 @@ class RosterManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest { } + void setBuddyNoAlias() { + User *user = userManager->getUser("user@localhost"); + CPPUNIT_ASSERT(user); + + std::vector grp; + grp.push_back("group1"); + LocalBuddy *buddy = new LocalBuddy(user->getRosterManager(), -1, "buddy1", "", grp, BUDDY_JID_ESCAPING); + user->getRosterManager()->setBuddy(buddy); + + CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); + + Swift::RosterPayload::ref payload1 = getStanza(received[0])->getPayload(); + CPPUNIT_ASSERT(payload1); + CPPUNIT_ASSERT_EQUAL(1, (int) payload1->getItems().size()); + Swift::RosterItemPayload item = payload1->getItems()[0]; + CPPUNIT_ASSERT_EQUAL(std::string("buddy1"), Buddy::JIDToLegacyName(item.getJID())); + CPPUNIT_ASSERT_EQUAL(std::string(""), item.getName()); + } + void setBuddy() { add2Buddies(); CPPUNIT_ASSERT_EQUAL(4, (int) received.size()); diff --git a/src/tests/user.cpp b/src/tests/user.cpp index 0575f979..932827a0 100644 --- a/src/tests/user.cpp +++ b/src/tests/user.cpp @@ -125,7 +125,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { User *user = userManager->getUser("user@localhost"); Swift::Presence::ref response = Swift::Presence::create(); - response->setTo("#room@localhost/hanzz"); + response->setTo("room@localhost/hanzz"); response->setFrom("user@localhost/resource"); Swift::MUCPayload *payload = new Swift::MUCPayload(); @@ -134,11 +134,8 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { injectPresence(response); loop->processEvents(); - // no presence received in server mode, just disco#info - CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); - CPPUNIT_ASSERT(getStanza(received[0])->getPayload()); - - CPPUNIT_ASSERT_EQUAL(std::string("#room"), room); + CPPUNIT_ASSERT_EQUAL(0, (int) received.size()); + CPPUNIT_ASSERT_EQUAL(std::string("room"), room); CPPUNIT_ASSERT_EQUAL(std::string("hanzz"), roomNickname); CPPUNIT_ASSERT_EQUAL(std::string("password"), roomPassword); @@ -147,7 +144,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { roomPassword = ""; // simulate that backend joined the room - TestingConversation *conv = new TestingConversation(user->getConversationManager(), "#room", true); + TestingConversation *conv = new TestingConversation(user->getConversationManager(), "room", true); conv->addJID("user@localhost/resource"); user->getConversationManager()->addConversation(conv); @@ -156,8 +153,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { loop->processEvents(); // no presence received in server mode, just disco#info - CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); - CPPUNIT_ASSERT(getStanza(received[0])->getPayload()); + CPPUNIT_ASSERT_EQUAL(0, (int) received.size()); CPPUNIT_ASSERT_EQUAL(std::string(""), room); CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname); @@ -169,14 +165,14 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { User *user = userManager->getUser("user@localhost"); // Add 1 participant - Conversation *conv = user->getConversationManager()->getConversation("#room"); - conv->handleParticipantChanged("anotheruser", 0, Swift::StatusShow::Away, "my status message"); + Conversation *conv = user->getConversationManager()->getConversation("room"); + conv->handleParticipantChanged("anotheruser", Conversation::PARTICIPANT_FLAG_NONE, Swift::StatusShow::Away, "my status message"); // Connect 2nd resource connectSecondResource(); received2.clear(); Swift::Presence::ref response = Swift::Presence::create(); - response->setTo("#room@localhost/hanzz"); + response->setTo("room@localhost/hanzz"); response->setFrom("user@localhost/resource2"); Swift::MUCPayload *payload = new Swift::MUCPayload(); @@ -189,19 +185,20 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname); CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword); - CPPUNIT_ASSERT_EQUAL(2, (int) received2.size()); - CPPUNIT_ASSERT(dynamic_cast(getStanza(received2[1]))); - CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast(getStanza(received2[1]))->getShow()); - CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource2"), dynamic_cast(getStanza(received2[1]))->getTo().toString()); - CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received2[1]))->getFrom().toString()); - CPPUNIT_ASSERT(getStanza(received2[1])->getPayload()); - CPPUNIT_ASSERT_EQUAL(Swift::MUCOccupant::Member, *getStanza(received2[1])->getPayload()->getItems()[0].affiliation); - CPPUNIT_ASSERT_EQUAL(Swift::MUCOccupant::Participant, *getStanza(received2[1])->getPayload()->getItems()[0].role); + CPPUNIT_ASSERT_EQUAL(1, (int) received2.size()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received2[0]))); + CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast(getStanza(received2[0]))->getShow()); + CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource2"), dynamic_cast(getStanza(received2[0]))->getTo().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("room@localhost/anotheruser"), dynamic_cast(getStanza(received2[0]))->getFrom().toString()); + CPPUNIT_ASSERT(getStanza(received2[0])->getPayload()); + CPPUNIT_ASSERT_EQUAL(Swift::MUCOccupant::Member, *getStanza(received2[0])->getPayload()->getItems()[0].affiliation); + CPPUNIT_ASSERT_EQUAL(Swift::MUCOccupant::Participant, *getStanza(received2[0])->getPayload()->getItems()[0].role); } void handlePresenceLeaveRoom() { + received.clear(); Swift::Presence::ref response = Swift::Presence::create(); - response->setTo("#room@localhost/hanzz"); + response->setTo("room@localhost/hanzz"); response->setFrom("user@localhost/resource"); response->setType(Swift::Presence::Unavailable); @@ -213,9 +210,9 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { CPPUNIT_ASSERT_EQUAL(0, (int) received.size()); - CPPUNIT_ASSERT_EQUAL(std::string("#room"), room); - CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname); - CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword); +// CPPUNIT_ASSERT_EQUAL(std::string("room"), room); +// CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname); +// CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword); } void handlePresenceLeaveRoomTwoResources() { @@ -224,7 +221,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { // User is still connected from resource2, so he should not leave the room Swift::Presence::ref response = Swift::Presence::create(); - response->setTo("#room@localhost/hanzz"); + response->setTo("room@localhost/hanzz"); response->setFrom("user@localhost/resource"); response->setType(Swift::Presence::Unavailable); @@ -243,7 +240,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { // disconnect also from resource // User is still connected from resource2, so he should not leave the room response = Swift::Presence::create(); - response->setTo("#room@localhost/hanzz"); + response->setTo("room@localhost/hanzz"); response->setFrom("user@localhost/resource2"); response->setType(Swift::Presence::Unavailable); @@ -255,7 +252,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { CPPUNIT_ASSERT_EQUAL(0, (int) received.size()); - CPPUNIT_ASSERT_EQUAL(std::string("#room"), room); + CPPUNIT_ASSERT_EQUAL(std::string("room"), room); CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname); CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword); } @@ -278,7 +275,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname); CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword); - Conversation *conv = user->getConversationManager()->getConversation("#room"); + Conversation *conv = user->getConversationManager()->getConversation("room"); CPPUNIT_ASSERT_EQUAL(1, (int) conv->getJIDs().size()); CPPUNIT_ASSERT_EQUAL(Swift::JID("user@localhost/resource2"), conv->getJIDs().front()); } @@ -287,7 +284,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { User *user = userManager->getUser("user@localhost"); user->addUserSetting("stay_connected", "1"); Swift::Presence::ref response = Swift::Presence::create(); - response->setTo("#room@localhost/hanzz"); + response->setTo("room@localhost/hanzz"); response->setFrom("user@localhost/resource"); response->setType(Swift::Presence::Unavailable); @@ -312,7 +309,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { // User is still connected from resource2, so he should not leave the room Swift::Presence::ref response = Swift::Presence::create(); - response->setTo("#room@localhost/hanzz"); + response->setTo("room@localhost/hanzz"); response->setFrom("user@localhost/resource"); response->setType(Swift::Presence::Unavailable); @@ -332,7 +329,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { // disconnect also from resource // User is still connected from resource2, so he should not leave the room response = Swift::Presence::create(); - response->setTo("#room@localhost/hanzz"); + response->setTo("room@localhost/hanzz"); response->setFrom("user@localhost/resource2"); response->setType(Swift::Presence::Unavailable); @@ -368,7 +365,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname); CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword); - Conversation *conv = user->getConversationManager()->getConversation("#room"); + Conversation *conv = user->getConversationManager()->getConversation("room"); CPPUNIT_ASSERT_EQUAL(1, (int) conv->getJIDs().size()); CPPUNIT_ASSERT_EQUAL(Swift::JID("user@localhost/resource2"), conv->getJIDs().front()); } @@ -377,12 +374,12 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { User *user = userManager->getUser("user@localhost"); handlePresenceJoinRoom(); - CPPUNIT_ASSERT(user->getConversationManager()->getConversation("#room")); + CPPUNIT_ASSERT(user->getConversationManager()->getConversation("room")); received.clear(); handlePresenceLeaveRoom(); - CPPUNIT_ASSERT(!user->getConversationManager()->getConversation("#room")); + CPPUNIT_ASSERT(!user->getConversationManager()->getConversation("room")); } void handleDisconnected() { @@ -427,7 +424,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { user->setConnected(false); Swift::Presence::ref response = Swift::Presence::create(); - response->setTo("#room@localhost/hanzz"); + response->setTo("room@localhost/hanzz"); response->setFrom("user@localhost/resource"); Swift::MUCPayload *payload = new Swift::MUCPayload(); @@ -436,16 +433,13 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { injectPresence(response); loop->processEvents(); - // no presence received in server mode, just disco#info - CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); - CPPUNIT_ASSERT(getStanza(received[0])->getPayload()); - + CPPUNIT_ASSERT_EQUAL(0, (int) received.size()); CPPUNIT_ASSERT_EQUAL(std::string(""), room); CPPUNIT_ASSERT_EQUAL(std::string(""), roomNickname); CPPUNIT_ASSERT_EQUAL(std::string(""), roomPassword); user->setConnected(true); - CPPUNIT_ASSERT_EQUAL(std::string("#room"), room); + CPPUNIT_ASSERT_EQUAL(std::string("room"), room); CPPUNIT_ASSERT_EQUAL(std::string("hanzz"), roomNickname); CPPUNIT_ASSERT_EQUAL(std::string("password"), roomPassword); } @@ -460,7 +454,7 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest { received.clear(); user->setConnected(true); - CPPUNIT_ASSERT_EQUAL(std::string("#room"), room); + CPPUNIT_ASSERT_EQUAL(std::string("room"), room); CPPUNIT_ASSERT_EQUAL(std::string("hanzz"), roomNickname); CPPUNIT_ASSERT_EQUAL(std::string("password"), roomPassword); CPPUNIT_ASSERT_EQUAL(0, (int) received.size()); diff --git a/src/tests/userregistry.cpp b/src/tests/userregistry.cpp index 9b5a7aa0..7e567cfd 100644 --- a/src/tests/userregistry.cpp +++ b/src/tests/userregistry.cpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include using namespace Transport; diff --git a/src/transport.cpp b/src/transport.cpp index 7bd92b4d..9c7172be 100644 --- a/src/transport.cpp +++ b/src/transport.cpp @@ -51,7 +51,7 @@ #include "transport/BlockSerializer.h" #include "Swiften/Parser/PayloadParsers/InvisibleParser.h" #include "Swiften/Serializer/PayloadSerializers/InvisibleSerializer.h" -#include "Swiften/Swiften.h" +#include "Swiften/Parser/GenericPayloadParserFactory.h" using namespace Swift; using namespace boost; @@ -275,9 +275,8 @@ void Component::handleDataWritten(const Swift::SafeByteArray &data) { } void Component::handlePresence(Swift::Presence::ref presence) { - bool isMUC = presence->getPayload() != NULL || *presence->getTo().getNode().c_str() == '#'; // filter out login/logout presence spam - if (!presence->getTo().getNode().empty() && isMUC == false) + if (!presence->getTo().getNode().empty()) return; // filter out bad presences diff --git a/src/user.cpp b/src/user.cpp index a142fefc..43234bcf 100644 --- a/src/user.cpp +++ b/src/user.cpp @@ -26,7 +26,6 @@ #include "transport/conversationmanager.h" #include "transport/presenceoracle.h" #include "transport/logging.h" -#include "Swiften/Swiften.h" #include "Swiften/Server/ServerStanzaChannel.h" #include "Swiften/Elements/StreamError.h" #include "Swiften/Elements/MUCPayload.h" @@ -195,11 +194,6 @@ void User::setCacheMessages(bool cacheMessages) { } void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) { - - int currentResourcesCount = m_presenceOracle->getAllPresence(m_jid).size(); - - m_conversationManager->resetResources(); - LOG4CXX_INFO(logger, "PRESENCE " << presence->getFrom().toString() << " " << presence->getTo().toString()); if (!m_connected) { // we are not connected to legacy network, so we should do it when disco#info arrive :) @@ -231,8 +225,9 @@ void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) { } } - bool isMUC = presence->getPayload() != NULL || *presence->getTo().getNode().c_str() == '#'; - if (isMUC) { + + if (!presence->getTo().getNode().empty()) { + bool isMUC = presence->getPayload() != NULL || *presence->getTo().getNode().c_str() == '#'; if (presence->getType() == Swift::Presence::Unavailable) { std::string room = Buddy::JIDToLegacyName(presence->getTo()); Conversation *conv = m_conversationManager->getConversation(room); @@ -242,6 +237,9 @@ void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) { return; } } + else { + return; + } if (getUserSetting("stay_connected") != "1") { LOG4CXX_INFO(logger, m_jid.toString() << ": Going to left room " << room); @@ -260,7 +258,7 @@ void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) { } } } - else { + else if (isMUC) { // force connection to legacy network to let backend to handle auto-join on connect. if (!m_readyForConnect) { LOG4CXX_INFO(logger, m_jid.toString() << ": Ready to be connected to legacy network"); @@ -317,9 +315,29 @@ void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) { } return; } - + + int currentResourcesCount = m_presenceOracle->getAllPresence(m_jid).size(); + + m_conversationManager->resetResources(); + + if (presence->getType() == Swift::Presence::Unavailable) { m_conversationManager->removeJID(presence->getFrom()); + + std::string presences; + std::vector ps = m_presenceOracle->getAllPresence(m_jid); + BOOST_FOREACH(Swift::Presence::ref p, ps) { + if (p != presence) { + presences += p->getFrom().toString() + " "; + } + }; + + if (!presences.empty()) { + LOG4CXX_INFO(logger, m_jid.toString() << ": User is still connected from following clients: " << presences); + } + else { + LOG4CXX_INFO(logger, m_jid.toString() << ": Last client disconnected"); + } } diff --git a/src/usermanager.cpp b/src/usermanager.cpp index 61872258..23ffa53d 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -29,9 +29,10 @@ #include "transport/discoitemsresponder.h" #include "storageresponder.h" -#include "Swiften/Swiften.h" #include "Swiften/Server/ServerStanzaChannel.h" #include "Swiften/Elements/StreamError.h" +#include "Swiften/Elements/MUCPayload.h" +#include "Swiften/Elements/ChatState.h" #ifndef __FreeBSD__ #include "malloc.h" #endif @@ -229,7 +230,7 @@ void UserManager::handlePresence(Swift::Presence::ref presence) { res.password = ""; res.uin = presence->getFrom().getNode(); res.jid = userkey; - if (res.uin.find_last_of("%") != std::string::npos) { // OK + while (res.uin.find_last_of("%") != std::string::npos) { // OK res.uin.replace(res.uin.find_last_of("%"), 1, "@"); // OK } if (m_storageBackend) { @@ -399,6 +400,7 @@ void UserManager::handleGeneralPresenceReceived(Swift::Presence::ref presence) { break; case Swift::Presence::Available: case Swift::Presence::Unavailable: + handleMUCPresence(presence); break; case Swift::Presence::Probe: handleProbePresence(presence); @@ -411,6 +413,24 @@ void UserManager::handleGeneralPresenceReceived(Swift::Presence::ref presence) { }; } +void UserManager::handleMUCPresence(Swift::Presence::ref presence) { + // Don't let RosterManager to handle presences for us + if (presence->getTo().getNode().empty()) { + return; + } + + if (presence->getType() == Swift::Presence::Available) { + handlePresence(presence); + } + else if (presence->getType() == Swift::Presence::Unavailable) { + std::string userkey = presence->getFrom().toBare().toString(); + User *user = getUser(userkey); + if (user) { + user->handlePresence(presence); + } + } +} + void UserManager::handleProbePresence(Swift::Presence::ref presence) { // Don't let RosterManager to handle presences for us if (presence->getTo().getNode().empty()) { diff --git a/src/userregistration.cpp b/src/userregistration.cpp index 174587fd..75f2d942 100644 --- a/src/userregistration.cpp +++ b/src/userregistration.cpp @@ -26,6 +26,9 @@ #include "transport/user.h" #include "transport/logging.h" #include "Swiften/Elements/ErrorPayload.h" +#include "Swiften/EventLoop/SimpleEventLoop.h" +#include "Swiften/Network/BoostNetworkFactories.h" +#include "Swiften/Client/Client.h" #include #include #include diff --git a/src/userregistry.cpp b/src/userregistry.cpp index 8d8a3975..a740e898 100644 --- a/src/userregistry.cpp +++ b/src/userregistry.cpp @@ -20,7 +20,6 @@ #include #include -#include "Swiften/Swiften.h" #include "Swiften/Server/UserRegistry.h" #include "transport/userregistry.h" #include "transport/logging.h" @@ -79,9 +78,6 @@ void UserRegistry::stopLogin(const Swift::JID& user, Swift::ServerFromClientSess LOG4CXX_WARN(logger, key << ": Stopping login process (user probably disconnected while logging in), but this is not active session"); } } - else { - LOG4CXX_WARN(logger, key << ": Stopping login process (user probably disconnected while logging in) for invalid user"); - } // ::removeLater can be called only by libtransport, not by Swift and libtransport // takes care about user disconnecting itself, so don't call our signal. @@ -96,21 +92,15 @@ void UserRegistry::onPasswordValid(const Swift::JID &user) { users[key].session->handlePasswordValid(); users.erase(key); } - else { - LOG4CXX_INFO(logger, key << ": onPasswordValid called for invalid user"); - } } void UserRegistry::onPasswordInvalid(const Swift::JID &user, const std::string &error) { std::string key = user.toBare().toString(); if (users.find(key) != users.end()) { - LOG4CXX_INFO(logger, key << ": Password is invalid"); + LOG4CXX_INFO(logger, key << ": Password is invalid or there was an error when connecting the legacy network"); users[key].session->handlePasswordInvalid(error); users.erase(key); } - else { - LOG4CXX_INFO(logger, key << ": onPasswordInvalid called for invalid user"); - } } void UserRegistry::handleRemoveTimeout(const Swift::JID &user) { diff --git a/src/usersreconnecter.cpp b/src/usersreconnecter.cpp index ada0283a..1ba6cfff 100644 --- a/src/usersreconnecter.cpp +++ b/src/usersreconnecter.cpp @@ -23,11 +23,12 @@ #include #include #include "Swiften/Queries/IQRouter.h" -#include "Swiften/Swiften.h" #include "transport/storagebackend.h" #include "transport/transport.h" #include "transport/logging.h" +#include "Swiften/Network/NetworkFactories.h" + using namespace Swift; using namespace boost; diff --git a/src/vcardresponder.cpp b/src/vcardresponder.cpp index 214e94e2..f216c92a 100644 --- a/src/vcardresponder.cpp +++ b/src/vcardresponder.cpp @@ -23,7 +23,6 @@ #include #include #include "Swiften/Queries/IQRouter.h" -#include "Swiften/Swiften.h" #include "transport/user.h" #include "transport/usermanager.h" #include "transport/rostermanager.h"