From af61db1e108d17afcf84a97492dd6b79426688ec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Thu, 21 Oct 2010 22:21:45 +0200
Subject: Make sure Component always sets 'from' on outgoing IQ stanzas.


diff --git a/Swiften/Component/CoreComponent.cpp b/Swiften/Component/CoreComponent.cpp
index 2f0752a..c9d9051 100644
--- a/Swiften/Component/CoreComponent.cpp
+++ b/Swiften/Component/CoreComponent.cpp
@@ -30,6 +30,7 @@ CoreComponent::CoreComponent(const JID& jid, const String& secret) : jid_(jid),
 	stanzaChannel_->onAvailableChanged.connect(boost::bind(&CoreComponent::handleStanzaChannelAvailableChanged, this, _1));
 
 	iqRouter_ = new IQRouter(stanzaChannel_);
+	iqRouter_->setFrom(jid);
 	connectionFactory_ = new BoostConnectionFactory(&MainBoostIOServiceThread::getInstance().getIOService());
 	timerFactory_ = new BoostTimerFactory(&MainBoostIOServiceThread::getInstance().getIOService());
 	tlsLayerFactory_ = new NullTLSLayerFactory();
diff --git a/Swiften/Queries/IQRouter.cpp b/Swiften/Queries/IQRouter.cpp
index f40d248..a1689e9 100644
--- a/Swiften/Queries/IQRouter.cpp
+++ b/Swiften/Queries/IQRouter.cpp
@@ -40,7 +40,7 @@ void IQRouter::handleIQ(boost::shared_ptr<IQ> iq) {
 		}
 	}
 	if (!handled && (iq->getType() == IQ::Get || iq->getType() == IQ::Set) ) {
-		channel_->sendIQ(IQ::createError(iq->getFrom(), iq->getID(), ErrorPayload::FeatureNotImplemented, ErrorPayload::Cancel));
+		sendIQ(IQ::createError(iq->getFrom(), iq->getID(), ErrorPayload::FeatureNotImplemented, ErrorPayload::Cancel));
 	}
 
 	processPendingRemoves();
@@ -77,6 +77,9 @@ void IQRouter::removeHandler(boost::shared_ptr<IQHandler> handler) {
 }
 
 void IQRouter::sendIQ(boost::shared_ptr<IQ> iq) {
+	if (from_.isValid()) {
+		iq->setFrom(from_);
+	}
 	channel_->sendIQ(iq);
 }
 
diff --git a/Swiften/Queries/IQRouter.h b/Swiften/Queries/IQRouter.h
index eab2848..42fa6e9 100644
--- a/Swiften/Queries/IQRouter.h
+++ b/Swiften/Queries/IQRouter.h
@@ -4,8 +4,7 @@
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
 
-#ifndef SWIFTEN_IQRouter_H
-#define SWIFTEN_IQRouter_H
+#pragma once
 
 #include <boost/shared_ptr.hpp>
 #include <vector>
@@ -22,11 +21,29 @@ namespace Swift {
 			IQRouter(IQChannel* channel);
 			~IQRouter();
 
+			/**
+			 * Sets the 'from' JID for all outgoing IQ stanzas.
+			 *
+			 * By default, IQRouter does not add a from to IQ stanzas, since
+			 * this is automatically added by the server. This overrides this
+			 * default behavior, which is necessary for e.g. components.
+			 */
+			void setFrom(const JID& from) {
+				from_ = from;
+			}
+
 			void addHandler(IQHandler* handler);
 			void removeHandler(IQHandler* handler);
 			void addHandler(boost::shared_ptr<IQHandler> handler);
 			void removeHandler(boost::shared_ptr<IQHandler> handler);
 
+			/**
+			 * Sends an IQ stanza.
+			 *
+			 * If a JID was specified using setFrom, the JID will
+			 * be set as the 'from' address on iq before sending
+			 * it.
+			 */
 			void sendIQ(boost::shared_ptr<IQ> iq);
 			String getNewIQID();
 			
@@ -38,10 +55,9 @@ namespace Swift {
 
 		private:
 			IQChannel* channel_;
+			JID from_;
 			std::vector< boost::shared_ptr<IQHandler> > handlers_;
 			std::vector< boost::shared_ptr<IQHandler> > queuedRemoves_;
 			bool queueRemoves_;
 	};
 }
-
-#endif
diff --git a/Swiften/Queries/UnitTest/IQRouterTest.cpp b/Swiften/Queries/UnitTest/IQRouterTest.cpp
index 919711e..2d6b2cb 100644
--- a/Swiften/Queries/UnitTest/IQRouterTest.cpp
+++ b/Swiften/Queries/UnitTest/IQRouterTest.cpp
@@ -24,6 +24,9 @@ class IQRouterTest : public CppUnit::TestFixture
 		CPPUNIT_TEST(testHandleIQ_SuccesfulHandlerLast);
 		CPPUNIT_TEST(testHandleIQ_NoSuccesfulHandler);
 		CPPUNIT_TEST(testHandleIQ_HandlerRemovedDuringHandle);
+		CPPUNIT_TEST(testSendIQ_WithFrom);
+		CPPUNIT_TEST(testSendIQ_WithoutFrom);
+		CPPUNIT_TEST(testHandleIQ_WithFrom);
 		CPPUNIT_TEST_SUITE_END();
 
 	public:
@@ -109,6 +112,33 @@ class IQRouterTest : public CppUnit::TestFixture
 			CPPUNIT_ASSERT_EQUAL(2, handler2.called);
 		}
 
+		void testSendIQ_WithFrom() {
+			IQRouter testling(channel_);
+			testling.setFrom(JID("foo@bar.com/baz"));
+
+			testling.sendIQ(boost::shared_ptr<IQ>(new IQ()));
+
+			CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), channel_->iqs_[0]->getFrom());
+		}
+
+		void testSendIQ_WithoutFrom() {
+			IQRouter testling(channel_);
+
+			testling.sendIQ(boost::shared_ptr<IQ>(new IQ()));
+
+			CPPUNIT_ASSERT_EQUAL(JID(), channel_->iqs_[0]->getFrom());
+		}
+
+		void testHandleIQ_WithFrom() {
+			IQRouter testling(channel_);
+			testling.setFrom(JID("foo@bar.com/baz"));
+			DummyIQHandler handler(false, &testling);
+
+			channel_->onIQReceived(boost::shared_ptr<IQ>(new IQ()));
+
+			CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), channel_->iqs_[0]->getFrom());
+		}
+
 	private:
 		struct DummyIQHandler : public IQHandler {
 			DummyIQHandler(bool handle, IQRouter* router) : handle(handle), router(router), called(0) {
-- 
cgit v0.10.2-6-g49f6