diff --git a/examples/usermanager/main.cpp b/examples/usermanager/main.cpp index a3391a75..c181334e 100644 --- a/examples/usermanager/main.cpp +++ b/examples/usermanager/main.cpp @@ -17,7 +17,7 @@ int main(void) } Swift::SimpleEventLoop eventLoop; - Component transport(&eventLoop, &config); + Component transport(&eventLoop, &config, NULL); Logger logger(&transport); SQLite3Backend sql(&config); diff --git a/include/transport/conversationmanager.h b/include/transport/conversationmanager.h index fd5a2e6a..fe0bb61f 100644 --- a/include/transport/conversationmanager.h +++ b/include/transport/conversationmanager.h @@ -52,10 +52,13 @@ class ConversationManager { void unsetConversation(AbstractConversation *conv); private: + void handleMessageReceived(Swift::Message::ref message); + Component *m_component; User *m_user; std::map m_convs; + friend class UserManager; }; } diff --git a/include/transport/factory.h b/include/transport/factory.h new file mode 100644 index 00000000..8787e1cc --- /dev/null +++ b/include/transport/factory.h @@ -0,0 +1,42 @@ +/** + * XMPP - libpurple transport + * + * Copyright (C) 2009, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#pragma once + +#include +#include +#include "transport/transport.h" + +#include "Swiften/Swiften.h" +#include "Swiften/Elements/Message.h" +#include "transport/abstractconversation.h" + +namespace Transport { + +class AbstractConversation; +class ConversationManager; + +class Factory { + public: + + virtual AbstractConversation *createConversation(ConversationManager *conversationManager, const std::string &legacyName) = 0; +}; + +} diff --git a/include/transport/transport.h b/include/transport/transport.h index b31ee150..4eb24ada 100644 --- a/include/transport/transport.h +++ b/include/transport/transport.h @@ -33,6 +33,7 @@ #include "Swiften/Server/UserRegistry.h" #include #include "transport/config.h" +#include "transport/factory.h" #define tr(lang,STRING) (STRING) #define _(STRING) (STRING) @@ -48,6 +49,7 @@ namespace Transport { class DiscoInfoResponder; class DiscoItemsResponder; class RosterResponder; + class Factory; /// Represents one transport instance. @@ -63,7 +65,7 @@ namespace Transport { /// - service.password /// - service.server /// - service.port - Component(Swift::EventLoop *loop, Config *config); + Component(Swift::EventLoop *loop, Config *config, Factory *factory); /// Component destructor. ~Component(); @@ -103,6 +105,8 @@ namespace Transport { Swift::BoostNetworkFactories *getFactories() { return m_factories; } + Factory *getFactory() { return m_factory; } + /// This signal is emitted when server disconnects the transport because of some error. /// \param error disconnection error boost::signal onConnectionError; @@ -160,6 +164,7 @@ namespace Transport { Config* m_config; std::string m_protocol; Swift::JID m_jid; + Factory *m_factory; friend class User; friend class UserRegistration; diff --git a/include/transport/usermanager.h b/include/transport/usermanager.h index 20bd13b3..ce7dcc0e 100644 --- a/include/transport/usermanager.h +++ b/include/transport/usermanager.h @@ -68,6 +68,7 @@ class UserManager { private: void handlePresence(Swift::Presence::ref presence); + void handleMessageReceived(Swift::Message::ref message); // void handleDiscoInfoResponse(boost::shared_ptr info, Swift::ErrorPayload::ref error, const Swift::JID& jid); void addUser(User *user); diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index 3bc32f95..365e705e 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -11,6 +11,7 @@ #include "transport/user.h" #include "transport/storagebackend.h" #include "transport/rostermanager.h" +#include "transport/abstractconversation.h" #include "spectrumeventloop.h" #include "spectrumbuddy.h" #include "spectrumconversation.h" @@ -164,6 +165,9 @@ static void conv_destroy(PurpleConversation *conv) { } static void conv_write_im(PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime) { + // Don't forwards our own messages. + if (flags & PURPLE_MESSAGE_SEND || flags & PURPLE_MESSAGE_SYSTEM) + return; SpectrumConversation *s_conv = (SpectrumConversation *) conv->ui_data; if (!s_conv) return; @@ -423,6 +427,14 @@ static void handleUserDestroyed(User *user, UserManager *userManager, Config *co } } +class SpectrumFactory : public Factory { + public: + AbstractConversation *createConversation(ConversationManager *conversationManager, const std::string &legacyName) { + PurpleConversation *conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, (PurpleAccount *) conversationManager->getUser()->getData() , legacyName.c_str()); + return (AbstractConversation *) conv->ui_data; + } +}; + int main(int argc, char **argv) { GError *error = NULL; GOptionContext *context; @@ -494,7 +506,8 @@ int main(int argc, char **argv) { initPurple(config); SpectrumEventLoop eventLoop; - Component transport(&eventLoop, &config); + SpectrumFactory factory; + Component transport(&eventLoop, &config, &factory); Logger logger(&transport); _logger = &logger; diff --git a/spectrum/src/spectrumconversation.cpp b/spectrum/src/spectrumconversation.cpp index ede6c5ed..4f2eb53b 100644 --- a/spectrum/src/spectrumconversation.cpp +++ b/spectrum/src/spectrumconversation.cpp @@ -30,7 +30,12 @@ SpectrumConversation::~SpectrumConversation() { } void SpectrumConversation::sendMessage(boost::shared_ptr &message) { - + // escape and send + gchar *_markup = purple_markup_escape_text(message->getBody().c_str(), -1); + if (purple_conversation_get_type(m_conv) == PURPLE_CONV_TYPE_IM) { + purple_conv_im_send(PURPLE_CONV_IM(m_conv), _markup); + } + g_free(_markup); } diff --git a/spectrum/src/spectrumconversation.h b/spectrum/src/spectrumconversation.h index 4fe8fc0d..697019e6 100644 --- a/spectrum/src/spectrumconversation.h +++ b/spectrum/src/spectrumconversation.h @@ -27,6 +27,7 @@ #include #include "transport/abstractconversation.h" #include "transport/conversationmanager.h" +#include "transport/user.h" using namespace Transport; diff --git a/src/abstractconversation.cpp b/src/abstractconversation.cpp index fba69c7c..e5cd22f6 100644 --- a/src/abstractconversation.cpp +++ b/src/abstractconversation.cpp @@ -29,8 +29,8 @@ namespace Transport { AbstractConversation::AbstractConversation(ConversationManager *conversationManager, const std::string &legacyName) : m_conversationManager(conversationManager) { - m_conversationManager->setConversation(this); m_legacyName = legacyName; + m_conversationManager->setConversation(this); } AbstractConversation::~AbstractConversation() { diff --git a/src/conversationmanager.cpp b/src/conversationmanager.cpp index 3aa76cad..4be44c75 100644 --- a/src/conversationmanager.cpp +++ b/src/conversationmanager.cpp @@ -22,6 +22,7 @@ #include "transport/abstractconversation.h" #include "transport/usermanager.h" #include "transport/abstractbuddy.h" +#include "transport/factory.h" #include "transport/user.h" #include "Swiften/Roster/SetRosterRequest.h" #include "Swiften/Elements/RosterPayload.h" @@ -45,4 +46,16 @@ void ConversationManager::unsetConversation(AbstractConversation *conv) { m_convs.erase(conv->getLegacyName()); } +void ConversationManager::handleMessageReceived(Swift::Message::ref message) { + std::string name = message->getTo().getUnescapedNode(); + if (name.find_last_of("%") != std::string::npos) { + name.replace(name.find_last_of("%"), 1, "@"); + } + + if (!m_convs[name]) { + m_convs[name] = m_component->getFactory()->createConversation(this, name); + } + m_convs[name]->sendMessage(message); +} + } \ No newline at end of file diff --git a/src/transport.cpp b/src/transport.cpp index 5f622ef7..108b6438 100644 --- a/src/transport.cpp +++ b/src/transport.cpp @@ -21,6 +21,7 @@ #include "transport/transport.h" #include #include "transport/storagebackend.h" +#include "transport/factory.h" #include "discoinforesponder.h" #include "discoitemsresponder.h" #include "rosterresponder.h" @@ -42,12 +43,13 @@ class MyUserRegistry : public Swift::UserRegistry { mutable std::map users; }; -Component::Component(Swift::EventLoop *loop, Config *config) { +Component::Component(Swift::EventLoop *loop, Config *config, Factory *factory) { m_component = NULL; m_userRegistry = NULL; m_server = NULL; m_reconnectCount = 0; m_config = config; + m_factory = factory; m_jid = Swift::JID(CONFIG_STRING(m_config, "service.jid")); diff --git a/src/usermanager.cpp b/src/usermanager.cpp index e783e43d..9511f3df 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -22,6 +22,7 @@ #include "transport/user.h" #include "transport/transport.h" #include "transport/storagebackend.h" +#include "transport/conversationmanager.h" namespace Transport { @@ -32,6 +33,7 @@ UserManager::UserManager(Component *component, StorageBackend *storageBackend) { m_storageBackend = storageBackend; component->onUserPresenceReceived.connect(bind(&UserManager::handlePresence, this, _1)); + m_component->getStanzaChannel()->onMessageReceived.connect(bind(&UserManager::handleMessageReceived, this, _1)); // component->onDiscoInfoResponse.connect(bind(&UserManager::handleDiscoInfoResponse, this, _1, _2, _3)); } @@ -144,4 +146,13 @@ void UserManager::handlePresence(Swift::Presence::ref presence) { } } +void UserManager::handleMessageReceived(Swift::Message::ref message) { + User *user = getUser(message->getFrom().toBare().toString()); + if (!user ){ + return; + } + + user->getConversationManager()->handleMessageReceived(message); +} + }