Changeset - 10eea7ab77a5
[Not reviewed]
0 2 0
dexterlb - 8 years ago 2017-12-26 21:38:25
dexterlb@qtrp.org
wrap incoming images in x:oob tag
2 files changed with 33 insertions and 0 deletions:
0 comments (0 inline, 0 general)
include/transport/NetworkPluginServer.h
Show inline comments
 
@@ -21,48 +21,49 @@
 
#pragma once
 

	
 
#include "transport/FileTransferManager.h"
 

	
 
#include <time.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 "Swiften/Elements/Message.h"
 
#include "Swiften/Elements/Presence.h"
 
#include "Swiften/Elements/IQ.h"
 
#include "Swiften/Network/Timer.h"
 
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
 
#include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h"
 
#include "Swiften/Parser/XMPPParser.h"
 
#include "Swiften/Parser/XMPPParserClient.h"
 
#include "Swiften/Serializer/XMPPSerializer.h"
 
#include "Swiften/SwiftenCompat.h"
 
#include <Swiften/Version.h>
 
#include <Swiften/FileTransfer/FileTransfer.h>
 
#include "transport/protocol.pb.h"
 
#define HAVE_SWIFTEN_3  (SWIFTEN_VERSION >= 0x030000)
 

	
 
#define NETWORK_PLUGIN_API_VERSION (1)
 

	
 
namespace Transport {
 

	
 
class UserManager;
 
class User;
 
class Component;
 
class Buddy;
 
class LocalBuddy;
 
class Config;
 
class NetworkConversation;
 
class VCardResponder;
 
class RosterResponder;
 
class BlockResponder;
 
class DummyReadBytestream;
 
class AdminInterface;
 
class FileTransferManager;
 
class FileTransfer;
 

	
 
class NetworkPluginServer : Swift::XMPPParserClient {
 
	public:
 
