From 9de5e656da7df4697a03153a3cdb809932b342f7 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Mon, 8 Feb 2016 09:26:34 +0100 Subject: [PATCH] Libpurple + Libtransport: Support aliases in rooms, fix joining rooms on protocols where you cannot join with custom nickname, show topic in the service discovery for rooms. --- backends/libpurple/main.cpp | 70 ++++++++++++++++++++++------ include/transport/Conversation.h | 15 +++--- include/transport/NetworkPlugin.h | 3 +- include/transport/protocol.proto | 1 + libtransport/Conversation.cpp | 24 ++++++---- libtransport/NetworkPluginServer.cpp | 7 ++- libtransport/UserManager.cpp | 1 + plugin/cpp/networkplugin.cpp | 3 +- 8 files changed, 89 insertions(+), 35 deletions(-) diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index 841b0243..7fe161d1 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -704,14 +704,19 @@ class SpectrumNetworkPlugin : public NetworkPlugin { comps = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, (room + "/" + nickname).c_str()); } else { comps = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, room.c_str()); - np->handleParticipantChanged(np->m_accounts[account], nickname, room, 0, pbnetwork::STATUS_ONLINE); - const char *disp; - if ((disp = purple_connection_get_display_name(account->gc))) { - handleRoomNicknameChanged(np->m_accounts[account], room, disp); - } - else { - handleRoomNicknameChanged(np->m_accounts[account], room, purple_account_get_username(account)); - } + } + } + + if (CONFIG_STRING(config, "service.protocol") != "prpl-jabber") { + np->handleParticipantChanged(np->m_accounts[account], nickname, room, 0, pbnetwork::STATUS_ONLINE); + const char *disp; + if ((disp = purple_connection_get_display_name(account->gc))) { + handleRoomNicknameChanged(np->m_accounts[account], room, disp); + np->handleParticipantChanged(np->m_accounts[account], nickname, room, 0, pbnetwork::STATUS_ONLINE, "", disp); + } + else { + handleRoomNicknameChanged(np->m_accounts[account], room, purple_account_get_username(account)); + np->handleParticipantChanged(np->m_accounts[account], nickname, room, 0, pbnetwork::STATUS_ONLINE, "", purple_account_get_username(account)); } } @@ -1182,6 +1187,7 @@ static void conv_chat_add_users(PurpleConversation *conv, GList *cbuddies, gbool while (l != NULL) { PurpleConvChatBuddy *cb = (PurpleConvChatBuddy *)l->data; std::string name(cb->name); + std::string alias = cb->alias ? cb->alias : cb->name; int flags = GPOINTER_TO_INT(cb->flags); if (flags & PURPLE_CBFLAGS_OP || flags & PURPLE_CBFLAGS_HALFOP) { // item->addAttribute("affiliation", "admin"); @@ -1199,7 +1205,7 @@ static void conv_chat_add_users(PurpleConversation *conv, GList *cbuddies, gbool // item->addAttribute("role", "participant"); } - np->handleParticipantChanged(np->m_accounts[account], name, purple_conversation_get_name_wrapped(conv), (int) flags, pbnetwork::STATUS_ONLINE); + np->handleParticipantChanged(np->m_accounts[account], name, purple_conversation_get_name_wrapped(conv), (int) flags, pbnetwork::STATUS_ONLINE, "", "", alias); l = l->next; } @@ -1597,14 +1603,47 @@ static PurpleXferUiOps xferUiOps = static void RoomlistProgress(PurpleRoomlist *list, gboolean in_progress) { - if (!in_progress) - { + if (!in_progress) { + GList *fields = purple_roomlist_get_fields(list); + GList *field; + int topicId = -1; + int id = 0; + for (field = fields; field != NULL; field = field->next, id++) { + PurpleRoomlistField *f = (PurpleRoomlistField *) field->data; + if (!f || !f->name) { + continue; + } + std::string fstring = f->name; + if (fstring == "topic") { + topicId = id; + } + else { + LOG4CXX_INFO(logger, "Uknown RoomList field " << fstring); + } + } + + LOG4CXX_INFO(logger, "RoomList topic ID: " << topicId); + GList *rooms; std::list m_rooms; - for (rooms = list->rooms; rooms != NULL; rooms = rooms->next) - { + std::list m_topics; + for (rooms = list->rooms; rooms != NULL; rooms = rooms->next) { PurpleRoomlistRoom *room = (PurpleRoomlistRoom *)rooms->data; m_rooms.push_back(room->name); + + if (topicId == -1) { + m_topics.push_back(room->name); + } + else { + char *topic = (char *) g_list_nth_data(purple_roomlist_room_get_fields(room), topicId); + if (topic) { + m_topics.push_back(topic); + } + else { + LOG4CXX_WARN(logger, "RoomList topic is NULL"); + m_topics.push_back(room->name); + } + } } std::string user = ""; @@ -1613,7 +1652,7 @@ static void RoomlistProgress(PurpleRoomlist *list, gboolean in_progress) } LOG4CXX_INFO(logger, "RoomList is fetched for user " << user); - np->handleRoomList(user, m_rooms, m_rooms); + np->handleRoomList(user, m_rooms, m_topics); } else { LOG4CXX_INFO(logger, "RoomList is still in progress"); @@ -1928,6 +1967,9 @@ static void transportDataReceived(gpointer data, gint source, PurpleInputConditi if (CONFIG_STRING(config, "service.protocol") == "prpl-telegram") { cfg.setNeedPassword(false); } + if (CONFIG_STRING(config, "service.protocol") != "prpl-irc") { + cfg.setNeedRegistration(false); + } np->sendConfig(cfg); } diff --git a/include/transport/Conversation.h b/include/transport/Conversation.h index 94ae77d4..d5374ec9 100644 --- a/include/transport/Conversation.h +++ b/include/transport/Conversation.h @@ -44,12 +44,6 @@ class Conversation { PARTICIPANT_FLAG_ROOM_NOT_FOUD = 64 } ParticipantFlag; - typedef struct _Participant { - ParticipantFlag flag; - int status; - std::string statusMessage; - } Participant; - /// Creates new conversation. /// \param conversationManager ConversationManager associated with this Conversation. @@ -81,7 +75,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, ParticipantFlag flag, int status = Swift::StatusShow::None, const std::string &statusMessage = "", const std::string &newname = "", const std::string &iconhash = ""); + void handleParticipantChanged(const std::string &nickname, ParticipantFlag flag, int status = Swift::StatusShow::None, const std::string &statusMessage = "", const std::string &newname = "", const std::string &iconhash = "", const std::string &alias = ""); /// Sets XMPP user nickname in MUC rooms. @@ -176,7 +170,12 @@ class Conversation { // every time, so we can get history messages for IRC for example. boost::shared_ptr m_subject; std::list > m_cachedMessages; - std::map m_participants; + + typedef struct { + Swift::Presence::ref presence; + std::string alias; + } Participant; + std::map m_participants; }; } diff --git a/include/transport/NetworkPlugin.h b/include/transport/NetworkPlugin.h index c9493a26..ece57e79 100644 --- a/include/transport/NetworkPlugin.h +++ b/include/transport/NetworkPlugin.h @@ -103,7 +103,8 @@ class NetworkPlugin { /// \param statusMessage Current status message of participant. /// \param newname New name of participant if he changed the nickname. Otherwise empty. void handleParticipantChanged(const std::string &user, const std::string &nickname, const std::string &room, int flags, - pbnetwork::StatusType = pbnetwork::STATUS_NONE, const std::string &statusMessage = "", const std::string &newname = ""); + pbnetwork::StatusType = pbnetwork::STATUS_NONE, const std::string &statusMessage = "", const std::string &newname = "", + const std::string &alias = ""); /// Call this function when user disconnected the legacy network because of some legacy network error. /// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld") diff --git a/include/transport/protocol.proto b/include/transport/protocol.proto index 703738f6..8f8a790b 100644 --- a/include/transport/protocol.proto +++ b/include/transport/protocol.proto @@ -112,6 +112,7 @@ message Participant { optional string statusMessage = 6; optional string newname = 7; optional string iconHash = 8; + optional string alias = 9; } message VCard { diff --git a/libtransport/Conversation.cpp b/libtransport/Conversation.cpp index d1bfef72..1907eb83 100644 --- a/libtransport/Conversation.cpp +++ b/libtransport/Conversation.cpp @@ -207,6 +207,11 @@ void Conversation::handleMessage(boost::shared_ptr &message, con n = " "; } + std::map::iterator it = m_participants.find(n); + if (it != m_participants.end() && !it->second.alias.empty()) { + n = it->second.alias; + } + message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), n)); LOG4CXX_INFO(logger, "MSG FROM " << message->getFrom().toString()); } @@ -216,16 +221,16 @@ void Conversation::handleMessage(boost::shared_ptr &message, con std::string Conversation::getParticipants() { std::string ret; - for (std::map::iterator it = m_participants.begin(); it != m_participants.end(); it++) { - ret += (*it).second->getFrom().getResource() + ", "; + for (std::map::iterator it = m_participants.begin(); it != m_participants.end(); it++) { + ret += (*it).second.presence->getFrom().getResource() + ", "; } return ret; } void Conversation::sendParticipants(const Swift::JID &to) { - for (std::map::iterator it = m_participants.begin(); it != m_participants.end(); it++) { - (*it).second->setTo(to); - m_conversationManager->getComponent()->getFrontend()->sendPresence((*it).second); + for (std::map::iterator it = m_participants.begin(); it != m_participants.end(); it++) { + (*it).second.presence->setTo(to); + m_conversationManager->getComponent()->getFrontend()->sendPresence((*it).second.presence); } } @@ -352,17 +357,18 @@ void Conversation::setNickname(const std::string &nickname) { void Conversation::handleRawPresence(Swift::Presence::ref presence) { // TODO: Detect nickname change. m_conversationManager->getComponent()->getFrontend()->sendPresence(presence); - m_participants[presence->getFrom().getResource()] = presence; + m_participants[presence->getFrom().getResource()].presence = presence; } -void Conversation::handleParticipantChanged(const std::string &nick, Conversation::ParticipantFlag flag, int status, const std::string &statusMessage, const std::string &newname, const std::string &iconhash) { - Swift::Presence::ref presence = generatePresence(nick, flag, status, statusMessage, newname, iconhash); +void Conversation::handleParticipantChanged(const std::string &nick, Conversation::ParticipantFlag flag, int status, const std::string &statusMessage, const std::string &newname, const std::string &iconhash, const std::string &alias) { + Swift::Presence::ref presence = generatePresence(alias.empty() ? nick : alias, flag, status, statusMessage, newname, iconhash); if (presence->getType() == Swift::Presence::Unavailable) { m_participants.erase(nick); } else { - m_participants[nick] = presence; + m_participants[nick].presence = presence; + m_participants[nick].alias = alias; } diff --git a/libtransport/NetworkPluginServer.cpp b/libtransport/NetworkPluginServer.cpp index 78667505..192d934d 100644 --- a/libtransport/NetworkPluginServer.cpp +++ b/libtransport/NetworkPluginServer.cpp @@ -636,7 +636,7 @@ void NetworkPluginServer::handleParticipantChangedPayload(const std::string &dat return; } - conv->handleParticipantChanged(payload.nickname(), (Conversation::ParticipantFlag) payload.flag(), payload.status(), payload.statusmessage(), payload.newname(), payload.iconhash()); + conv->handleParticipantChanged(payload.nickname(), (Conversation::ParticipantFlag) payload.flag(), payload.status(), payload.statusmessage(), payload.newname(), payload.iconhash(), payload.alias()); } void NetworkPluginServer::handleRoomChangedPayload(const std::string &data) { @@ -646,11 +646,14 @@ void NetworkPluginServer::handleRoomChangedPayload(const std::string &data) { } User *user = m_userManager->getUser(payload.username()); - if (!user) + if (!user) { + LOG4CXX_ERROR(logger, "RoomChangePayload for unknown user " << user); return; + } NetworkConversation *conv = (NetworkConversation *) user->getConversationManager()->getConversation(payload.room()); if (!conv) { + LOG4CXX_ERROR(logger, "RoomChangePayload for unknown conversation " << payload.room()); return; } diff --git a/libtransport/UserManager.cpp b/libtransport/UserManager.cpp index f4746013..44d9bd3c 100644 --- a/libtransport/UserManager.cpp +++ b/libtransport/UserManager.cpp @@ -220,6 +220,7 @@ void UserManager::handlePresence(Swift::Presence::ref presence) { if (CONFIG_BOOL_DEFAULTED(m_component->getConfig(), "registration.needRegistration", false) && CONFIG_BOOL_DEFAULTED(m_component->getConfig(), "registration.needPassword", true)) { m_userRegistry->onPasswordInvalid(presence->getFrom()); + LOG4CXX_INFO(logger, userkey << ": Tried to login, but is not registered."); return; } res.password = ""; diff --git a/plugin/cpp/networkplugin.cpp b/plugin/cpp/networkplugin.cpp index 9d1a73e1..bf900db7 100644 --- a/plugin/cpp/networkplugin.cpp +++ b/plugin/cpp/networkplugin.cpp @@ -287,7 +287,7 @@ void NetworkPlugin::handleDisconnected(const std::string &user, int error, const send(message); } -void NetworkPlugin::handleParticipantChanged(const std::string &user, const std::string &nickname, const std::string &room, int flags, pbnetwork::StatusType status, const std::string &statusMessage, const std::string &newname) { +void NetworkPlugin::handleParticipantChanged(const std::string &user, const std::string &nickname, const std::string &room, int flags, pbnetwork::StatusType status, const std::string &statusMessage, const std::string &newname, const std::string &alias) { pbnetwork::Participant d; d.set_username(user); d.set_nickname(nickname); @@ -296,6 +296,7 @@ void NetworkPlugin::handleParticipantChanged(const std::string &user, const std: d.set_newname(newname); d.set_status((pbnetwork::StatusType) status); d.set_statusmessage(statusMessage); + d.set_alias(alias); std::string message; d.SerializeToString(&message);