From 523dbfb769069663eda19e381ad35f466b1ef27c Mon Sep 17 00:00:00 2001
From: Tobias Markmann <tm@ayena.de>
Date: Mon, 30 Nov 2015 09:02:15 +0100
Subject: Show file-transfer description if provided

Test-Information:

Tested by transferring a file between two Swift instances.
Tested in WebKit chat views and in plain chat views.

Change-Id: Ie46cbd7bac8a36478f64b4557cf55926e6d4af37

diff --git a/Swift/Controllers/FileTransfer/FileTransferController.cpp b/Swift/Controllers/FileTransfer/FileTransferController.cpp
index c21c364..89e9a91 100644
--- a/Swift/Controllers/FileTransfer/FileTransferController.cpp
+++ b/Swift/Controllers/FileTransfer/FileTransferController.cpp
@@ -16,14 +16,14 @@
 #include <boost/filesystem.hpp>
 #include <boost/smart_ptr/make_shared.hpp>
 
-#include <Swiften/FileTransfer/FileTransferManager.h>
-#include <Swiften/FileTransfer/OutgoingJingleFileTransfer.h>
 #include <Swiften/Base/Log.h>
 #include <Swiften/Base/boost_bsignals.h>
 #include <Swiften/FileTransfer/FileReadBytestream.h>
+#include <Swiften/FileTransfer/FileTransferManager.h>
+#include <Swiften/FileTransfer/OutgoingJingleFileTransfer.h>
 
-#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
 #include <Swift/Controllers/Intl.h>
