From 6ce9e6bfa735ebeb577a308a1dd51a3424f5f0fe Mon Sep 17 00:00:00 2001
From: Richard Maudsley <richard.maudsley@isode.com>
Date: Mon, 19 May 2014 20:12:23 +0200
Subject: Check if contact supports file transfer before sending

Change-Id: Iadb580ad8b3f258d49b7c1b8713f0f92009e022e

diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index 10cf54b..65d65a6 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -10,21 +10,22 @@
 #include <boost/smart_ptr/make_shared.hpp>
 #include <stdio.h>
 
-#include <Swiften/Base/format.h>
-#include <Swiften/Base/Algorithm.h>
 #include <Swiften/Avatars/AvatarManager.h>
+#include <Swiften/Base/Algorithm.h>
+#include <Swiften/Base/DateTime.h>
+#include <Swiften/Base/foreach.h>
+#include <Swiften/Base/format.h>
+#include <Swiften/Base/Log.h>
 #include <Swiften/Chat/ChatStateNotifier.h>
 #include <Swiften/Chat/ChatStateTracker.h>
-#include <Swiften/Client/StanzaChannel.h>
+#include <Swiften/Client/ClientBlockListManager.h>
 #include <Swiften/Client/NickResolver.h>
+#include <Swiften/Client/StanzaChannel.h>
 #include <Swiften/Disco/EntityCapsProvider.h>
-#include <Swiften/Base/foreach.h>
-#include <Swiften/Base/DateTime.h>
 #include <Swiften/Elements/DeliveryReceipt.h>
 #include <Swiften/Elements/DeliveryReceiptRequest.h>
 #include <Swiften/Elements/Idle.h>
-#include <Swiften/Base/Log.h>
-#include <Swiften/Client/ClientBlockListManager.h>
+#include <Swiften/FileTransfer/FileTransferManager.h>
 
 #include <Swift/Controllers/Intl.h>
 #include <Swift/Controllers/UIInterfaces/ChatWindowFactory.h>
@@ -135,6 +136,11 @@ void ChatController::handleBareJIDCapsChanged(const JID& /*jid*/) {
 		} else {
 			contactSupportsReceipts_ = ChatWindow::No;
 		}