		struct Backend {
 
@@ -157,48 +158,50 @@ class NetworkPluginServer : Swift::XMPPParserClient {
 
		void handleFTRejected(User *user, const std::string &buddyName, const std::string &fileName, unsigned long size);
 
		void handleFTDataNeeded(Backend *b, unsigned long ftid);
 

	
 
		void handlePIDTerminated(unsigned long pid);
 
	private:
 
		void send(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Connection> &, const std::string &data);
 

	
 
		void pingTimeout();
 
		void sendPing(Backend *c);
 
		void sendAPIVersion(Backend *c);
 
		Backend *getFreeClient(bool acceptUsers = true, bool longRun = false, bool check = false);
 
		void connectWaitingUsers();
 
		void loginDelayFinished();
 
		void handleRawIQReceived(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::IQ> iq);
 
		void handleRawPresenceReceived(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Presence> presence);
 

	
 
		void handleStreamStart(const Swift::ProtocolHeader&) {}
 
#if HAVE_SWIFTEN_3
 
		void handleElement(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::ToplevelElement> element);
 
#else
 
		void handleElement(SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Element> element);
 
#endif
 
		void handleStreamEnd() {}
 

	
 
		void wrapIncomingImage(Swift::Message* msg, const pbnetwork::ConversationMessage& payload);
 

	
 
		UserManager *m_userManager;
 
		VCardResponder *m_vcardResponder;
 
		RosterResponder *m_rosterResponder;
 
		BlockResponder *m_blockResponder;
 
		Config *m_config;
 
		SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::ConnectionServer> m_server;
 
		std::list<Backend *>  m_clients;
 
		std::vector<unsigned long> m_pids;
 
		Swift::Timer::ref m_pingTimer;
 
		Swift::Timer::ref m_collectTimer;
 
		Swift::Timer::ref m_loginTimer;
 
		Component *m_component;
 
		std::list<User *> m_waitingUsers;
 
		bool m_isNextLongRun;
 
		std::map<unsigned long, FileTransferManager::Transfer> m_filetransfers;
 
		FileTransferManager *m_ftManager;
 
		std::vector<std::string> m_crashedBackends;
 
		AdminInterface *m_adminInterface;
 
		bool m_startingBackend;
 
		time_t m_lastLogin;
 
		Swift::XMPPParser *m_xmppParser;
 
		Swift::FullPayloadParserFactoryCollection m_collection;
 
		Swift::XMPPSerializer *m_serializer;
 
		Swift::FullPayloadSerializerCollection m_collection2;
libtransport/NetworkPluginServer.cpp
Show inline comments
 
@@ -25,50 +25,52 @@
 
#include "transport/UserManager.h"
 
#include "transport/ConversationManager.h"
 
#include "transport/LocalBuddy.h"
 
#include "transport/Config.h"
 
#include "transport/Conversation.h"
 
#include "transport/MemoryReadBytestream.h"
 
#include "transport/Logging.h"
 
#include "transport/AdminInterface.h"
 
#include "transport/Frontend.h"
 
#include "transport/Factory.h"
 
#include "transport/UserRegistry.h"
 
#include "transport/protocol.pb.h"
 
#include "transport/Util.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 "Swiften/Elements/RawXMLPayload.h"
 

	
 
#include "boost/date_time/posix_time/posix_time.hpp"
 
#include <boost/regex.hpp>
 

	
 
#include "transport/utf8.h"
 

	
 
#include <Swiften/FileTransfer/ReadBytestream.h>
 
#include <Swiften/Elements/StreamInitiationFileInfo.h>
 

	
 
#ifdef _WIN32
 
#include "windows.h"
 
#include <stdint.h>
 
#else
 
#include "sys/wait.h"
 
#include "sys/signal.h"
 
#include <sys/types.h>
 
#include <signal.h>
 
#include "popt.h"
 
#endif
 

	
 
using namespace Transport::Util;
 

	
 
namespace Transport {
 

	
 
static unsigned long backend_id;
 
static unsigned long bytestream_id;
 

	
 
@@ -665,48 +667,50 @@ void NetworkPluginServer::handleConvMessagePayload(const std::string &data, bool
 

	
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 

	
 
	User *user = m_userManager->getUser(payload.username());
 
	if (!user) {
 
		LOG4CXX_ERROR(logger, "handleConvMessagePayload: unknown username " << payload.username());
 
		return;
 
	}
 

	
 
	// Message from legacy network triggers network acticity
 
	user->updateLastActivity();
 

	
 
	// Set proper body.
 
	SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Message> msg(new Swift::Message());
 
	if (subject) {
 
		msg->setSubject(payload.message());
 
	}
 
	else {
 
		msg->setBody(payload.message());
 
	}
 

	
 
    wrapIncomingImage(msg.get(), payload);
 

	
 
	if (payload.headline()) {
 
		msg->setType(Swift::Message::Headline);
 
	}
 

	
 
	// Add xhtml-im payload.
 
	if (CONFIG_BOOL(m_config, "service.enable_xhtml") && !payload.xhtml().empty()) {
 
		msg->addPayload(SWIFTEN_SHRPTR_NAMESPACE::make_shared<Swift::XHTMLIMPayload>(payload.xhtml()));
 
	}
 

	
 
	if (!payload.timestamp().empty()) {
 
		boost::posix_time::ptime timestamp = boost::posix_time::from_iso_string(payload.timestamp());
 
		SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::Delay> delay(SWIFTEN_SHRPTR_NAMESPACE::make_shared<Swift::Delay>());
 
		delay->setStamp(timestamp);
 
		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,
 
	// but this user is not in any room, so it's OK to just reject this message
 
	if (!conv && !payload.nickname().empty()) {
 
		LOG4CXX_WARN(logger, "handleConvMessagePayload: No conversation with name " << payload.buddyname());
 
		return;
 
	}
 
@@ -1768,48 +1772,74 @@ void NetworkPluginServer::handleMessageReceived(NetworkConversation *conv, SWIFT
 
void NetworkPluginServer::handleBuddyRemoved(Buddy *b) {
 
	User *user = b->getRosterManager()->getUser();
 

	
 
	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_REMOVED);
 

	
 
	Backend *c = (Backend *) user->getData();
 
	if (!c) {
 
		return;
 
	}
 
	send(c->connection, message);
 
}
 

	
 
void NetworkPluginServer::wrapIncomingImage(Swift::Message* msg, const pbnetwork::ConversationMessage& payload) {
 
    static boost::regex image_expr{"<img src=[\"']([^\"']+)[\"'].*>"};
 

	
 
    if (payload.xhtml().find("<img") != std::string::npos) {
 
        boost::smatch match;
 

	
 
        if (boost::regex_search(payload.xhtml(), match, image_expr)) {
 
            const std::string& image_url = match[1];
 

	
 
            SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::RawXMLPayload>
 
                oob_payload(new Swift::RawXMLPayload(
 
                    "<x xmlns='jabber:x:oob'><url>"
 
                    + image_url
 
                    + "</url>"
 
                    + "</x>"
 
                ));
 
                // todo: add the payload itself as a caption
 

	
 
            msg->addPayload(oob_payload);
 
            msg->setBody(image_url);
 
        } else {
 
            LOG4CXX_WARN(logger, "xhtml seems to contain an image, but doesn't match: " + payload.xhtml())
 
        }
 
    }
 
}
 

	
 
void NetworkPluginServer::handleBuddyUpdated(Buddy *b, const Swift::RosterItemPayload &item) {
 
	User *user = b->getRosterManager()->getUser();
 

	
 
	dynamic_cast<LocalBuddy *>(b)->setAlias(item.getName());
 
	dynamic_cast<LocalBuddy *>(b)->setGroups(item.getGroups());
 

	
 
	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;
 
	}
0 comments (0 inline, 0 general)