+#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
 
 namespace Swift {
 
@@ -49,9 +49,9 @@ const JID &FileTransferController::getOtherParty() const {
 std::string FileTransferController::setChatWindow(ChatWindow* wnd, std::string nickname) {
 	chatWindow = wnd;
 	if (sending) {
-		uiID = wnd->addFileTransfer(QT_TRANSLATE_NOOP("", "me"), true, filename, boost::filesystem::file_size(boost::filesystem::path(filename)));
+		uiID = wnd->addFileTransfer(QT_TRANSLATE_NOOP("", "me"), true, filename, boost::filesystem::file_size(boost::filesystem::path(filename)), "");
 	} else {
-		uiID = wnd->addFileTransfer(nickname, false, filename, transfer->getFileSizeInBytes());
+		uiID = wnd->addFileTransfer(nickname, false, filename, transfer->getFileSizeInBytes(), transfer->getDescription());
 	}
 	return uiID;
 }
diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h
index 0fa734c..3a1acdf 100644
--- a/Swift/Controllers/UIInterfaces/ChatWindow.h
+++ b/Swift/Controllers/UIInterfaces/ChatWindow.h
@@ -129,7 +129,7 @@ namespace Swift {
 			virtual void replaceWithAction(const ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) = 0;
 			
 			// File transfer related stuff
-			virtual std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes) = 0;
+			virtual std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes, const std::string& description) = 0;
 			virtual void setFileTransferProgress(std::string, const int percentageDone) = 0;
 			virtual void setFileTransferStatus(std::string, const FileTransferState state, const std::string& msg = "") = 0;
 			virtual void addMUCInvitation(const std::string& senderName, const JID& jid, const std::string& reason, const std::string& password, bool direct = true, bool isImpromptu = false, bool isContinuation = false) = 0;
diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h
index 2798be6..c906bfd 100644
--- a/Swift/Controllers/UnitTest/MockChatWindow.h
+++ b/Swift/Controllers/UnitTest/MockChatWindow.h
@@ -38,7 +38,7 @@ namespace Swift {
 			virtual void replaceSystemMessage(const ChatMessage& /*message*/, const std::string& /*id*/, const TimestampBehaviour /*timestampBehaviour*/) {}
 
 			// File transfer related stuff
-			virtual std::string addFileTransfer(const std::string& /*senderName*/, bool /*senderIsSelf*/,const std::string& /*filename*/, const boost::uintmax_t /*sizeInBytes*/) { return 0; }
+			virtual std::string addFileTransfer(const std::string& /*senderName*/, bool /*senderIsSelf*/,const std::string& /*filename*/, const boost::uintmax_t /*sizeInBytes*/, const std::string& /*description*/) { return 0; }
 			virtual void setFileTransferProgress(std::string /*id*/, const int /*alreadyTransferedBytes*/) { }
 			virtual void setFileTransferStatus(std::string /*id*/, const FileTransferState /*state*/, const std::string& /*msg*/) { }
 			
diff --git a/Swift/QtUI/QtChatView.h b/Swift/QtUI/QtChatView.h
index 75e38e2..e1d2e1a 100644
--- a/Swift/QtUI/QtChatView.h
+++ b/Swift/QtUI/QtChatView.h
@@ -7,8 +7,9 @@
 #pragma once
 
 #include <string>
-#include <boost/shared_ptr.hpp>
+
 #include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/shared_ptr.hpp>
 
 #include <QWidget>
 
@@ -43,7 +44,7 @@ namespace Swift {
 			virtual void replaceLastMessage(const ChatWindow::ChatMessage& message, const ChatWindow::TimestampBehaviour /*timestampBehaviour*/) = 0;
 			virtual void setAckState(const std::string& id, ChatWindow::AckState state) = 0;
 			
-			virtual std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes) = 0;
+			virtual std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes, const std::string& description) = 0;
 			virtual void setFileTransferProgress(std::string, const int percentageDone) = 0;
 			virtual void setFileTransferStatus(std::string, const ChatWindow::FileTransferState state, const std::string& msg = "") = 0;
 			virtual void addMUCInvitation(const std::string& senderName, const JID& jid, const std::string& reason, const std::string& password, bool direct, bool isImpromptu, bool isContinuation) = 0;
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index abbfae5..caa556f 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -906,9 +906,9 @@ void QtChatWindow::replaceWithAction(const ChatMessage& message, const std::stri
 	messageLog_->replaceWithAction(message, id, time, highlight);
 }
 
-std::string QtChatWindow::addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes) {
+std::string QtChatWindow::addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes, const std::string& description) {
 	handleAppendedToLog();
-	return messageLog_->addFileTransfer(senderName, senderIsSelf, filename, sizeInBytes);
+	return messageLog_->addFileTransfer(senderName, senderIsSelf, filename, sizeInBytes, description);
 }
 
 void QtChatWindow::setFileTransferProgress(std::string id, const int percentageDone) {
diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h
index bbcdee7..121192a 100644
--- a/Swift/QtUI/QtChatWindow.h
+++ b/Swift/QtUI/QtChatWindow.h
@@ -90,7 +90,7 @@ namespace Swift {
 			void replaceMessage(const ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight);
 			void replaceWithAction(const ChatMessage& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight);
 			// File transfer related stuff
-			std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes);
+			std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes, const std::string& description);
 			void setFileTransferProgress(std::string id, const int percentageDone);
 			void setFileTransferStatus(std::string id, const FileTransferState state, const std::string& msg);
 			
diff --git a/Swift/QtUI/QtPlainChatView.cpp b/Swift/QtUI/QtPlainChatView.cpp
index e062efc..a794167 100644
--- a/Swift/QtUI/QtPlainChatView.cpp
+++ b/Swift/QtUI/QtPlainChatView.cpp
@@ -177,7 +177,7 @@ void QtPlainChatView::setAckState(const std::string& /*id*/, ChatWindow::AckStat
 	}
 }
 