+		if (FileTransferManager::isSupportedBy(disco)) {
+			chatWindow_->setFileTransferEnabled(ChatWindow::Yes);
+		} else {
+			chatWindow_->setFileTransferEnabled(ChatWindow::No);
+		}
 	} else {
 		SWIFT_LOG(debug) << "No disco info :(" << std::endl;
 		chatWindow_->setCorrectionEnabled(ChatWindow::Maybe);
diff --git a/Swift/Controllers/Roster/RosterController.cpp b/Swift/Controllers/Roster/RosterController.cpp
index 4016f81..d2d024c 100644
--- a/Swift/Controllers/Roster/RosterController.cpp
+++ b/Swift/Controllers/Roster/RosterController.cpp
@@ -356,7 +356,7 @@ void RosterController::handleOnCapsChanged(const JID& jid) {
 	DiscoInfo::ref info = entityCapsManager_->getCaps(jid);
 	if (info) {
 		std::set<ContactRosterItem::Feature> features;
-		if (info->hasFeature(DiscoInfo::JingleFeature) && info->hasFeature(DiscoInfo::JingleFTFeature) && info->hasFeature(DiscoInfo::JingleTransportsIBBFeature)) {
+		if (FileTransferManager::isSupportedBy(info)) {
 			features.insert(ContactRosterItem::FileTransferFeature);
 		}
 		if (info->hasFeature(DiscoInfo::WhiteboardFeature)) {
diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h
index 096a59a..ba4b397 100644
--- a/Swift/Controllers/UIInterfaces/ChatWindow.h
+++ b/Swift/Controllers/UIInterfaces/ChatWindow.h
@@ -133,6 +133,7 @@ namespace Swift {
 			virtual void setAvailableSecurityLabels(const std::vector<SecurityLabelsCatalog::Item>& labels) = 0;
 			virtual void setSecurityLabelsEnabled(bool enabled) = 0;
 			virtual void setCorrectionEnabled(Tristate enabled) = 0;
+			virtual void setFileTransferEnabled(Tristate enabled) = 0;
 			virtual void setUnreadMessageCount(int count) = 0;
 			virtual void convertToMUC(MUCType mucType) = 0;
 //			virtual TreeWidget *getTreeWidget() = 0;
diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h
index c2e2c9f..e4c2548 100644
--- a/Swift/Controllers/UnitTest/MockChatWindow.h
+++ b/Swift/Controllers/UnitTest/MockChatWindow.h
@@ -58,6 +58,7 @@ namespace Swift {
 			virtual void setAlert(const std::string& /*alertText*/, const std::string& /*buttonText*/) {}
 			virtual void cancelAlert() {}
 			virtual void setCorrectionEnabled(Tristate /*enabled*/) {}
+			virtual void setFileTransferEnabled(Tristate /*enabled*/) {}
 			void setAvailableOccupantActions(const std::vector<OccupantAction>&/* actions*/) {}
 			void setSubject(const std::string& /*subject*/) {}
 			virtual void showRoomConfigurationForm(Form::ref) {}
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index f58c11b..f0d2038 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -67,6 +67,7 @@ QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventSt
 	isCorrection_ = false;
 	labelModel_ = NULL;
 	correctionEnabled_ = Maybe;
+	fileTransferEnabled_ = Maybe;
 	updateTitleWithUnreadCount();
 
 #ifdef SWIFT_EXPERIMENTAL_FT
@@ -386,6 +387,10 @@ void QtChatWindow::setCorrectionEnabled(Tristate enabled) {
 	correctionEnabled_ = enabled;
 }
 
+void QtChatWindow::setFileTransferEnabled(Tristate enabled) {
+	fileTransferEnabled_ = enabled;
+}
+
 SecurityLabelsCatalog::Item QtChatWindow::getSelectedSecurityLabel() {
 	assert(labelsWidget_->isEnabled());
 	assert(labelsWidget_->currentIndex() >= 0 && static_cast<size_t>(labelsWidget_->currentIndex()) < labelModel_->availableLabels_.size());
@@ -550,7 +555,7 @@ void QtChatWindow::dragEnterEvent(QDragEnterEvent *event) {
 }
 
 void QtChatWindow::dropEvent(QDropEvent *event) {
-	if (event->mimeData()->hasUrls()) {
+	if (fileTransferEnabled_ == ChatWindow::Yes && event->mimeData()->hasUrls()) {
 		if (event->mimeData()->urls().size() == 1) {
 			onSendFileRequest(Q2PSTRING(event->mimeData()->urls().at(0).toLocalFile()));
 		} else {
diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h
index de7e45e..95edcd0 100644
--- a/Swift/QtUI/QtChatWindow.h
+++ b/Swift/QtUI/QtChatWindow.h
@@ -136,6 +136,7 @@ namespace Swift {
 			void setAlert(const std::string& alertText, const std::string& buttonText = "");
 			void cancelAlert();
 			void setCorrectionEnabled(Tristate enabled);
+			void setFileTransferEnabled(Tristate enabled);
 
 		signals:
 			void geometryChanged();
@@ -203,6 +204,7 @@ namespace Swift {
 			bool inputEnabled_;
 			QSplitter *logRosterSplitter_;
 			Tristate correctionEnabled_;
+			Tristate fileTransferEnabled_;
 			QString alertStyleSheet_;
 			QPointer<QtMUCConfigurationWindow> mucConfigurationWindow_;
 			QPointer<QtAffiliationEditor> affiliationEditor_;
diff --git a/Swiften/FileTransfer/FileTransferManager.cpp b/Swiften/FileTransfer/FileTransferManager.cpp
index 69be852..0c7d894 100644
--- a/Swiften/FileTransfer/FileTransferManager.cpp
+++ b/Swiften/FileTransfer/FileTransferManager.cpp
@@ -11,4 +11,13 @@ namespace Swift {
 FileTransferManager::~FileTransferManager() {
 }
 
+bool FileTransferManager::isSupportedBy(const DiscoInfo::ref info) {
+	if (info) {
+		return info->hasFeature(DiscoInfo::JingleFeature)
+						&& info->hasFeature(DiscoInfo::JingleFTFeature)
+						&& (info->hasFeature(DiscoInfo::JingleTransportsIBBFeature) || info->hasFeature(DiscoInfo::JingleTransportsS5BFeature));
+	}
+	return false;
+}
+
 }
diff --git a/Swiften/FileTransfer/FileTransferManager.h b/Swiften/FileTransfer/FileTransferManager.h
index 3b793c5..bc6530b 100644
--- a/Swiften/FileTransfer/FileTransferManager.h
+++ b/Swiften/FileTransfer/FileTransferManager.h
@@ -18,6 +18,7 @@
 
 #include <Swiften/Base/API.h>
 #include <Swiften/Base/boost_bsignals.h>
+#include <Swiften/Elements/DiscoInfo.h>
 #include <Swiften/JID/JID.h>
 #include <Swiften/FileTransfer/FileTransferOptions.h>
 #include <Swiften/FileTransfer/OutgoingFileTransfer.h>
@@ -45,6 +46,8 @@ namespace Swift {
 					boost::shared_ptr<ReadBytestream> bytestream,
 					const FileTransferOptions& = FileTransferOptions()) = 0;
 			
+			static bool isSupportedBy(const DiscoInfo::ref info);
+
 			boost::signal<void (IncomingFileTransfer::ref)> onIncomingFileTransfer;
 	};
 }
diff --git a/Swiften/FileTransfer/FileTransferManagerImpl.cpp b/Swiften/FileTransfer/FileTransferManagerImpl.cpp
index b832d7e..04a2332 100644
--- a/Swiften/FileTransfer/FileTransferManagerImpl.cpp
+++ b/Swiften/FileTransfer/FileTransferManagerImpl.cpp
@@ -111,8 +111,7 @@ boost::optional<JID> FileTransferManagerImpl::highestPriorityJIDSupportingFileTr
 		if (pres->getPriority() > priority) {
 			// look up caps from the jid
 			DiscoInfo::ref info = capsProvider->getCaps(pres->getFrom());
-			if (info && info->hasFeature(DiscoInfo::JingleFeature) && info->hasFeature(DiscoInfo::JingleFTFeature) && (info->hasFeature(DiscoInfo::JingleTransportsIBBFeature) || info->hasFeature(DiscoInfo::JingleTransportsS5BFeature))) {
-			
+			if (isSupportedBy(info)) {
 				priority = pres->getPriority();
 				fullReceipientJID = pres->getFrom();
 			}
-- 
cgit v0.10.2-6-g49f6