/* Copyright (C) 2015 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. 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. * * 0 A.D. 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 0 A.D. If not, see . */ #include "precompiled.h" #include "glooxwrapper.h" #include #include #include #include #if OS_WIN const std::string gloox::EmptyString = ""; #endif void* glooxwrapper::glooxwrapper_alloc(size_t size) { void* p = malloc(size); if (p == NULL) throw std::bad_alloc(); return p; } void glooxwrapper::glooxwrapper_free(void* p) { free(p); } namespace glooxwrapper { class ConnectionListenerWrapper : public gloox::ConnectionListener { glooxwrapper::ConnectionListener* m_Wrapped; public: ConnectionListenerWrapper(glooxwrapper::ConnectionListener* wrapped) : m_Wrapped(wrapped) {} virtual void onConnect() { m_Wrapped->onConnect(); } virtual void onDisconnect(gloox::ConnectionError e) { m_Wrapped->onDisconnect(e); } virtual bool onTLSConnect(const gloox::CertInfo& info) { glooxwrapper::CertInfo infoWrapped; #define COPY(n) infoWrapped.n = info.n COPY(status); COPY(chain); COPY(issuer); COPY(server); COPY(date_from); COPY(date_to); COPY(protocol); COPY(cipher); COPY(mac); COPY(compression); #undef COPY return m_Wrapped->onTLSConnect(infoWrapped); } }; class IqHandlerWrapper : public gloox::IqHandler { glooxwrapper::IqHandler* m_Wrapped; public: IqHandlerWrapper(glooxwrapper::IqHandler* wrapped) : m_Wrapped(wrapped) {} virtual bool handleIq(const gloox::IQ& iq) { glooxwrapper::IQ iqWrapper(iq); return m_Wrapped->handleIq(iqWrapper); } virtual void handleIqID(const gloox::IQ& iq, int context) { glooxwrapper::IQ iqWrapper(iq); m_Wrapped->handleIqID(iqWrapper, context); } }; class MessageHandlerWrapper : public gloox::MessageHandler { glooxwrapper::MessageHandler* m_Wrapped; public: MessageHandlerWrapper(glooxwrapper::MessageHandler* wrapped) : m_Wrapped(wrapped) {} virtual void handleMessage(const gloox::Message& msg, gloox::MessageSession* UNUSED(session)) { /* MessageSession not supported */ glooxwrapper::Message msgWrapper(const_cast(&msg), false); m_Wrapped->handleMessage(msgWrapper, NULL); } }; class MUCRoomHandlerWrapper : public gloox::MUCRoomHandler { glooxwrapper::MUCRoomHandler* m_Wrapped; public: MUCRoomHandlerWrapper(glooxwrapper::MUCRoomHandler* wrapped) : m_Wrapped(wrapped) {} virtual ~MUCRoomHandlerWrapper() {} virtual void handleMUCParticipantPresence(gloox::MUCRoom* UNUSED(room), const gloox::MUCRoomParticipant participant, const gloox::Presence& presence) { glooxwrapper::MUCRoomParticipant part; glooxwrapper::JID nick(*participant.nick); glooxwrapper::JID jid(*participant.jid); glooxwrapper::JID actor(*participant.actor); glooxwrapper::JID alternate(*participant.alternate); part.nick = participant.nick ? &nick : NULL; part.affiliation = participant.affiliation; part.role = participant.role; part.jid = participant.jid ? &jid : NULL; part.flags = participant.flags; part.reason = participant.reason; part.actor = participant.actor ? &actor : NULL; part.newNick = participant.newNick; part.status = participant.status; part.alternate = participant.alternate ? &alternate : NULL; /* MUCRoom not supported */ m_Wrapped->handleMUCParticipantPresence(NULL, part, glooxwrapper::Presence(presence.presence())); /* gloox 1.0 leaks some JIDs (fixed in 1.0.1), so clean them up */ #if GLOOXVERSION == 0x10000 delete participant.jid; delete participant.actor; delete participant.alternate; #endif } virtual void handleMUCMessage(gloox::MUCRoom* UNUSED(room), const gloox::Message& msg, bool priv) { glooxwrapper::Message msgWrapper(const_cast(&msg), false); /* MUCRoom not supported */ m_Wrapped->handleMUCMessage(NULL, msgWrapper, priv); } virtual bool handleMUCRoomCreation(gloox::MUCRoom* UNUSED(room)) { /* Not supported */ return false; } virtual void handleMUCSubject(gloox::MUCRoom* UNUSED(room), const std::string& nick, const std::string& subject) { /* MUCRoom not supported */ m_Wrapped->handleMUCSubject(NULL, nick, subject); } virtual void handleMUCInviteDecline(gloox::MUCRoom* UNUSED(room), const gloox::JID& UNUSED(invitee), const std::string& UNUSED(reason)) { /* Not supported */ } virtual void handleMUCError(gloox::MUCRoom* UNUSED(room), gloox::StanzaError error) { /* MUCRoom not supported */ m_Wrapped->handleMUCError(NULL, error); } virtual void handleMUCInfo(gloox::MUCRoom* UNUSED(room), int UNUSED(features), const std::string& UNUSED(name), const gloox::DataForm* UNUSED(infoForm)) { /* Not supported */ } virtual void handleMUCItems(gloox::MUCRoom* UNUSED(room), const gloox::Disco::ItemList& UNUSED(items)) { /* Not supported */ } }; class RegistrationHandlerWrapper : public gloox::RegistrationHandler { glooxwrapper::RegistrationHandler* m_Wrapped; public: RegistrationHandlerWrapper(glooxwrapper::RegistrationHandler* wrapped) : m_Wrapped(wrapped) {} virtual void handleRegistrationFields(const gloox::JID& from, int fields, std::string instructions) { glooxwrapper::JID fromWrapped(from); m_Wrapped->handleRegistrationFields(fromWrapped, fields, instructions); } virtual void handleAlreadyRegistered(const gloox::JID& from) { glooxwrapper::JID fromWrapped(from); m_Wrapped->handleAlreadyRegistered(fromWrapped); } virtual void handleRegistrationResult(const gloox::JID& from, gloox::RegistrationResult regResult) { glooxwrapper::JID fromWrapped(from); m_Wrapped->handleRegistrationResult(fromWrapped, regResult); } virtual void handleDataForm(const gloox::JID& from, const gloox::DataForm& UNUSED(form)) { glooxwrapper::JID fromWrapped(from); /* DataForm not supported */ m_Wrapped->handleDataForm(fromWrapped, *(glooxwrapper::DataForm*)NULL); } virtual void handleOOB(const gloox::JID& from, const gloox::OOB& UNUSED(oob)) { glooxwrapper::JID fromWrapped(from); /* OOB not supported */ m_Wrapped->handleOOB(fromWrapped, *(glooxwrapper::OOB*)NULL); } }; class StanzaExtensionWrapper : public gloox::StanzaExtension { public: const glooxwrapper::StanzaExtension* m_Wrapped; bool m_Owned; std::string m_FilterString; StanzaExtensionWrapper(const glooxwrapper::StanzaExtension* wrapped, bool owned) : gloox::StanzaExtension(wrapped->extensionType()), m_Wrapped(wrapped), m_Owned(owned) { m_FilterString = m_Wrapped->filterString().to_string(); } ~StanzaExtensionWrapper() { if (m_Owned) delete m_Wrapped; } virtual const std::string& filterString() const { return m_FilterString; } virtual gloox::StanzaExtension* newInstance(const gloox::Tag* tag) const { glooxwrapper::Tag* tagWrapper = glooxwrapper::Tag::allocate(const_cast(tag), false); gloox::StanzaExtension* ret = new StanzaExtensionWrapper(m_Wrapped->newInstance(tagWrapper), true); glooxwrapper::Tag::free(tagWrapper); return ret; } virtual gloox::Tag* tag() const { glooxwrapper::Tag* wrapper = m_Wrapped->tag(); gloox::Tag* ret = wrapper->stealWrapped(); glooxwrapper::Tag::free(wrapper); return ret; } virtual gloox::StanzaExtension* clone() const { return new StanzaExtensionWrapper(m_Wrapped->clone(), true); } }; class ClientImpl { public: // List of registered callback wrappers, to get deleted when Client is deleted std::list > m_ConnectionListeners; std::list > m_MessageHandlers; std::list > m_IqHandlers; }; } // namespace glooxwrapper glooxwrapper::Client::Client(const string& server) { m_Wrapped = new gloox::Client(server.to_string()); m_DiscoWrapper = new glooxwrapper::Disco(m_Wrapped->disco()); m_Impl = new ClientImpl; } glooxwrapper::Client::Client(const JID& jid, const string& password, int port) { m_Wrapped = new gloox::Client(jid.getWrapped(), password.to_string(), port); m_DiscoWrapper = new glooxwrapper::Disco(m_Wrapped->disco()); m_Impl = new ClientImpl; } glooxwrapper::Client::~Client() { delete m_Wrapped; delete m_DiscoWrapper; delete m_Impl; } bool glooxwrapper::Client::connect(bool block) { return m_Wrapped->connect(block); } gloox::ConnectionError glooxwrapper::Client::recv(int timeout) { return m_Wrapped->recv(timeout); } void glooxwrapper::Client::send(const IQ& iq) { m_Wrapped->send(iq.getWrapped()); } void glooxwrapper::Client::setTls(gloox::TLSPolicy tls) { m_Wrapped->setTls(tls); } void glooxwrapper::Client::setCompression(bool compression) { m_Wrapped->setCompression(compression); } void glooxwrapper::Client::setSASLMechanisms(int mechanisms) { m_Wrapped->setSASLMechanisms(mechanisms); } void glooxwrapper::Client::disconnect() { m_Wrapped->disconnect(); } void glooxwrapper::Client::registerStanzaExtension(glooxwrapper::StanzaExtension* ext) { gloox::StanzaExtension* stanza = new StanzaExtensionWrapper(ext, true); m_Wrapped->registerStanzaExtension(stanza); } void glooxwrapper::Client::registerConnectionListener(glooxwrapper::ConnectionListener* hnd) { gloox::ConnectionListener* listener = new ConnectionListenerWrapper(hnd); m_Wrapped->registerConnectionListener(listener); m_Impl->m_ConnectionListeners.push_back(shared_ptr(listener)); } void glooxwrapper::Client::registerMessageHandler(glooxwrapper::MessageHandler* hnd) { gloox::MessageHandler* handler = new MessageHandlerWrapper(hnd); m_Wrapped->registerMessageHandler(handler); m_Impl->m_MessageHandlers.push_back(shared_ptr(handler)); } void glooxwrapper::Client::registerIqHandler(glooxwrapper::IqHandler* ih, int exttype) { gloox::IqHandler* handler = new IqHandlerWrapper(ih); m_Wrapped->registerIqHandler(handler, exttype); m_Impl->m_IqHandlers.push_back(shared_ptr(handler)); } bool glooxwrapper::Client::removePresenceExtension(int type) { return m_Wrapped->removePresenceExtension(type); } void glooxwrapper::Client::setPresence(gloox::Presence::PresenceType pres, int priority, const string& status) { m_Wrapped->setPresence(pres, priority, status.to_string()); } glooxwrapper::DelayedDelivery::DelayedDelivery(const gloox::DelayedDelivery* wrapped) { m_Wrapped = wrapped; } const glooxwrapper::string glooxwrapper::DelayedDelivery::stamp() const { return m_Wrapped->stamp(); } glooxwrapper::Disco::Disco(gloox::Disco* wrapped) { m_Wrapped = wrapped; } void glooxwrapper::Disco::setVersion(const string& name, const string& version, const string& os) { m_Wrapped->setVersion(name.to_string(), version.to_string(), os.to_string()); } void glooxwrapper::Disco::setIdentity(const string& category, const string& type, const string& name) { m_Wrapped->setIdentity(category.to_string(), type.to_string(), name.to_string()); } glooxwrapper::IQ::IQ(gloox::IQ::IqType type, const JID& to, const string& id) { m_Wrapped = new gloox::IQ(type, to.getWrapped(), id.to_string()); m_Owned = true; } glooxwrapper::IQ::~IQ() { if (m_Owned) delete m_Wrapped; } void glooxwrapper::IQ::addExtension(const glooxwrapper::StanzaExtension* se) { m_Wrapped->addExtension(new StanzaExtensionWrapper(se, true)); } const glooxwrapper::StanzaExtension* glooxwrapper::IQ::findExtension(int type) const { const gloox::StanzaExtension* ext = m_Wrapped->findExtension(type); if (!ext) return NULL; return static_cast(ext)->m_Wrapped; } gloox::StanzaError glooxwrapper::IQ::error_error() const { return m_Wrapped->error()->error(); } glooxwrapper::Tag* glooxwrapper::IQ::tag() const { return Tag::allocate(m_Wrapped->tag(), true); } gloox::IQ::IqType glooxwrapper::IQ::subtype() const { return m_Wrapped->subtype(); } glooxwrapper::JID::JID() { m_Wrapped = new gloox::JID(); m_Owned = true; } glooxwrapper::JID::JID(const glooxwrapper::string& jid) { m_Wrapped = new gloox::JID(jid.to_string()); m_Owned = true; } void glooxwrapper::JID::init(const char* data, size_t len) { m_Wrapped = new gloox::JID(std::string(data, data+len)); m_Owned = true; } glooxwrapper::JID::~JID() { if (m_Owned) delete m_Wrapped; } glooxwrapper::string glooxwrapper::JID::username() const { return m_Wrapped->username(); } glooxwrapper::string glooxwrapper::JID::resource() const { return m_Wrapped->resource(); }; glooxwrapper::Message::Message(gloox::Message* wrapped, bool owned) : m_Wrapped(wrapped), m_Owned(owned) { m_From = new glooxwrapper::JID(m_Wrapped->from()); } glooxwrapper::Message::~Message() { if (m_Owned) delete m_Wrapped; delete m_From; } gloox::Message::MessageType glooxwrapper::Message::subtype() const { return m_Wrapped->subtype(); } const glooxwrapper::JID& glooxwrapper::Message::from() const { return *m_From; } glooxwrapper::string glooxwrapper::Message::body() const { return m_Wrapped->body(); } glooxwrapper::string glooxwrapper::Message::subject(const string& lang) const { return m_Wrapped->subject(lang.to_string()); } glooxwrapper::string glooxwrapper::Message::thread() const { return m_Wrapped->thread(); } const glooxwrapper::DelayedDelivery* glooxwrapper::Message::when() const { const gloox::DelayedDelivery* wrapped = m_Wrapped->when(); if (wrapped == 0) return 0; return new glooxwrapper::DelayedDelivery(wrapped); } glooxwrapper::MUCRoom::MUCRoom(Client* parent, const JID& nick, MUCRoomHandler* mrh, MUCRoomConfigHandler* UNUSED(mrch)) { m_HandlerWrapper = new MUCRoomHandlerWrapper(mrh); m_Wrapped = new gloox::MUCRoom(parent ? parent->getWrapped() : NULL, nick.getWrapped(), m_HandlerWrapper); } glooxwrapper::MUCRoom::~MUCRoom() { delete m_Wrapped; delete m_HandlerWrapper; } const glooxwrapper::string glooxwrapper::MUCRoom::nick() const { return m_Wrapped->nick(); } void glooxwrapper::MUCRoom::join(gloox::Presence::PresenceType type, const string& status, int priority) { m_Wrapped->join(type, status.to_string(), priority); } void glooxwrapper::MUCRoom::leave(const string& msg) { m_Wrapped->leave(msg.to_string()); } void glooxwrapper::MUCRoom::send(const string& message) { m_Wrapped->send(message.to_string()); } void glooxwrapper::MUCRoom::setNick(const string& nick) { m_Wrapped->setNick(nick.to_string()); } void glooxwrapper::MUCRoom::setPresence(gloox::Presence::PresenceType presence, const string& msg) { m_Wrapped->setPresence(presence, msg.to_string()); } void glooxwrapper::MUCRoom::setRequestHistory(int value, gloox::MUCRoom::HistoryRequestType type) { m_Wrapped->setRequestHistory(value, type); } void glooxwrapper::MUCRoom::kick(const string& nick, const string& reason) { m_Wrapped->kick(nick.to_string(), reason.to_string()); } void glooxwrapper::MUCRoom::ban(const string& nick, const string& reason) { m_Wrapped->ban(nick.to_string(), reason.to_string()); } glooxwrapper::Registration::Registration(Client* parent) { m_Wrapped = new gloox::Registration(parent->getWrapped()); } glooxwrapper::Registration::~Registration() { delete m_Wrapped; } void glooxwrapper::Registration::fetchRegistrationFields() { m_Wrapped->fetchRegistrationFields(); } bool glooxwrapper::Registration::createAccount(int fields, const glooxwrapper::RegistrationFields& values) { gloox::RegistrationFields valuesUnwrapped; #define COPY(n) valuesUnwrapped.n = values.n.to_string() COPY(username); COPY(nick); COPY(password); COPY(name); COPY(first); COPY(last); COPY(email); COPY(address); COPY(city); COPY(state); COPY(zip); COPY(phone); COPY(url); COPY(date); COPY(misc); COPY(text); #undef COPY return m_Wrapped->createAccount(fields, valuesUnwrapped); } void glooxwrapper::Registration::registerRegistrationHandler(RegistrationHandler* rh) { gloox::RegistrationHandler* handler = new RegistrationHandlerWrapper(rh); m_Wrapped->registerRegistrationHandler(handler); m_RegistrationHandlers.push_back(shared_ptr(handler)); } glooxwrapper::Tag::Tag(const string& name) { m_Wrapped = new gloox::Tag(name.to_string()); m_Owned = true; } glooxwrapper::Tag::Tag(const string& name, const string& cdata) { m_Wrapped = new gloox::Tag(name.to_string(), cdata.to_string()); m_Owned = true; } glooxwrapper::Tag::~Tag() { if (m_Owned) delete m_Wrapped; } glooxwrapper::Tag* glooxwrapper::Tag::allocate(const string& name) { return new glooxwrapper::Tag(name); } glooxwrapper::Tag* glooxwrapper::Tag::allocate(const string& name, const string& cdata) { return new glooxwrapper::Tag(name, cdata); } glooxwrapper::Tag* glooxwrapper::Tag::allocate(gloox::Tag* wrapped, bool owned) { return new glooxwrapper::Tag(wrapped, owned); } void glooxwrapper::Tag::free(const glooxwrapper::Tag* tag) { delete tag; } bool glooxwrapper::Tag::addAttribute(const string& name, const string& value) { return m_Wrapped->addAttribute(name.to_string(), value.to_string()); } glooxwrapper::string glooxwrapper::Tag::findAttribute(const string& name) const { return m_Wrapped->findAttribute(name.to_string()); } glooxwrapper::Tag* glooxwrapper::Tag::clone() const { return new glooxwrapper::Tag(m_Wrapped->clone(), true); } glooxwrapper::string glooxwrapper::Tag::xmlns() const { return m_Wrapped->xmlns(); } bool glooxwrapper::Tag::setXmlns(const string& xmlns) { return m_Wrapped->setXmlns(xmlns.to_string()); } glooxwrapper::string glooxwrapper::Tag::xml() const { return m_Wrapped->xml(); } void glooxwrapper::Tag::addChild(Tag* child) { m_Wrapped->addChild(child->stealWrapped()); Tag::free(child); } glooxwrapper::string glooxwrapper::Tag::name() const { return m_Wrapped->name(); } glooxwrapper::string glooxwrapper::Tag::cdata() const { return m_Wrapped->cdata(); } const glooxwrapper::Tag* glooxwrapper::Tag::findTag_clone(const string& expression) const { const gloox::Tag* tag = m_Wrapped->findTag(expression.to_string()); if (!tag) return NULL; return new glooxwrapper::Tag(const_cast(tag), false); } glooxwrapper::ConstTagList glooxwrapper::Tag::findTagList_clone(const string& expression) const { glooxwrapper::ConstTagList tagListWrapper; for (const gloox::Tag* const& t : m_Wrapped->findTagList(expression.to_string())) tagListWrapper.push_back(new glooxwrapper::Tag(const_cast(t), false)); return tagListWrapper; }