-std::string QtPlainChatView::addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes)
+std::string QtPlainChatView::addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes, const std::string& description)
 {
 	const std::string ftId = "ft" + boost::lexical_cast<std::string>(idGenerator_++);
 	const std::string sizeString = formatSize(sizeInBytes);
@@ -187,11 +187,13 @@ std::string QtPlainChatView::addFileTransfer(const std::string& senderName, bool
 		QString description = QInputDialog::getText(this, tr("File transfer description"),
 			tr("Description:"), QLineEdit::Normal, "");
 		/* NOTE: it is not possible to abort if description is not provided, since we must always return a valid transfer id */
-		const std::string message = std::string() + "Confirm file transfer: <i>" + filename + " (" + sizeString + " bytes)</i>";
+		const std::string descriptionMessage = description.isEmpty() ? "" : (" \"" + Q2PSTRING(description) + "\"");
+		const std::string message = std::string() + "Confirm file transfer: <i>" + filename + " (" + sizeString + " bytes)</i>" + descriptionMessage;
 		transfer = new FileTransfer(this, senderIsSelf, ftId, filename, ChatWindow::WaitingForAccept, Q2PSTRING(description), message, true);
 		addSystemMessage(ChatWindow::ChatMessage("Preparing to start file transfer..."), ChatWindow::DefaultDirection);
 	} else { /* incoming transfer */
-		const std::string message = std::string() + "Incoming file transfer: <i>" + filename + " (" + sizeString + " bytes)</i>";
+		const std::string descriptionMessage = description.empty() ? "" : (" \"" + description + "\"");
+		const std::string message = std::string() + "Incoming file transfer: <i>" + filename + " (" + sizeString + " bytes)</i>" + descriptionMessage;
 		transfer = new FileTransfer(this, senderIsSelf, ftId, filename, ChatWindow::WaitingForAccept, "", message, true);
 		addSystemMessage("Incoming file transfer from " + senderName + "...", ChatWindow::DefaultDirection);
 	}
@@ -285,6 +287,8 @@ void QtPlainChatView::fileTransferAccept()
 
 	FileTransfer* transfer = transferIter->second;
 
+	const std::string message = transfer->message_;
+
 	if (transfer->senderIsSelf_) { /* if we are the sender, kick of the transfer */
 		window_->onFileTransferStart(transfer->ftId_, transfer->description_);
 	} else { /* ask the user where to save the file first */
@@ -296,7 +300,7 @@ void QtPlainChatView::fileTransferAccept()
 		window_->onFileTransferAccept(transfer->ftId_, Q2PSTRING(path));
 	}
 
-	setFileTransferStatus(transfer->ftId_, ChatWindow::Negotiating, transfer->message_);
+	setFileTransferStatus(transfer->ftId_, ChatWindow::Negotiating, message);
 }
 
 void QtPlainChatView::fileTransferReject()
diff --git a/Swift/QtUI/QtPlainChatView.h b/Swift/QtUI/QtPlainChatView.h
index 782944f..aeb50b6 100644
--- a/Swift/QtUI/QtPlainChatView.h
+++ b/Swift/QtUI/QtPlainChatView.h
@@ -7,11 +7,12 @@
 #pragma once
 
 #include <string>
-#include <boost/shared_ptr.hpp>
+
 #include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/shared_ptr.hpp>
 
-#include <QWidget>
 #include <QTextEdit>
+#include <QWidget>
 
 #include <Swift/Controllers/UIInterfaces/ChatWindow.h>
 
@@ -50,7 +51,7 @@ namespace Swift {
 			virtual void replaceSystemMessage(const ChatWindow::ChatMessage& message, const std::string& id, const ChatWindow::TimestampBehaviour /*timestampBehaviour*/);
 			virtual void setAckState(const std::string& /*id*/, ChatWindow::AckState /*state*/);
 
-			virtual std::string addFileTransfer(const std::string& /*senderName*/, bool /*senderIsSelf*/, const std::string& /*filename*/, const boost::uintmax_t /*sizeInBytes*/);
+			virtual std::string addFileTransfer(const std::string& /*senderName*/, bool /*senderIsSelf*/, const std::string& /*filename*/, const boost::uintmax_t /*sizeInBytes*/, const std::string& /*description*/);
 			virtual void setFileTransferProgress(std::string, const int /*percentageDone*/);
 			virtual void setFileTransferStatus(std::string, const ChatWindow::FileTransferState /*state*/, const std::string& /*msg*/ = "");
 			virtual void addMUCInvitation(const std::string& /*senderName*/, const JID& /*jid*/, const std::string& /*reason*/, const std::string& /*password*/, bool /*direct*/, bool /*isImpromptu*/, bool /*isContinuation*/);
diff --git a/Swift/QtUI/QtWebKitChatView.cpp b/Swift/QtUI/QtWebKitChatView.cpp
index 7e0e505..260da8a 100644
--- a/Swift/QtUI/QtWebKitChatView.cpp
+++ b/Swift/QtUI/QtWebKitChatView.cpp
@@ -441,6 +441,11 @@ void QtWebKitChatView::setFileTransferStatus(QString id, const ChatWindow::FileT
 
 	QString newInnerHTML = "";
 	if (state == ChatWindow::Initialisation) {
+		QWebElement filenameSizeDescriptionElement = ftElement.parent().firstChild();
+		QString description = QtUtilities::htmlEscape(descriptions_[id]);
+		if (!description.isEmpty()) {
+			filenameSizeDescriptionElement.prependOutside(QString(" \"%1\"").arg(description));
+		}
 		newInnerHTML = tr("Preparing to transfer.") + "<br/>" +
 			buildChatWindowButton(tr("Cancel"), ButtonFileTransferCancel, id);
 	}
@@ -660,17 +665,19 @@ QString QtWebKitChatView::buildChatWindowButton(const QString& name, const QStri
 	return html;
 }
 
-std::string QtWebKitChatView::addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes) {
+std::string QtWebKitChatView::addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes, const std::string& description) {
 	SWIFT_LOG(debug) << "addFileTransfer" << std::endl;
 	QString ft_id = QString("ft%1").arg(P2QSTRING(boost::lexical_cast<std::string>(idCounter_++)));
 	
 	QString actionText;
 	QString htmlString;
 	QString formattedFileSize = P2QSTRING(formatSize(sizeInBytes));
+	QString sanitizedFileName = QtUtilities::htmlEscape(P2QSTRING(filename));
+	QString sanitizedDescription = QtUtilities::htmlEscape(P2QSTRING(description));
 	if (senderIsSelf) {
 		// outgoing
-		filePaths_[ft_id] = P2QSTRING(filename);
-		actionText = tr("Send file: %1 (%2)").arg(P2QSTRING(filename)).arg(formattedFileSize);
+		filePaths_[ft_id] = sanitizedFileName;
+		actionText = tr("Send file: %1 (%2)").arg(sanitizedFileName).arg(formattedFileSize);
 		htmlString = actionText + " <br/>" +
 			"<div id='" + ft_id + "'>" +
 				buildChatWindowButton(tr("Cancel"), ButtonFileTransferCancel, ft_id) +
@@ -679,7 +686,10 @@ std::string QtWebKitChatView::addFileTransfer(const std::string& senderName, boo
 			"</div>";
 	} else {
 		// incoming
-		actionText = tr("Receiving file: %1 (%2)").arg(P2QSTRING(filename)).arg(formattedFileSize);
+		actionText = tr("Receiving file: %1 (%2)").arg(sanitizedFileName).arg(formattedFileSize);
+		if (!sanitizedDescription.isEmpty()) {
+			actionText += QString(" \"%1\"").arg(sanitizedDescription);
+		}
 		htmlString = actionText + " <br/>" +
 			"<div id='" + ft_id + "'>" +
 				buildChatWindowButton(tr("Cancel"), ButtonFileTransferCancel, ft_id) +
diff --git a/Swift/QtUI/QtWebKitChatView.h b/Swift/QtUI/QtWebKitChatView.h
index af2da01..99375f7 100644
--- a/Swift/QtUI/QtWebKitChatView.h
+++ b/Swift/QtUI/QtWebKitChatView.h
@@ -66,7 +66,7 @@ namespace Swift {
 			virtual void replaceLastMessage(const ChatWindow::ChatMessage& message, const ChatWindow::TimestampBehaviour timestampBehaviour) SWIFTEN_OVERRIDE;
 			virtual void setAckState(const std::string& id, ChatWindow::AckState state) SWIFTEN_OVERRIDE;
 			
-			virtual std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes) SWIFTEN_OVERRIDE;
+			virtual std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes, const std::string& description) SWIFTEN_OVERRIDE;
 			virtual void setFileTransferProgress(std::string, const int percentageDone) SWIFTEN_OVERRIDE;
 			virtual void setFileTransferStatus(std::string, const ChatWindow::FileTransferState state, const std::string& msg = "") SWIFTEN_OVERRIDE;
 			virtual void addMUCInvitation(const std::string& senderName, const JID& jid, const std::string& reason, const std::string& password, bool direct, bool isImpromptu, bool isContinuation) SWIFTEN_OVERRIDE;
diff --git a/Swiften/FileTransfer/FileTransfer.cpp b/Swiften/FileTransfer/FileTransfer.cpp
index f63a4e8..4782d39 100644
--- a/Swiften/FileTransfer/FileTransfer.cpp
+++ b/Swiften/FileTransfer/FileTransfer.cpp
@@ -19,7 +19,8 @@ void FileTransfer::setState(const State& state) {
 	onStateChanged(state);
 }
 
-void FileTransfer::setFileInfo(const std::string& name, boost::uintmax_t size) {
+void FileTransfer::setFileInfo(const std::string& name, boost::uintmax_t size, const std::string& description) {
 	filename_ = name;
 	fileSizeInBytes_ = size;
+	description_ = description;
 }
diff --git a/Swiften/FileTransfer/FileTransfer.h b/Swiften/FileTransfer/FileTransfer.h
index afb3f7b..ab8e806 100644
--- a/Swiften/FileTransfer/FileTransfer.h
+++ b/Swiften/FileTransfer/FileTransfer.h
@@ -66,6 +66,10 @@ namespace Swift {
 				return state_;
 			}
 
+			const std::string& getDescription() const {
+				return description_;
+			}
+
 		public:
 			boost::signal<void (size_t /* proccessedBytes */)> onProcessedBytes;
 			boost::signal<void (const State&)> onStateChanged;
@@ -73,11 +77,12 @@ namespace Swift {
 
 		protected:
 			void setState(const State& state);
-			void setFileInfo(const std::string& name, boost::uintmax_t size);
+			void setFileInfo(const std::string& name, boost::uintmax_t size, const std::string& description);
 
 		private:
 			boost::uintmax_t fileSizeInBytes_;
 			std::string filename_;
+			std::string description_;
 			State state_;
 	};
 }
diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp
index 39da46f..01bed78 100644
--- a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp
+++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp
@@ -47,7 +47,7 @@ IncomingJingleFileTransfer::IncomingJingleFileTransfer(
 	description = initialContent->getDescription<JingleFileTransferDescription>();
 	assert(description);
 	JingleFileTransferFileInfo fileInfo = description->getFileInfo();
-	setFileInfo(fileInfo.getName(), fileInfo.getSize());
+	setFileInfo(fileInfo.getName(), fileInfo.getSize(), fileInfo.getDescription());
 	hashes = fileInfo.getHashes();
 
 	waitOnHashTimer = timerFactory->createTimer(5000);
diff --git a/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp b/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp
index 6369581..b8e848c 100644
--- a/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp
+++ b/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp
@@ -62,7 +62,7 @@ OutgoingJingleFileTransfer::OutgoingJingleFileTransfer(
 			state(Initial),
 			candidateAcknowledged(false) {
 
-	setFileInfo(fileInfo.getName(), fileInfo.getSize());
+	setFileInfo(fileInfo.getName(), fileInfo.getSize(), fileInfo.getDescription());
 
 	// calculate both, MD5 and SHA-1 since we don't know which one the other side supports
 	hashCalculator = new IncrementalBytestreamHashCalculator(true, true, crypto);
-- 
cgit v0.10.2-6-g49f6