diff options
41 files changed, 872 insertions, 499 deletions
diff --git a/Swiften/Elements/HashElement.h b/Swiften/Elements/HashElement.h new file mode 100644 index 0000000..44d2f96 --- /dev/null +++ b/Swiften/Elements/HashElement.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/ByteArray.h> + +namespace Swift { +	/* +	 * @brief This class represents a XEP-0300 <hash/> element. +	 */ +	class HashElement { +		public: +			HashElement(const std::string& algorithm, const ByteArray& hash) : algorithm_(algorithm), hash_(hash) { +			} + +			void setHashValue(const std::string& algorithm, const ByteArray& hash) { +				algorithm_ = algorithm; +				hash_ = hash; +			} + +			const std::string& getAlgorithm() const { +				return algorithm_; +			} + +			const ByteArray& getHashValue() const { +				return hash_; +			} + +			bool operator==(const HashElement& rhs) const { +				return (algorithm_ == rhs.algorithm_) && (hash_ == rhs.hash_); +			} + + +		private: +			std::string algorithm_; +			ByteArray hash_; +	}; +} diff --git a/Swiften/Elements/JingleFileTransferDescription.h b/Swiften/Elements/JingleFileTransferDescription.h index 620f8f5..9308abf 100644 --- a/Swiften/Elements/JingleFileTransferDescription.h +++ b/Swiften/Elements/JingleFileTransferDescription.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2011 Isode Limited. + * Copyright (c) 2011-2014 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */ @@ -10,32 +10,22 @@  #include <vector>  #include <Swiften/Elements/JingleDescription.h> -#include <Swiften/Elements/StreamInitiationFileInfo.h> +#include <Swiften/Elements/JingleFileTransferFileInfo.h>  namespace Swift {  	class JingleFileTransferDescription : public JingleDescription {  		public:  			typedef boost::shared_ptr<JingleFileTransferDescription> ref; -			void addOffer(const StreamInitiationFileInfo& offer) { -				offers.push_back(offer); +			void setFileInfo(const JingleFileTransferFileInfo& fileInfo) { +				fileInfo_ = fileInfo;  			} -			 -			const std::vector<StreamInitiationFileInfo>& getOffers() const { -				return offers; -			} -			 -			void addRequest(const StreamInitiationFileInfo& request) { -				reqeusts.push_back(request); -			} -			 -			const std::vector<StreamInitiationFileInfo>& getRequests() const { -				return reqeusts; +			const JingleFileTransferFileInfo& getFileInfo() { +				return fileInfo_;  			}  		private: -			std::vector<StreamInitiationFileInfo> offers; -			std::vector<StreamInitiationFileInfo> reqeusts; +			JingleFileTransferFileInfo fileInfo_;  	};  } diff --git a/Swiften/Elements/JingleFileTransferFileInfo.h b/Swiften/Elements/JingleFileTransferFileInfo.h new file mode 100644 index 0000000..8fec59e --- /dev/null +++ b/Swiften/Elements/JingleFileTransferFileInfo.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> +#include <vector> +#include <map> + +#include <boost/optional.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/date_time/posix_time/posix_time_types.hpp> + +#include <Swiften/Elements/HashElement.h> +#include <Swiften/Elements/Payload.h> + +namespace Swift { + +	/** +	 * @brief This class represents the file info used in XEP-0234. +	 */ +	class JingleFileTransferFileInfo : public Payload { +		typedef boost::shared_ptr<JingleFileTransferFileInfo> ref; + +		public: +			JingleFileTransferFileInfo(const std::string& name = "", const std::string& description = "", unsigned long long size = 0, const boost::posix_time::ptime &date = boost::posix_time::ptime()) : +				name_(name), description_(description), size_(size), date_(date), supportsRangeRequests_(false), rangeOffset_(0) { +			} + +		public: +			typedef std::map<std::string, ByteArray> HashElementMap; + +		public: +			void setName(const std::string& name) { +				name_ = name;; +			} +	 +			const std::string& getName() const { +				return name_; +			} + +			void setDescription(const std::string& description) { +				description_ = description; +			} +	 +			const std::string& getDescription() const { +				return description_; +			} + +			void setMediaType(const std::string& mediaType) { +				mediaType_ = mediaType; +			} + +			const std::string& getMediaType() const { +				return mediaType_; +			} +	 +			void setSize(const boost::uintmax_t size) { +				size_ = size; +			} +	 +			boost::uintmax_t getSize() const { +				return size_; +			} + +			void setDate(const boost::posix_time::ptime& date) { +				date_ = date; +			} +	 +			const boost::posix_time::ptime& getDate() const { +				return date_; +			} + +			void setSupportsRangeRequests(const bool supportsIt) { +				supportsRangeRequests_ = supportsIt; +			} +	 +			bool getSupportsRangeRequests() const { +				return supportsRangeRequests_; +			} +	 +			void setRangeOffset(const boost::uintmax_t offset) { +				supportsRangeRequests_ = true; +				rangeOffset_ = offset; +			} +	 +			boost::uintmax_t getRangeOffset() const { +				return rangeOffset_; +			} + +			void addHash(const HashElement& hash) { +				hashes_[hash.getAlgorithm()] = hash.getHashValue(); +			} + +			const std::map<std::string, ByteArray>& getHashes() const { +				return hashes_; +			} + +			boost::optional<ByteArray> getHash(const std::string& algorithm) const { +				boost::optional<ByteArray> ret; +				if (hashes_.find(algorithm) != hashes_.end()) { +					ret = boost::optional<ByteArray>(hashes_.find(algorithm)->second); +				} +				return ret; +			} + +		private:	 +			std::string name_; +			std::string description_; +			std::string mediaType_; +			boost::uintmax_t size_; +			boost::posix_time::ptime date_; +			bool supportsRangeRequests_; +			boost::uintmax_t rangeOffset_; +			HashElementMap hashes_; +	}; +} diff --git a/Swiften/Elements/JingleFileTransferHash.h b/Swiften/Elements/JingleFileTransferHash.h index 5603531..d34e35d 100644 --- a/Swiften/Elements/JingleFileTransferHash.h +++ b/Swiften/Elements/JingleFileTransferHash.h @@ -4,6 +4,12 @@   * See Documentation/Licenses/BSD-simplified.txt for more information.   */ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +  #pragma once  #include <boost/shared_ptr.hpp> @@ -11,25 +17,24 @@  #include <string>  #include <Swiften/Elements/JingleDescription.h> +#include <Swiften/Elements/JingleFileTransferFileInfo.h>  namespace Swift {  class JingleFileTransferHash : public Payload {  public: -	typedef std::map<std::string, std::string> HashesMap; -public:  	typedef boost::shared_ptr<JingleFileTransferHash> ref; -	void setHash(const std::string& algo, const std::string& hash) { -		hashes[algo] = hash; +	void setFileInfo(const JingleFileTransferFileInfo& fileInfo) { +		fileInfo_ = fileInfo;  	} -	const HashesMap& getHashes() const { -		return hashes; +	JingleFileTransferFileInfo& getFileInfo() { +		return fileInfo_;  	}  private: -	HashesMap hashes; +	JingleFileTransferFileInfo fileInfo_;  };  } diff --git a/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp b/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp index 74492b1..1a77685 100644 --- a/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp +++ b/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp @@ -1,5 +1,5 @@  /* - * Copyright (c) 2013 Isode Limited. + * Copyright (c) 2013-2014 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */ @@ -242,8 +242,10 @@ boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createIBBSen  boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createIBBReceiveSession(  		const std::string& sessionID, unsigned long long size, boost::shared_ptr<WriteBytestream> stream) { -	closeLocalSession(); -	closeRemoteSession(); +	if (s5bServerManager->getServer()) { +		closeLocalSession(); +		closeRemoteSession(); +	}  	boost::shared_ptr<IBBReceiveSession> ibbSession = boost::make_shared<IBBReceiveSession>(  			sessionID, initiator, responder, size, stream, router);  	return boost::make_shared<IBBReceiveTransportSession>(ibbSession); diff --git a/Swiften/FileTransfer/FileTransferManagerImpl.cpp b/Swiften/FileTransfer/FileTransferManagerImpl.cpp index f248b8a..fe8bfd6 100644 --- a/Swiften/FileTransfer/FileTransferManagerImpl.cpp +++ b/Swiften/FileTransfer/FileTransferManagerImpl.cpp @@ -5,7 +5,7 @@   */  /* - * Copyright (c) 2013 Isode Limited. + * Copyright (c) 2013-2014 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */ @@ -21,7 +21,7 @@  #include <Swiften/Base/Path.h>  #include "Swiften/Disco/EntityCapsProvider.h"  #include <Swiften/JID/JID.h> -#include <Swiften/Elements/StreamInitiationFileInfo.h> +#include <Swiften/Elements/JingleFileTransferFileInfo.h>  #include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h>  #include <Swiften/FileTransfer/OutgoingFileTransferManager.h>  #include <Swiften/FileTransfer/IncomingFileTransferManager.h> @@ -146,7 +146,7 @@ OutgoingFileTransfer::ref FileTransferManagerImpl::createOutgoingFileTransfer(  		const boost::posix_time::ptime& lastModified,   		boost::shared_ptr<ReadBytestream> bytestream,  		const FileTransferOptions& config) { -	StreamInitiationFileInfo fileInfo; +	JingleFileTransferFileInfo fileInfo;  	fileInfo.setDate(lastModified);  	fileInfo.setSize(sizeInBytes);  	fileInfo.setName(filename); diff --git a/Swiften/FileTransfer/FileTransferOptions.h b/Swiften/FileTransfer/FileTransferOptions.h index 3a0abcb..3d00d2b 100644 --- a/Swiften/FileTransfer/FileTransferOptions.h +++ b/Swiften/FileTransfer/FileTransferOptions.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2013 Isode Limited. + * Copyright (c) 2013-2014 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */ @@ -12,7 +12,7 @@  namespace Swift {  	class SWIFTEN_API FileTransferOptions {  		public: -			FileTransferOptions() : allowInBand(false) { +			FileTransferOptions() : allowInBand(true) {  			}  			SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(FileTransferOptions)  			~FileTransferOptions(); diff --git a/Swiften/FileTransfer/FileTransferTransporter.h b/Swiften/FileTransfer/FileTransferTransporter.h index d149722..2116f0d 100644 --- a/Swiften/FileTransfer/FileTransferTransporter.h +++ b/Swiften/FileTransfer/FileTransferTransporter.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2013 Isode Limited. + * Copyright (c) 2013-2014 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */ @@ -20,6 +20,11 @@ namespace Swift {  	class ReadBytestream;  	class WriteBytestream; +	/** +	 * @brief The FileTransferTransporter class is an abstract factory definition +	 * to generate SOCKS5 bytestream transports or IBB bytestreams for use in file +	 * transfers. +	 */  	class SWIFTEN_API FileTransferTransporter {  		public:  			virtual ~FileTransferTransporter(); diff --git a/Swiften/FileTransfer/IncomingFileTransfer.h b/Swiften/FileTransfer/IncomingFileTransfer.h index e0cb4ad..93ecf1a 100644 --- a/Swiften/FileTransfer/IncomingFileTransfer.h +++ b/Swiften/FileTransfer/IncomingFileTransfer.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2014 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */ @@ -16,6 +16,10 @@ namespace Swift {  	class WriteBytestream;  	class JID; +	/** +	 * @brief The IncomingFileTransfer abstract class is the general interface in Swiften +	 * for incoming file transfers. +	 */  	class IncomingFileTransfer : public FileTransfer {  		public:  			typedef boost::shared_ptr<IncomingFileTransfer> ref; diff --git a/Swiften/FileTransfer/IncomingFileTransferManager.cpp b/Swiften/FileTransfer/IncomingFileTransferManager.cpp index 05d6259..239c4a8 100644 --- a/Swiften/FileTransfer/IncomingFileTransferManager.cpp +++ b/Swiften/FileTransfer/IncomingFileTransferManager.cpp @@ -44,13 +44,13 @@ bool IncomingFileTransferManager::handleIncomingJingleSession(  	if (JingleContentPayload::ref content = Jingle::getContentWithDescription<JingleFileTransferDescription>(contents)) {  		if (content->getTransport<JingleS5BTransportPayload>()) {  			JingleFileTransferDescription::ref description = content->getDescription<JingleFileTransferDescription>(); -			if (description && description->getOffers().size() == 1) { +			if (description) {  				IncomingJingleFileTransfer::ref transfer = boost::make_shared<IncomingJingleFileTransfer>(  						recipient, session, content, transporterFactory, timerFactory, crypto);  				onIncomingFileTransfer(transfer);  			}   			else { -				SWIFT_LOG(warning) << "Received a file-transfer request with no description or more than one file."; +				SWIFT_LOG(warning) << "Received a file-transfer request with no file description.";  				session->sendTerminate(JinglePayload::Reason::FailedApplication);  			}  		} diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp index 66b2e53..720eefd 100644 --- a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp +++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp @@ -1,15 +1,18 @@  /* - * Copyright (c) 2011-2013 Isode Limited. + * Copyright (c) 2011-2014 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */  #include <Swiften/FileTransfer/IncomingJingleFileTransfer.h> +#include <set> +  #include <boost/bind.hpp>  #include <boost/smart_ptr/make_shared.hpp>  #include <Swiften/Base/Log.h> +#include <Swiften/StringCodecs/Base64.h>  #include <Swiften/Base/foreach.h>  #include <Swiften/Jingle/JingleSession.h>  #include <Swiften/Elements/JingleIBBTransportPayload.h> @@ -43,11 +46,9 @@ IncomingJingleFileTransfer::IncomingJingleFileTransfer(  			hashCalculator(NULL) {  	description = initialContent->getDescription<JingleFileTransferDescription>();  	assert(description); -	assert(description->getOffers().size() == 1); -	StreamInitiationFileInfo fileInfo = description->getOffers().front(); +	JingleFileTransferFileInfo fileInfo = description->getFileInfo();  	setFileInfo(fileInfo.getName(), fileInfo.getSize()); -	hash = fileInfo.getHash(); -	hashAlgorithm = fileInfo.getAlgo(); +	hashes = fileInfo.getHashes();  	waitOnHashTimer = timerFactory->createTimer(5000);  	waitOnHashTimerTickedConnection = waitOnHashTimer->onTick.connect( @@ -68,20 +69,33 @@ void IncomingJingleFileTransfer::accept(  	this->options = options;  	assert(!hashCalculator); +  	hashCalculator = new IncrementalBytestreamHashCalculator( -			hashAlgorithm == "md5" || hash.empty(), hashAlgorithm == "sha-1" || hash.empty(), crypto); +			hashes.find("md5") != hashes.end(), hashes.find("sha-1") != hashes.end(), crypto);  	writeStreamDataReceivedConnection = stream->onWrite.connect(  			boost::bind(&IncomingJingleFileTransfer::handleWriteStreamDataReceived, this, _1));  	if (JingleS5BTransportPayload::ref s5bTransport = initialContent->getTransport<JingleS5BTransportPayload>()) { -		SWIFT_LOG(debug) << "Got S5B transport payload!" << std::endl; +		SWIFT_LOG(debug) << "Got S5B transport as initial payload." << std::endl;  		setTransporter(transporterFactory->createResponderTransporter(  				getInitiator(), getResponder(), s5bTransport->getSessionID()));  		transporter->addRemoteCandidates(s5bTransport->getCandidates());  		setState(GeneratingInitialLocalCandidates);  		transporter->startGeneratingLocalCandidates();  	} +	else if (JingleIBBTransportPayload::ref ibbTransport = initialContent->getTransport<JingleIBBTransportPayload>()) { +		SWIFT_LOG(debug) << "Got IBB transport as initial payload." << std::endl; +		setTransporter(transporterFactory->createResponderTransporter( +				getInitiator(), getResponder(), ibbTransport->getSessionID())); + +		startTransferring(transporter->createIBBReceiveSession( +			ibbTransport->getSessionID(), +			description->getFileInfo().getSize(), +			stream)); + +		session->sendAccept(getContentID(), initialContent->getDescriptions()[0], ibbTransport); +	}  	else {  		// Can't happen, because the transfer would have been rejected automatically  		assert(false); @@ -121,13 +135,11 @@ void IncomingJingleFileTransfer::handleSessionInfoReceived(JinglePayload::ref ji  	if (transferHash) {  		SWIFT_LOG(debug) << "Received hash information." << std::endl;  		waitOnHashTimer->stop(); -		if (transferHash->getHashes().find("sha-1") != transferHash->getHashes().end()) { -			hashAlgorithm = "sha-1"; -			hash = transferHash->getHashes().find("sha-1")->second; +		if (transferHash->getFileInfo().getHashes().find("sha-1") != transferHash->getFileInfo().getHashes().end()) { +			hashes["sha-1"] = transferHash->getFileInfo().getHash("sha-1").get();  		} -		else if (transferHash->getHashes().find("md5") != transferHash->getHashes().end()) { -			hashAlgorithm = "md5"; -			hash = transferHash->getHashes().find("md5")->second; +		else if (transferHash->getFileInfo().getHashes().find("md5") != transferHash->getFileInfo().getHashes().end()) { +			hashes["md5"] = transferHash->getFileInfo().getHash("md5").get();  		}  		if (state == WaitingForHash) {  			checkHashAndTerminate(); @@ -172,7 +184,12 @@ void IncomingJingleFileTransfer::checkHashAndTerminate() {  void IncomingJingleFileTransfer::checkIfAllDataReceived() {  	if (receivedBytes == getFileSizeInBytes()) {  		SWIFT_LOG(debug) << "All data received." << std::endl; -		if (hash.empty()) { +		bool hashInfoAvailable = true; +		foreach(const JingleFileTransferFileInfo::HashElementMap::value_type& hashElement, hashes) { +			hashInfoAvailable &= !hashElement.second.empty(); +		} + +		if (!hashInfoAvailable) {  			SWIFT_LOG(debug) << "No hash information yet. Waiting a while on hash info." << std::endl;  			setState(WaitingForHash);  			waitOnHashTimer->start(); @@ -207,7 +224,7 @@ void IncomingJingleFileTransfer::handleTransportReplaceReceived(  		startTransferring(transporter->createIBBReceiveSession(  			ibbTransport->getSessionID(),  -			description->getOffers()[0].getSize(), +			description->getFileInfo().getSize(),  			stream));  		session->sendTransportAccept(content, ibbTransport);  	}  @@ -222,17 +239,17 @@ JingleContentID IncomingJingleFileTransfer::getContentID() const {  }  bool IncomingJingleFileTransfer::verifyData() { -	if (hashAlgorithm.empty() || hash.empty()) { +	if (hashes.empty()) {  		SWIFT_LOG(debug) << "no verification possible, skipping" << std::endl;  		return true;  	}  -	if (hashAlgorithm == "sha-1") { -		SWIFT_LOG(debug) << "Verify SHA-1 hash: " << (hash == hashCalculator->getSHA1String()) << std::endl; -		return hash == hashCalculator->getSHA1String(); +	if (hashes.find("sha-1") != hashes.end()) { +		SWIFT_LOG(debug) << "Verify SHA-1 hash: " << (hashes["sha-1"] == hashCalculator->getSHA1Hash()) << std::endl; +		return hashes["sha-1"] == hashCalculator->getSHA1Hash();  	} -	else if (hashAlgorithm == "md5") { -		SWIFT_LOG(debug) << "Verify MD5 hash: " << (hash == hashCalculator->getMD5String()) << std::endl; -		return hash == hashCalculator->getMD5String(); +	else if (hashes.find("md5") != hashes.end()) { +		SWIFT_LOG(debug) << "Verify MD5 hash: " << (hashes["md5"] == hashCalculator->getMD5Hash()) << std::endl; +		return hashes["md5"] == hashCalculator->getMD5Hash();  	}  	else {  		SWIFT_LOG(debug) << "Unknown hash, skipping" << std::endl; diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.h b/Swiften/FileTransfer/IncomingJingleFileTransfer.h index 727d278..7fc22f4 100644 --- a/Swiften/FileTransfer/IncomingJingleFileTransfer.h +++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2010-2013 Isode Limited. + * Copyright (c) 2010-2014 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */ @@ -17,6 +17,7 @@  #include <Swiften/FileTransfer/JingleFileTransfer.h>  #include <Swiften/Elements/JingleS5BTransportPayload.h>  #include <Swiften/FileTransfer/FileTransferOptions.h> +#include <Swiften/Base/ByteArray.h>  namespace Swift {  	class JID; @@ -29,7 +30,15 @@ namespace Swift {  	class CryptoProvider;  	class IncrementalBytestreamHashCalculator;  	class JingleFileTransferDescription; +	class HashElement; +	/** +	 * @brief The IncomingJingleFileTransfer class contains the business logic for managing incoming +	 *        Jingle file transfers. +	 * +	 * Calling IncomingJingleFileTransfer::accept will start to negotiate possible transfer +	 * methods and after a working method has been decided among peers the trasnfer is started. +	 */  	class SWIFTEN_API IncomingJingleFileTransfer : public IncomingFileTransfer, public JingleFileTransfer {  		public:  			typedef boost::shared_ptr<IncomingJingleFileTransfer> ref; @@ -43,7 +52,7 @@ namespace Swift {  				CryptoProvider*);  			~IncomingJingleFileTransfer(); -			virtual void accept(boost::shared_ptr<WriteBytestream>, const FileTransferOptions&) SWIFTEN_OVERRIDE; +			virtual void accept(boost::shared_ptr<WriteBytestream>, const FileTransferOptions& = FileTransferOptions()) SWIFTEN_OVERRIDE;  			virtual void cancel() SWIFTEN_OVERRIDE;  		private: @@ -108,8 +117,7 @@ namespace Swift {  			boost::uintmax_t receivedBytes;  			IncrementalBytestreamHashCalculator* hashCalculator;  			boost::shared_ptr<Timer> waitOnHashTimer; -			std::string hashAlgorithm; -			std::string hash; +			std::map<std::string, ByteArray> hashes;  			FileTransferOptions options;  			boost::bsignals::scoped_connection writeStreamDataReceivedConnection; diff --git a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp index e982fd0..7eb9560 100644 --- a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp +++ b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp @@ -5,7 +5,7 @@   */  /* - * Copyright (c) 2013 Isode Limited. + * Copyright (c) 2013-2014 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */ @@ -46,20 +46,30 @@ void IncrementalBytestreamHashCalculator::feedData(const SafeByteArray& data) {  	}  }*/ -std::string IncrementalBytestreamHashCalculator::getSHA1String() { +ByteArray IncrementalBytestreamHashCalculator::getSHA1Hash() {  	assert(sha1Hasher);  	if (!sha1Hash) { -		sha1Hash = Hexify::hexify(sha1Hasher->getHash()); +		sha1Hash = sha1Hasher->getHash();  	}  	return *sha1Hash;  } -std::string IncrementalBytestreamHashCalculator::getMD5String() { +ByteArray IncrementalBytestreamHashCalculator::getMD5Hash() {  	assert(md5Hasher);  	if (!md5Hash) { -		md5Hash = Hexify::hexify(md5Hasher->getHash()); +		md5Hash = md5Hasher->getHash();  	}  	return *md5Hash;  } +std::string IncrementalBytestreamHashCalculator::getSHA1String() { +	assert(sha1Hasher); +	return Hexify::hexify(getSHA1Hash());; +} + +std::string IncrementalBytestreamHashCalculator::getMD5String() { +	assert(md5Hasher); +	return Hexify::hexify(getMD5Hash());; +} +  } diff --git a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h index bb6b441..bc4ebf9 100644 --- a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h +++ b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h @@ -5,7 +5,7 @@   */  /* - * Copyright (c) 2013 Isode Limited. + * Copyright (c) 2013-2014 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */ @@ -30,14 +30,17 @@ namespace Swift {  		void feedData(const ByteArray& data);  		//void feedData(const SafeByteArray& data); +		ByteArray getSHA1Hash(); +		ByteArray getMD5Hash(); +  		std::string getSHA1String();  		std::string getMD5String();  	private:  		Hash* md5Hasher;  		Hash* sha1Hasher; -		boost::optional<std::string> md5Hash; -		boost::optional<std::string> sha1Hash; +		boost::optional<ByteArray> md5Hash; +		boost::optional<ByteArray> sha1Hash;  	};  } diff --git a/Swiften/FileTransfer/OutgoingFileTransferManager.cpp b/Swiften/FileTransfer/OutgoingFileTransferManager.cpp index 5ed4656..5d0555f 100644 --- a/Swiften/FileTransfer/OutgoingFileTransferManager.cpp +++ b/Swiften/FileTransfer/OutgoingFileTransferManager.cpp @@ -5,7 +5,7 @@   */  /* - * Copyright (c) 2013 Isode Limited. + * Copyright (c) 2013-2014 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */ @@ -43,7 +43,7 @@ boost::shared_ptr<OutgoingFileTransfer> OutgoingFileTransferManager::createOutgo  		const JID& from,   		const JID& recipient,   		boost::shared_ptr<ReadBytestream> readBytestream,  -		const StreamInitiationFileInfo& fileInfo, +		const JingleFileTransferFileInfo& fileInfo,  		const FileTransferOptions& config) {  	JingleSessionImpl::ref jingleSession = boost::make_shared<JingleSessionImpl>(  			from, recipient, idGenerator->generateID(), iqRouter); diff --git a/Swiften/FileTransfer/OutgoingFileTransferManager.h b/Swiften/FileTransfer/OutgoingFileTransferManager.h index 8dd4bbc..fd7380b 100644 --- a/Swiften/FileTransfer/OutgoingFileTransferManager.h +++ b/Swiften/FileTransfer/OutgoingFileTransferManager.h @@ -5,7 +5,7 @@   */  /* - * Copyright (c) 2013 Isode Limited. + * Copyright (c) 2013-2014 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */ @@ -22,7 +22,7 @@ namespace Swift {  	class JID;  	class IDGenerator;  	class ReadBytestream; -	class StreamInitiationFileInfo; +	class JingleFileTransferFileInfo;  	class CryptoProvider;  	class FileTransferOptions; @@ -39,7 +39,7 @@ namespace Swift {  					const JID& from,   					const JID& to,   					boost::shared_ptr<ReadBytestream>,  -					const StreamInitiationFileInfo&, +					const JingleFileTransferFileInfo&,  					const FileTransferOptions&);  		private: diff --git a/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp b/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp index 93214eb..369af8f 100644 --- a/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp +++ b/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp @@ -5,7 +5,7 @@   */  /* - * Copyright (C) 2013 Isode Limited. + * Copyright (C) 2013-2014 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */ @@ -49,7 +49,7 @@ OutgoingJingleFileTransfer::OutgoingJingleFileTransfer(  		boost::shared_ptr<ReadBytestream> stream,  		FileTransferTransporterFactory* transporterFactory,  		IDGenerator* idGenerator, -		const StreamInitiationFileInfo& fileInfo, +		const JingleFileTransferFileInfo& fileInfo,  		const FileTransferOptions& options,  		CryptoProvider* crypto) :  			JingleFileTransfer(session, toJID, transporterFactory), @@ -149,8 +149,8 @@ void OutgoingJingleFileTransfer::sendSessionInfoHash() {  	SWIFT_LOG(debug) << std::endl;  	JingleFileTransferHash::ref hashElement = boost::make_shared<JingleFileTransferHash>(); -	hashElement->setHash("sha-1", hashCalculator->getSHA1String()); -	hashElement->setHash("md5", hashCalculator->getMD5String()); +	hashElement->getFileInfo().addHash(HashElement("sha-1", hashCalculator->getSHA1Hash())); +	hashElement->getFileInfo().addHash(HashElement("md5", hashCalculator->getMD5Hash()));  	session->sendInfo(hashElement);  } @@ -162,7 +162,9 @@ void OutgoingJingleFileTransfer::handleLocalTransportCandidatesGenerated(  	fillCandidateMap(localCandidates, candidates);  	JingleFileTransferDescription::ref description = boost::make_shared<JingleFileTransferDescription>(); -	description->addOffer(fileInfo); +	fileInfo.addHash(HashElement("sha-1", ByteArray())); +	fileInfo.addHash(HashElement("md5", ByteArray())); +	description->setFileInfo(fileInfo);  	JingleS5BTransportPayload::ref transport = boost::make_shared<JingleS5BTransportPayload>();  	transport->setSessionID(s5bSessionID); diff --git a/Swiften/FileTransfer/OutgoingJingleFileTransfer.h b/Swiften/FileTransfer/OutgoingJingleFileTransfer.h index c21c50b..f022b9f 100644 --- a/Swiften/FileTransfer/OutgoingJingleFileTransfer.h +++ b/Swiften/FileTransfer/OutgoingJingleFileTransfer.h @@ -5,7 +5,7 @@   */  /* - * Copyright (c) 2013 Isode Limited. + * Copyright (c) 2013-2014 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */ @@ -18,7 +18,7 @@  #include <Swiften/Base/API.h>  #include <Swiften/Base/Override.h>  #include <Swiften/Jingle/JingleContentID.h> -#include <Swiften/Elements/StreamInitiationFileInfo.h> +#include <Swiften/Elements/JingleFileTransferFileInfo.h>  #include <Swiften/FileTransfer/OutgoingFileTransfer.h>  #include <Swiften/FileTransfer/JingleFileTransfer.h>  #include <Swiften/FileTransfer/FileTransferOptions.h> @@ -40,7 +40,7 @@ namespace Swift {  				boost::shared_ptr<ReadBytestream>,  				FileTransferTransporterFactory*,  				IDGenerator*, -				const StreamInitiationFileInfo&, +				const JingleFileTransferFileInfo&,  				const FileTransferOptions&,  				CryptoProvider*);  			virtual ~OutgoingJingleFileTransfer(); @@ -99,7 +99,7 @@ namespace Swift {  		private:  			IDGenerator* idGenerator;  			boost::shared_ptr<ReadBytestream> stream; -			StreamInitiationFileInfo fileInfo; +			JingleFileTransferFileInfo fileInfo;  			FileTransferOptions options;  			JingleContentID contentID;  			IncrementalBytestreamHashCalculator* hashCalculator; diff --git a/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp b/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp index a296b33..207f590 100644 --- a/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp +++ b/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp @@ -5,7 +5,7 @@   */  /* - * Copyright (c) 2013 Isode Limited. + * Copyright (c) 2013-2014 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */ @@ -22,14 +22,20 @@  #include <Swiften/Elements/IBB.h>  #include <Swiften/Elements/JingleIBBTransportPayload.h>  #include <Swiften/Elements/JingleS5BTransportPayload.h> +#include <Swiften/Elements/JingleFileTransferDescription.h> +#include <Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h>  #include <Swiften/FileTransfer/ByteArrayWriteBytestream.h>  #include <Swiften/FileTransfer/IncomingJingleFileTransfer.h>  #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/Network/PlatformNetworkEnvironment.h>  #include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h>  #include <Swiften/Jingle/FakeJingleSession.h> +#include <Swiften/Network/NATTraverser.h>  #include <Swiften/Network/DummyTimerFactory.h>  #include <Swiften/EventLoop/DummyEventLoop.h>  #include <Swiften/Network/DummyConnectionFactory.h> +#include <Swiften/Network/DummyConnectionServerFactory.h>  #include <Swiften/Network/PlatformNATTraversalWorker.h>  #include <Swiften/Queries/IQRouter.h>  #include <Swiften/Crypto/CryptoProvider.h> @@ -42,53 +48,61 @@ using namespace boost;  class IncomingJingleFileTransferTest : public CppUnit::TestFixture {  		CPPUNIT_TEST_SUITE(IncomingJingleFileTransferTest); -		//CPPUNIT_TEST(test_AcceptOnyIBBSendsSessionAccept); -		//CPPUNIT_TEST(test_OnlyIBBTransferReceiveWorks); +		CPPUNIT_TEST(test_AcceptOnyIBBSendsSessionAccept); +		CPPUNIT_TEST(test_OnlyIBBTransferReceiveWorks);  		//CPPUNIT_TEST(test_AcceptFailingS5BFallsBackToIBB);  		CPPUNIT_TEST_SUITE_END();  public: -		// shared_ptr<IncomingJingleFileTransfer> createTestling() { -		// 	JID ourJID("our@jid.org/full"); -		// 	return boost::shared_ptr<IncomingJingleFileTransfer>(new IncomingJingleFileTransfer(ourJID, shared_ptr<JingleSession>(session), jingleContentPayload, fakeRJTCSF.get(), fakeLJTCF.get(), iqRouter, bytestreamRegistry, bytestreamProxy, timerFactory, crypto.get())); -		// } +		shared_ptr<IncomingJingleFileTransfer> createTestling() { +			JID ourJID("our@jid.org/full"); +			return boost::make_shared<IncomingJingleFileTransfer>(ourJID, shared_ptr<JingleSession>(session), jingleContentPayload, ftTransporterFactory, timerFactory, crypto.get()); +		} -		// IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) { -		// 	IQ::ref request = IQ::createRequest(IQ::Set, JID("foo@bar.com/baz"), id, ibb); -		// 	request->setFrom(from); -		// 	return request; -		// } +		IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) { +			IQ::ref request = IQ::createRequest(IQ::Set, JID("foo@bar.com/baz"), id, ibb); +			request->setFrom(from); +			return request; +		}  		void setUp() {  			crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());  			eventLoop = new DummyEventLoop();  			session = boost::make_shared<FakeJingleSession>("foo@bar.com/baz", "mysession"); -			// jingleContentPayload = make_shared<JingleContentPayload>(); +			jingleContentPayload = make_shared<JingleContentPayload>();  			// fakeRJTCSF = make_shared<FakeRemoteJingleTransportCandidateSelectorFactory>();  			// fakeLJTCF = make_shared<FakeLocalJingleTransportCandidateGeneratorFactory>(); -			// stanzaChannel = new DummyStanzaChannel(); -			// iqRouter = new IQRouter(stanzaChannel); -			// bytestreamRegistry = new SOCKS5BytestreamRegistry(); -			// timerFactory = new DummyTimerFactory(); -			// connectionFactory = new DummyConnectionFactory(eventLoop); -			// bytestreamProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory); +			stanzaChannel = new DummyStanzaChannel(); +			connectionFactory = new DummyConnectionFactory(eventLoop); +			serverConnectionFactory = new DummyConnectionServerFactory(eventLoop); +			iqRouter = new IQRouter(stanzaChannel); +			bytestreamRegistry = new SOCKS5BytestreamRegistry(); +			networkEnvironment = new PlatformNetworkEnvironment(); +			natTraverser = new PlatformNATTraversalWorker(eventLoop); +			bytestreamServerManager = new SOCKS5BytestreamServerManager(bytestreamRegistry, serverConnectionFactory, networkEnvironment, natTraverser); +			idGenerator = new SimpleIDGenerator(); +			timerFactory = new DummyTimerFactory(); +			bytestreamProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory); +			ftTransporterFactory = new DefaultFileTransferTransporterFactory(bytestreamRegistry, bytestreamServerManager, bytestreamProxy, idGenerator, connectionFactory, timerFactory, crypto.get(), iqRouter);  		}  		void tearDown() { -			// delete bytestreamProxy; -			// delete connectionFactory; -			// delete timerFactory; -			// delete bytestreamRegistry; -			// delete iqRouter; -			// delete stanzaChannel; +			delete ftTransporterFactory; +			delete bytestreamServerManager; +			delete bytestreamProxy; +			delete connectionFactory; +			delete timerFactory; +			delete bytestreamRegistry; +			delete iqRouter; +			delete stanzaChannel;  			delete eventLoop; +			Log::setLogLevel(Log::error);  		}  		// Tests whether IncomingJingleFileTransfer would accept a IBB only file transfer. -#if 0  		void test_AcceptOnyIBBSendsSessionAccept() {  			//1. create your test incoming file transfer  			shared_ptr<JingleFileTransferDescription> desc = make_shared<JingleFileTransferDescription>(); -			desc->addOffer(StreamInitiationFileInfo("foo.txt", "", 10)); +			desc->setFileInfo(JingleFileTransferFileInfo("foo.txt", "", 10));  			jingleContentPayload->addDescription(desc);  			JingleIBBTransportPayload::ref tpRef = make_shared<JingleIBBTransportPayload>();  			tpRef->setSessionID("mysession"); @@ -107,7 +121,7 @@ public:  		void test_OnlyIBBTransferReceiveWorks() {  			//1. create your test incoming file transfer  			shared_ptr<JingleFileTransferDescription> desc = make_shared<JingleFileTransferDescription>(); -			desc->addOffer(StreamInitiationFileInfo("file.txt", "", 10)); +			desc->setFileInfo(JingleFileTransferFileInfo("file.txt", "", 10));  			jingleContentPayload->addDescription(desc);  			JingleIBBTransportPayload::ref tpRef = make_shared<JingleIBBTransportPayload>();  			tpRef->setSessionID("mysession"); @@ -139,6 +153,8 @@ public:  			shared_ptr<ByteArrayWriteBytestream> byteStream = make_shared<ByteArrayWriteBytestream>();  			fileTransfer->accept(byteStream); +			// candidates are gathered +  			// check whether accept has been called  			FakeJingleSession::AcceptCall acceptCall = getCall<FakeJingleSession::AcceptCall>(0);  			CPPUNIT_ASSERT_EQUAL(payLoad->getSessionID(), acceptCall.payload->getSessionID()); @@ -149,7 +165,7 @@ public:  			CPPUNIT_ASSERT(s5bPayload->hasCandidateError());  			// indicate transport replace (Romeo) -			session->onTransportReplaceReceived(getContentID(), addJingleIBBPayload()); +			session->handleTransportReplaceReceived(getContentID(), addJingleIBBPayload());  			FakeJingleSession::AcceptTransportCall acceptTransportCall = getCall<FakeJingleSession::AcceptTransportCall>(2); @@ -158,16 +174,16 @@ public:  			stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a"));  			CPPUNIT_ASSERT(createByteArray("abc") == byteStream->getData());  		} - +#if 0  		void test_S5BTransferReceiveTest() {  			addFileTransferDescription();  			JingleS5BTransportPayload::ref payLoad = addJingleS5BPayload();  		} - +#endif  private:  	void addFileTransferDescription() {  		shared_ptr<JingleFileTransferDescription> desc = make_shared<JingleFileTransferDescription>(); -		desc->addOffer(StreamInitiationFileInfo("file.txt", "", 10)); +		desc->setFileInfo(JingleFileTransferFileInfo("file.txt", "", 10));  		jingleContentPayload->addDescription(desc);  	} @@ -196,23 +212,26 @@ private:  		CPPUNIT_ASSERT(cmd);  		return *cmd;  	} -#endif  private:  	EventLoop* eventLoop;  	boost::shared_ptr<CryptoProvider> crypto;  	boost::shared_ptr<FakeJingleSession> session; -#if 0  	shared_ptr<JingleContentPayload> jingleContentPayload; -	shared_ptr<FakeRemoteJingleTransportCandidateSelectorFactory> fakeRJTCSF; -	shared_ptr<FakeLocalJingleTransportCandidateGeneratorFactory> fakeLJTCF; +//	shared_ptr<FakeRemoteJingleTransportCandidateSelectorFactory> fakeRJTCSF; +//	shared_ptr<FakeLocalJingleTransportCandidateGeneratorFactory> fakeLJTCF; +	FileTransferTransporterFactory* ftTransporterFactory; +	SOCKS5BytestreamServerManager* bytestreamServerManager;  	DummyStanzaChannel* stanzaChannel;  	IQRouter* iqRouter;  	SOCKS5BytestreamRegistry* bytestreamRegistry;  	DummyConnectionFactory* connectionFactory; +	DummyConnectionServerFactory* serverConnectionFactory;  	SOCKS5BytestreamProxiesManager* bytestreamProxy;  	DummyTimerFactory* timerFactory; -#endif +	NetworkEnvironment* networkEnvironment; +	NATTraverser* natTraverser; +	IDGenerator* idGenerator;  };  CPPUNIT_TEST_SUITE_REGISTRATION(IncomingJingleFileTransferTest); diff --git a/Swiften/Jingle/FakeJingleSession.cpp b/Swiften/Jingle/FakeJingleSession.cpp index 1df106a..3b94da7 100644 --- a/Swiften/Jingle/FakeJingleSession.cpp +++ b/Swiften/Jingle/FakeJingleSession.cpp @@ -4,7 +4,14 @@   * See Documentation/Licenses/BSD-simplified.txt for more information.   */ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +  #include <Swiften/Jingle/FakeJingleSession.h> +#include <Swiften/Jingle/JingleSessionListener.h>  #include <boost/smart_ptr/make_shared.hpp> @@ -50,4 +57,8 @@ void FakeJingleSession::sendTransportReplace(const JingleContentID& id, JingleTr  	calledCommands.push_back(ReplaceTransportCall(id, payload));  } +void FakeJingleSession::handleTransportReplaceReceived(const JingleContentID& contentID, JingleTransportPayload::ref transport) { +	notifyListeners(&JingleSessionListener::handleTransportReplaceReceived, contentID, transport); +} +  } diff --git a/Swiften/Jingle/FakeJingleSession.h b/Swiften/Jingle/FakeJingleSession.h index 24e85d8..19028ad 100644 --- a/Swiften/Jingle/FakeJingleSession.h +++ b/Swiften/Jingle/FakeJingleSession.h @@ -5,7 +5,7 @@   */  /* - * Copyright (c) 2013 Isode Limited. + * Copyright (c) 2013-2014 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */ @@ -96,6 +96,8 @@ namespace Swift {  			virtual void sendTransportReject(const JingleContentID&, JingleTransportPayload::ref) SWIFTEN_OVERRIDE;  			virtual void sendTransportReplace(const JingleContentID&, JingleTransportPayload::ref) SWIFTEN_OVERRIDE; +			void handleTransportReplaceReceived(const JingleContentID&, JingleTransportPayload::ref); +  		public:  			std::vector<Command> calledCommands;  			SimpleIDGenerator idGenerator; diff --git a/Swiften/Network/DummyConnectionServer.h b/Swiften/Network/DummyConnectionServer.h new file mode 100644 index 0000000..0cbce0e --- /dev/null +++ b/Swiften/Network/DummyConnectionServer.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2010-2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/enable_shared_from_this.hpp> + +#include <Swiften/Base/API.h> +#include <Swiften/Network/ConnectionServer.h> +#include <Swiften/Network/HostAddressPort.h> +#include <Swiften/EventLoop/EventLoop.h> +#include <Swiften/EventLoop/EventOwner.h> + +namespace Swift { +	class SWIFTEN_API DummyConnectionServer : public ConnectionServer, public EventOwner, public boost::enable_shared_from_this<DummyConnectionServer> { +		public: +			DummyConnectionServer(EventLoop* eventLoop, int port) : eventLoop(eventLoop), localAddressPort(HostAddress(), port) {} +			DummyConnectionServer(EventLoop* eventLoop, const Swift::HostAddress& hostAddress, int port) : eventLoop(eventLoop), localAddressPort(hostAddress, port) {} +			virtual ~DummyConnectionServer() {} + +			virtual HostAddressPort getAddressPort() const { +				return localAddressPort; +			} + +			virtual boost::optional<Error> tryStart() { +				return boost::optional<Error>(); +			} + +			virtual void start() { + +			} + +			virtual void stop() { + +			} + +		public: +			EventLoop* eventLoop; +			HostAddressPort localAddressPort; +	}; +} diff --git a/Swiften/Network/DummyConnectionServerFactory.h b/Swiften/Network/DummyConnectionServerFactory.h new file mode 100644 index 0000000..6369452 --- /dev/null +++ b/Swiften/Network/DummyConnectionServerFactory.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/smart_ptr/make_shared.hpp> + +#include <Swiften/Network/ConnectionServerFactory.h> +#include <Swiften/Network/DummyConnectionServer.h> + +namespace Swift { + +class EventLoop; + +class DummyConnectionServerFactory : public ConnectionServerFactory { +public: +	DummyConnectionServerFactory(EventLoop* eventLoop) : eventLoop(eventLoop) {} +	virtual ~DummyConnectionServerFactory() {} + +	virtual boost::shared_ptr<ConnectionServer> createConnectionServer(int port) { +		return boost::make_shared<DummyConnectionServer>(eventLoop, port); +	} + +	virtual boost::shared_ptr<ConnectionServer> createConnectionServer(const Swift::HostAddress& hostAddress, int port) { +		return boost::make_shared<DummyConnectionServer>(eventLoop, hostAddress, port); +	} + +private: +	EventLoop* eventLoop; +}; + +} diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp index fe61c72..812e968 100644 --- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp +++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp @@ -78,6 +78,7 @@  #include <Swiften/Parser/PayloadParsers/StatusShowParser.h>  #include <Swiften/Parser/PayloadParsers/StorageParser.h>  #include <Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.h> +#include <Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h>  #include <Swiften/Parser/PayloadParsers/StreamInitiationParser.h>  #include <Swiften/Parser/PayloadParsers/SubjectParser.h>  #include <Swiften/Parser/PayloadParsers/UserLocationParser.h> @@ -140,6 +141,7 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() {  	factories_.push_back(boost::make_shared<GenericPayloadParserFactory<JingleS5BTransportMethodPayloadParser> >("transport", "urn:xmpp:jingle:transports:s5b:1"));  	factories_.push_back(boost::make_shared<JingleFileTransferDescriptionParserFactory>(this));  	factories_.push_back(boost::make_shared<GenericPayloadParserFactory<StreamInitiationFileInfoParser> >("file", "http://jabber.org/protocol/si/profile/file-transfer")); +	factories_.push_back(boost::make_shared<GenericPayloadParserFactory<JingleFileTransferFileInfoParser> >("file", "urn:xmpp:jingle:apps:file-transfer:4"));  	factories_.push_back(boost::make_shared<GenericPayloadParserFactory<JingleFileTransferReceivedParser> >("received", "urn:xmpp:jingle:apps:file-transfer:3"));  	factories_.push_back(boost::make_shared<GenericPayloadParserFactory<JingleFileTransferHashParser> >("checksum"));  	factories_.push_back(boost::make_shared<GenericPayloadParserFactory<S5BProxyRequestParser> >("query", "http://jabber.org/protocol/bytestreams")); diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.cpp b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.cpp index b394115..fb1836f 100644 --- a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.cpp +++ b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.cpp @@ -4,72 +4,59 @@   * See Documentation/Licenses/BSD-simplified.txt for more information.   */ -#include "JingleFileTransferDescriptionParser.h" +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h> + +#include <boost/optional.hpp> +#include <boost/lexical_cast.hpp>  #include <Swiften/Parser/PayloadParserFactoryCollection.h>  #include <Swiften/Parser/PayloadParserFactory.h> -#include <Swiften/Base/Log.h> +#include <Swiften/Base/DateTime.h> +#include <Swiften/StringCodecs/Base64.h>  namespace Swift { -JingleFileTransferDescriptionParser::JingleFileTransferDescriptionParser(PayloadParserFactoryCollection* factories) :   factories(factories), level(0), -															currentElement(UnknownElement) { -	 +JingleFileTransferDescriptionParser::JingleFileTransferDescriptionParser(PayloadParserFactoryCollection* factories) :   factories(factories), level(0) {  }  void JingleFileTransferDescriptionParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { -	if (level == 0) { -		 -	} -	  	if (level == 1) { -		if (element == "offer") { -			currentElement = OfferElement; -		} else if (element == "request") { -			currentElement = RequestElement; -		} else { -			currentElement = UnknownElement; -		} -	} - -	if (level == 2) {  		PayloadParserFactory* payloadParserFactory = factories->getPayloadParserFactory(element, ns, attributes);  		if (payloadParserFactory) {  			currentPayloadParser.reset(payloadParserFactory->createPayloadParser());  		}  	} -	if (level >= 2 && currentPayloadParser) { +	if (level >= 1 && currentPayloadParser) {  		currentPayloadParser->handleStartElement(element, ns, attributes);  	} -  	++level;  }  void JingleFileTransferDescriptionParser::handleEndElement(const std::string& element, const std::string& ns) {  	--level; -	if (currentPayloadParser) {  -		if (level >= 2) { -			currentPayloadParser->handleEndElement(element, ns); -		} +	if (level >= 1 && currentPayloadParser) { +		currentPayloadParser->handleEndElement(element, ns); +	} -		if (level == 2) { -			boost::shared_ptr<StreamInitiationFileInfo> info = boost::dynamic_pointer_cast<StreamInitiationFileInfo>(currentPayloadParser->getPayload()); -			if (info) { -				if (currentElement == OfferElement) { -					getPayloadInternal()->addOffer(*info); -				} else if (currentElement == RequestElement) { -					getPayloadInternal()->addRequest(*info); -				} -			} +	if (level == 0) { +		boost::shared_ptr<JingleFileTransferFileInfo> info = boost::dynamic_pointer_cast<JingleFileTransferFileInfo>(currentPayloadParser->getPayload()); +		if (info) { +			getPayloadInternal()->setFileInfo(*info);  		}  	}  }  void JingleFileTransferDescriptionParser::handleCharacterData(const std::string& data) { -	if (level >= 2 && currentPayloadParser) { +	if (level >= 1 && currentPayloadParser) {  		currentPayloadParser->handleCharacterData(data);  	}  } -		 +  } diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h index 7ea22b4..a1215c1 100644 --- a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h +++ b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h @@ -4,6 +4,12 @@   * See Documentation/Licenses/BSD-simplified.txt for more information.   */ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +  #pragma once  #include <Swiften/Elements/JingleFileTransferDescription.h> @@ -20,18 +26,11 @@ class JingleFileTransferDescriptionParser : public GenericPayloadParser<JingleFi  		virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes);  		virtual void handleEndElement(const std::string& element, const std::string&); -		virtual void handleCharacterData(const std::string& data);	 +		virtual void handleCharacterData(const std::string& data);  	private: -		enum CurrentParseElement { -			UnknownElement, -			RequestElement, -			OfferElement -		}; -		  		PayloadParserFactoryCollection* factories;  		int level; -		CurrentParseElement currentElement;  		boost::shared_ptr<PayloadParser> currentPayloadParser;  }; diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParserFactory.h b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParserFactory.h index b997c1d..7bd4b8a 100644 --- a/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParserFactory.h +++ b/Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParserFactory.h @@ -4,6 +4,12 @@   * See Documentation/Licenses/BSD-simplified.txt for more information.   */ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +  #pragma once  #include <Swiften/Parser/GenericPayloadParserFactory.h> @@ -19,7 +25,7 @@ namespace Swift {  			}  			virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { -				return element == "description" && ns == "urn:xmpp:jingle:apps:file-transfer:3"; +				return element == "description" && ns == "urn:xmpp:jingle:apps:file-transfer:4";  			}  			virtual PayloadParser* createPayloadParser() { diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.cpp b/Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.cpp new file mode 100644 index 0000000..2a62f23 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h> + +#include <boost/optional.hpp> +#include <boost/lexical_cast.hpp> + +#include <Swiften/Base/DateTime.h> +#include <Swiften/StringCodecs/Base64.h> + +namespace Swift { + +JingleFileTransferFileInfoParser::JingleFileTransferFileInfoParser() : level(0) {	 +} + +template<typename T> boost::optional<T> safeLexicalCast(const std::string& str) { +	boost::optional<T> ret; +	try { +		ret = boost::lexical_cast<T>(str); +	} catch (boost::bad_lexical_cast &) { + +	} +	return ret; +} + +void JingleFileTransferFileInfoParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { +	charData.clear(); +	if (element == "hash") { +		hashAlg = attributes.getAttributeValue("algo").get_value_or(""); +	} +	else if (element == "range") { +		rangeOffset = safeLexicalCast<boost::uintmax_t>(attributes.getAttributeValue("offset").get_value_or("")); +	} + +	++level; +} + +void JingleFileTransferFileInfoParser::handleEndElement(const std::string& element, const std::string&) { +	--level; +	if (level == 1) { +		if (element == "date") { +			getPayloadInternal()->setDate(stringToDateTime(charData)); +		} +		else if (element == "desc") { +			getPayloadInternal()->setDescription(charData); +		} +		else if (element == "media-type") { +			getPayloadInternal()->setMediaType(charData); +		} +		else if (element == "name") { +			getPayloadInternal()->setName(charData); +		} +		else if (element == "size") { +			boost::optional<boost::uintmax_t> size = safeLexicalCast<boost::uintmax_t>(charData); +			if (size) { +				getPayloadInternal()->setSize(size.get()); +			} +		} +		else if (element == "range") { +			getPayloadInternal()->setSupportsRangeRequests(true); +			if (rangeOffset) { +				getPayloadInternal()->setRangeOffset(rangeOffset.get_value_or(0)); +			} +		} +		else if (element == "hash") { +			getPayloadInternal()->addHash(HashElement(hashAlg, Base64::decode(charData))); +		} +	} +} + +void JingleFileTransferFileInfoParser::handleCharacterData(const std::string& data) { +	charData += data; +} + +} diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h b/Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h new file mode 100644 index 0000000..eb6245c --- /dev/null +++ b/Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Elements/JingleFileTransferFileInfo.h> +#include <Swiften/Parser/GenericPayloadParser.h> + +namespace Swift { + +class JingleFileTransferFileInfoParser : public GenericPayloadParser<JingleFileTransferFileInfo> { +	public: +		JingleFileTransferFileInfoParser(); + +		virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes); +		virtual void handleEndElement(const std::string& element, const std::string&); +		virtual void handleCharacterData(const std::string& data); +		 +	private: +		int level; +		std::string charData; +		std::string hashAlg; +		boost::optional<boost::uintmax_t> rangeOffset; +}; + +} diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.cpp b/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.cpp index 87f8317..6a1a031 100644 --- a/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.cpp +++ b/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.cpp @@ -4,39 +4,54 @@   * See Documentation/Licenses/BSD-simplified.txt for more information.   */ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +  #include "JingleFileTransferHashParser.h"  #include <boost/shared_ptr.hpp>  #include <boost/algorithm/string.hpp> -#include <Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.h> +#include <Swiften/Parser/PayloadParsers/JingleFileTransferFileInfoParser.h>  #include <Swiften/Parser/GenericPayloadParserFactory.h>  #include <Swiften/Parser/PayloadParserFactory.h>  namespace Swift { -JingleFileTransferHashParser::JingleFileTransferHashParser() { +JingleFileTransferHashParser::JingleFileTransferHashParser() : level(0) {  } -void JingleFileTransferHashParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) { -	if (element == "hash") { -		algo = attributes.getAttribute("algo"); +void JingleFileTransferHashParser::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { +	if (level == 1 && element == "file") { +		currentPayloadParser = boost::make_shared<JingleFileTransferFileInfoParser>();  	} + +	if (level >= 1 && currentPayloadParser) { +		currentPayloadParser->handleStartElement(element, ns, attributes); +	} +	++level;  } -void JingleFileTransferHashParser::handleEndElement(const std::string& element, const std::string& ) { -	if (element == "hash" && !algo.empty() && !hash.empty()) { -		getPayloadInternal()->setHash(algo, hash); -		algo.clear(); -		hash.clear(); +void JingleFileTransferHashParser::handleEndElement(const std::string& element, const std::string& ns) { +	--level; +	if (level >= 1 && currentPayloadParser) { +		currentPayloadParser->handleEndElement(element, ns); +	} + +	if (level == 1) { +		boost::shared_ptr<JingleFileTransferFileInfo> info = boost::dynamic_pointer_cast<JingleFileTransferFileInfo>(currentPayloadParser->getPayload()); +		if (info) { +			getPayloadInternal()->setFileInfo(*info); +		}  	}  }  void JingleFileTransferHashParser::handleCharacterData(const std::string& data) { -	if (!algo.empty()) { -		std::string new_data(data); -		boost::trim(new_data); -		hash += new_data; +	if (level >= 1 && currentPayloadParser) { +		currentPayloadParser->handleCharacterData(data);  	}  } diff --git a/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.h b/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.h index 35e4a05..5a7c6c5 100644 --- a/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.h +++ b/Swiften/Parser/PayloadParsers/JingleFileTransferHashParser.h @@ -4,6 +4,12 @@   * See Documentation/Licenses/BSD-simplified.txt for more information.   */ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +  #pragma once  #include <Swiften/Elements/JingleFileTransferHash.h> @@ -20,8 +26,8 @@ public:  	virtual void handleCharacterData(const std::string& data);  private: -	std::string algo; -	std::string hash; +	int level; +	boost::shared_ptr<PayloadParser> currentPayloadParser;  };  } diff --git a/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp b/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp index cc69348..b3888d6 100644 --- a/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp +++ b/Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.cpp @@ -4,7 +4,13 @@   * See Documentation/Licenses/BSD-simplified.txt for more information.   */ -#include "StreamInitiationFileInfoParser.h" +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Parser/PayloadParsers/StreamInitiationFileInfoParser.h>  #include <boost/optional.hpp>  #include <boost/lexical_cast.hpp> diff --git a/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp index 8c8601a..a6be599 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/JingleParserTest.cpp @@ -16,7 +16,7 @@  #include <Swiften/Elements/JingleFileTransferReceived.h>  #include <Swiften/Elements/JingleFileTransferHash.h>  #include <Swiften/Base/DateTime.h> - +#include <Swiften/StringCodecs/Base64.h>  #include <Swiften/Base/Log.h>  using namespace Swift; @@ -36,8 +36,6 @@ class JingleParserTest : public CppUnit::TestFixture {  		CPPUNIT_TEST(testParse_Xep0234_Example5);  		CPPUNIT_TEST(testParse_Xep0234_Example8);  		CPPUNIT_TEST(testParse_Xep0234_Example10); -		CPPUNIT_TEST(testParse_Xep0234_Example11); -		CPPUNIT_TEST(testParse_Xep0234_Example12);  		CPPUNIT_TEST(testParse_Xep0260_Example1);  		CPPUNIT_TEST(testParse_Xep0260_Example3); @@ -223,40 +221,39 @@ class JingleParserTest : public CppUnit::TestFixture {  			PayloadsParserTester parser;  			CPPUNIT_ASSERT(parser.parse(  				"<jingle xmlns='urn:xmpp:jingle:1'\n" -				"          action='session-initiate'\n" -				"          initiator='romeo@montague.lit/orchard'\n" -				"          sid='851ba2'>\n" -				"    <content creator='initiator' name='a-file-offer'>\n" -				"      <description xmlns='urn:xmpp:jingle:apps:file-transfer:3'>\n" -				"        <offer>\n" -				"          <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n" -				"                date='1969-07-21T02:56:15Z'\n" -				"                hash='552da749930852c69ae5d2141d3766b1'\n" -				"                name='test.txt'\n" -				"                size='1022'>\n" -				"            <desc>This is a test. If this were a real file...</desc>\n" -				"            <range/>\n" -				"          </file>\n" -				"        </offer>\n" -				"      </description>\n" -				"      <transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n" -				"                 mode='tcp'\n" -				"                 sid='vj3hs98y'>\n" -				"        <candidate cid='hft54dqy'\n" -				"                   host='192.168.4.1'\n" -				"                   jid='romeo@montague.lit/orchard'\n" -				"                   port='5086'\n" -				"                   priority='8257636'\n" -				"                   type='direct'/>\n" -				"        <candidate cid='hutr46fe'\n" -				"                   host='24.24.24.1'\n" -				"                   jid='romeo@montague.lit/orchard'\n" -				"                   port='5087'\n" -				"                   priority='8258636'\n" -				"                   type='direct'/>\n" -				"      </transport>\n" -				"    </content>\n" -				"  </jingle>\n" +					" action='session-initiate'\n" +					" initiator='romeo@montague.lit/orchard'\n" +					" sid='851ba2'>\n" +					"<content creator='initiator' name='a-file-offer'>\n" +						"<description xmlns='urn:xmpp:jingle:apps:file-transfer:4'>\n" +							"<file>\n" +								"<date>1969-07-21T02:56:15Z</date>\n" +								"<desc>This is a test. If this were a real file...</desc>\n" +								"<media-type>text/plain</media-type>\n" +								"<name>test.txt</name>\n" +								"<range/>\n" +								"<size>1022</size>\n" +								"<hash xmlns='urn:xmpp:hashes:1' algo='sha-1'>VS2nSZMIUsaa5dIUHTdmsQ==</hash>\n" +							"</file>\n" +						"</description>\n" +						"<transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n" +							" mode='tcp'\n" +							" sid='vj3hs98y'>\n" +							"<candidate cid='hft54dqy'\n" +								" host='192.168.4.1'\n" +								" jid='romeo@montague.lit/orchard'\n" +								" port='5086'\n" +								" priority='8257636'\n" +								" type='direct'/>\n" +							"<candidate cid='hutr46fe'\n" +								" host='24.24.24.1'\n" +								" jid='romeo@montague.lit/orchard'\n" +								" port='5087'\n" +								" priority='8258636'\n" +								" type='direct'/>\n" +						"</transport>\n" +					"</content>\n" +				"</jingle>\n"  			));  			JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); @@ -270,16 +267,15 @@ class JingleParserTest : public CppUnit::TestFixture {  			JingleFileTransferDescription::ref description = contents[0]->getDescription<JingleFileTransferDescription>(); -			 -			std::vector<StreamInitiationFileInfo> offers = description->getOffers(); -			CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), offers.size()); -			CPPUNIT_ASSERT_EQUAL(std::string("test.txt"), offers[0].getName()); -			CPPUNIT_ASSERT_EQUAL(std::string("552da749930852c69ae5d2141d3766b1"), offers[0].getHash()); -			CPPUNIT_ASSERT(1022 == offers[0].getSize()); -			CPPUNIT_ASSERT_EQUAL(std::string("This is a test. If this were a real file..."), offers[0].getDescription()); -			CPPUNIT_ASSERT_EQUAL(true, offers[0].getSupportsRangeRequests()); -			CPPUNIT_ASSERT(stringToDateTime("1969-07-21T02:56:15Z") == offers[0].getDate()); -			CPPUNIT_ASSERT_EQUAL(std::string("md5"), offers[0].getAlgo());	 +			CPPUNIT_ASSERT(description); +			JingleFileTransferFileInfo fileInfo = description->getFileInfo(); +			CPPUNIT_ASSERT_EQUAL(std::string("test.txt"), fileInfo.getName()); +			CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), fileInfo.getHashes().begin()->first); +			CPPUNIT_ASSERT_EQUAL(std::string("VS2nSZMIUsaa5dIUHTdmsQ=="), Base64::encode(fileInfo.getHashes().begin()->second)); +			CPPUNIT_ASSERT(1022 == fileInfo.getSize()); +			CPPUNIT_ASSERT_EQUAL(std::string("This is a test. If this were a real file..."), fileInfo.getDescription()); +			CPPUNIT_ASSERT_EQUAL(true, fileInfo.getSupportsRangeRequests()); +			CPPUNIT_ASSERT(stringToDateTime("1969-07-21T02:56:15Z") == fileInfo.getDate());  		}  		// http://xmpp.org/extensions/xep-0234.html#example-3 @@ -287,22 +283,21 @@ class JingleParserTest : public CppUnit::TestFixture {  			PayloadsParserTester parser;  			CPPUNIT_ASSERT(parser.parse(  				"<jingle xmlns='urn:xmpp:jingle:1'\n" -				"        action='session-accept'\n" -				"        initiator='romeo@montague.lit/orchard'\n" -				"        sid='851ba2'>\n" -				"  <content creator='initiator' name='a-file-offer'>\n" -				"    <description xmlns='urn:xmpp:jingle:apps:file-transfer:3'>\n" -				"      <offer>\n" -				"        <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n" -				"              name='test.txt'\n" -				"              size='1022'\n" -				"              hash='552da749930852c69ae5d2141d3766b1'\n" -				"              date='1969-07-21T02:56:15Z'>\n" -				"          <desc>This is a test. If this were a real file...</desc>\n" -				"          <range/>\n" -				"        </file>\n" -				"      </offer>\n" -				"    </description>\n" +					" action='session-accept'\n" +					" initiator='romeo@montague.lit/orchard'\n" +					" sid='851ba2'>\n" +					"<content creator='initiator' name='a-file-offer'>\n" +						"<description xmlns='urn:xmpp:jingle:apps:file-transfer:4'>\n" +							"<file>\n" +								"<date>1969-07-21T02:56:15Z</date>\n" +								"<desc>This is a test. If this were a real file...</desc>\n" +								"<media-type>text/plain</media-type>\n" +								"<name>test.txt</name>\n" +								"<range/>\n" +								"<size>1022</size>\n" +								"<hash xmlns='urn:xmpp:hashes:1' algo='sha-1'>VS2nSZMIUsaa5dIUHTdmsQ==</hash>\n" +							"</file>\n" +						"</description>\n"  				"    <transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n"  				"               mode='tcp'\n"  				"               sid='vj3hs98y'>\n" @@ -340,16 +335,16 @@ class JingleParserTest : public CppUnit::TestFixture {  			JingleFileTransferDescription::ref description = contents[0]->getDescription<JingleFileTransferDescription>(); +			CPPUNIT_ASSERT(description); -			std::vector<StreamInitiationFileInfo> offers = description->getOffers(); -			CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), offers.size()); -			CPPUNIT_ASSERT_EQUAL(std::string("test.txt"), offers[0].getName()); -			CPPUNIT_ASSERT_EQUAL(std::string("552da749930852c69ae5d2141d3766b1"), offers[0].getHash()); -			CPPUNIT_ASSERT(1022 == offers[0].getSize()); -			CPPUNIT_ASSERT_EQUAL(std::string("This is a test. If this were a real file..."), offers[0].getDescription()); -			CPPUNIT_ASSERT_EQUAL(true, offers[0].getSupportsRangeRequests()); -			CPPUNIT_ASSERT(stringToDateTime("1969-07-21T02:56:15Z") == offers[0].getDate()); -			CPPUNIT_ASSERT_EQUAL(std::string("md5"), offers[0].getAlgo()); +			JingleFileTransferFileInfo fileInfo = description->getFileInfo(); +			CPPUNIT_ASSERT_EQUAL(std::string("test.txt"), fileInfo.getName()); +			CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), fileInfo.getHashes().begin()->first); +			CPPUNIT_ASSERT_EQUAL(std::string("VS2nSZMIUsaa5dIUHTdmsQ=="), Base64::encode(fileInfo.getHashes().begin()->second)); +			CPPUNIT_ASSERT(1022 == fileInfo.getSize()); +			CPPUNIT_ASSERT_EQUAL(std::string("This is a test. If this were a real file..."), fileInfo.getDescription()); +			CPPUNIT_ASSERT_EQUAL(true, fileInfo.getSupportsRangeRequests()); +			CPPUNIT_ASSERT(stringToDateTime("1969-07-21T02:56:15Z") == fileInfo.getDate());  		}  		// http://xmpp.org/extensions/xep-0234.html#example-5 @@ -393,11 +388,9 @@ class JingleParserTest : public CppUnit::TestFixture {  				"        action='session-info'\n"  				"        initiator='romeo@montague.lit/orchard'\n"  				"        sid='a73sjjvkla37jfea'>\n" -				"	<checksum xmlns='urn:xmpp:jingle:apps:file-transfer:3'>\n" +				"	<checksum xmlns='urn:xmpp:jingle:apps:file-transfer:4'>\n"  				"	  <file>\n" -				"	    <hashes xmlns='urn:xmpp:hashes:0'>\n" -				"	      <hash algo='sha-1'>552da749930852c69ae5d2141d3766b1</hash>\n" -				"	    </hashes>\n" +				"	      <hash xmlns='urn:xmpp:hashes:0' algo='sha-1'>VS2nSZMIUsaa5dIUHTdmsQ==</hash>\n"  				"	  </file>\n"  				"	</checksum>\n"  				"</jingle>\n" @@ -410,12 +403,12 @@ class JingleParserTest : public CppUnit::TestFixture {  			JingleFileTransferHash::ref hash = jingle->getPayload<JingleFileTransferHash>();  			CPPUNIT_ASSERT(hash); -			CPPUNIT_ASSERT_EQUAL(std::string("552da749930852c69ae5d2141d3766b1"), hash->getHashes().find("sha-1")->second); -			 +			CPPUNIT_ASSERT_EQUAL(std::string("VS2nSZMIUsaa5dIUHTdmsQ=="), Base64::encode(hash->getFileInfo().getHash("sha-1").get()));  		}  		// http://xmpp.org/extensions/xep-0234.html#example-10  		void testParse_Xep0234_Example10() { +			Log::setLogLevel(Log::debug);  			PayloadsParserTester parser;  			CPPUNIT_ASSERT(parser.parse(  				"<jingle xmlns='urn:xmpp:jingle:1'\n" @@ -423,13 +416,11 @@ class JingleParserTest : public CppUnit::TestFixture {  				"        initiator='romeo@montague.lit/orchard'\n"  				"        sid='uj3b2'>\n"  				"  <content creator='initiator' name='a-file-request'>\n" -				"    <description xmlns='urn:xmpp:jingle:apps:file-transfer:3'>\n" -				"      <request>\n" -				"        <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n" -				"              hash='552da749930852c69ae5d2141d3766b1'>\n" -				"          <range offset='270336'/>\n" -				"        </file>\n" -				"      </request>\n" +				"    <description xmlns='urn:xmpp:jingle:apps:file-transfer:4'>\n" +				"      <file>\n" +				"        <hash xmlns='urn:xmpp:hashes:1' algo='sha-1'>VS2nSZMIUsaa5dIUHTdmsQ==</hash>\n" +				"        <range offset='270336'/>\n" +				"      </file>\n"  				"    </description>\n"  				"    <transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n"  				"               mode='tcp'\n" @@ -466,101 +457,13 @@ class JingleParserTest : public CppUnit::TestFixture {  			JingleContentPayload::ref content = jingle->getPayload<JingleContentPayload>();  			CPPUNIT_ASSERT(content); -			StreamInitiationFileInfo file = content->getDescription<JingleFileTransferDescription>()->getRequests()[0]; -			CPPUNIT_ASSERT_EQUAL(std::string("552da749930852c69ae5d2141d3766b1"), file.getHash()); -			CPPUNIT_ASSERT_EQUAL(static_cast<unsigned long long>(270336), file.getRangeOffset()); +			JingleFileTransferFileInfo file = content->getDescription<JingleFileTransferDescription>()->getFileInfo(); +			CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), file.getHashes().begin()->first); +			CPPUNIT_ASSERT_EQUAL(std::string("VS2nSZMIUsaa5dIUHTdmsQ=="), Base64::encode(file.getHashes().begin()->second)); +			CPPUNIT_ASSERT_EQUAL(static_cast<boost::uintmax_t>(270336), file.getRangeOffset());  			CPPUNIT_ASSERT_EQUAL(true, file.getSupportsRangeRequests());  		} -		// http://xmpp.org/extensions/xep-0234.html#example-11 -		void testParse_Xep0234_Example11() { -			PayloadsParserTester parser; -			CPPUNIT_ASSERT(parser.parse( -				"<jingle xmlns='urn:xmpp:jingle:1'\n" -				"        action='session-initiate'\n" -				"        initiator='romeo@montague.lit/orchard'\n" -				"        sid='h2va419i'>\n" -				"  <content creator='initiator' name='a-file-offer'>\n" -				"    <description xmlns='urn:xmpp:jingle:apps:file-transfer:3'>\n" -				"      <offer>\n" -				"        <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n" -				"              date='2011-06-01T15:58:15Z'\n" -				"              hash='a749930852c69ae5d2141d3766b1552d'\n" -				"              name='somefile.txt'\n" -				"              size='1234'/>\n" -				"        <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n" -				"              date='2011-06-01T15:58:15Z'\n" -				"              hash='930852c69ae5d2141d3766b1552da749'\n" -				"              name='anotherfile.txt'\n" -				"              size='2345'/>\n" -				"        <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n" -				"              date='2011-06-01T15:58:15Z'\n" -				"              hash='52c69ae5d2141d3766b1552da7499308'\n" -				"              name='yetanotherfile.txt'\n" -				"              size='3456'/>\n" -				"      </offer>\n" -				"    </description>\n" -				"    <transport xmlns='urn:xmpp:jingle:transports:s5b:1'\n" -				"               mode='tcp'\n" -				"               sid='vj3hs98y'>\n" -				"      <candidate cid='hft54dqy'\n" -				"                 host='192.168.4.1'\n" -				"                 jid='romeo@montague.lit/orchard'\n" -				"                 port='5086'\n" -				"                 priority='8257636'\n" -				"                 type='direct'/>\n" -				"      <candidate cid='hutr46fe'\n" -				"                 host='24.24.24.1'\n" -				"                 jid='romeo@montague.lit/orchard'\n" -				"                 port='5087'\n" -				"                 priority='8258636'\n" -				"                 type='direct'/>\n" -				"    </transport>\n" -				"  </content>\n" -				"</jingle>\n"			 -			)); -			 -			JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); -			CPPUNIT_ASSERT(jingle); -			CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionInitiate, jingle->getAction()); -			CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); -			CPPUNIT_ASSERT_EQUAL(std::string("h2va419i"), jingle->getSessionID()); -			 -			JingleContentPayload::ref content = jingle->getPayload<JingleContentPayload>(); -			CPPUNIT_ASSERT(content); -			CPPUNIT_ASSERT_EQUAL(JingleContentPayload::InitiatorCreator, content->getCreator()); -			CPPUNIT_ASSERT_EQUAL(std::string("a-file-offer"), content->getName()); -			 -			std::vector<StreamInitiationFileInfo> offers = content->getDescription<JingleFileTransferDescription>()->getOffers(); -			CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), offers.size()); -		} -		 -		// http://xmpp.org/extensions/xep-0234.html#example-12 -		void testParse_Xep0234_Example12() { -			PayloadsParserTester parser; -			CPPUNIT_ASSERT(parser.parse( -				"<jingle xmlns='urn:xmpp:jingle:1'\n" -				"        action='session-info'\n" -				"        initiator='romeo@montague.lit/orchard'\n" -				"        sid='a73sjjvkla37jfea'>\n" -				"  <received xmlns='urn:xmpp:jingle:apps:file-transfer:3'>\n" -				"    <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'\n" -				"          hash='a749930852c69ae5d2141d3766b1552d'/>\n" -				"  </received>\n" -				"</jingle>\n" -			)); -			 -			JinglePayload::ref jingle = parser.getPayload<JinglePayload>(); -			CPPUNIT_ASSERT(jingle); -			CPPUNIT_ASSERT_EQUAL(JinglePayload::SessionInfo, jingle->getAction()); -			CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.lit/orchard"), jingle->getInitiator()); -			CPPUNIT_ASSERT_EQUAL(std::string("a73sjjvkla37jfea"), jingle->getSessionID()); -			 -			boost::shared_ptr<JingleFileTransferReceived> received = jingle->getPayload<JingleFileTransferReceived>(); -			CPPUNIT_ASSERT(received); -			CPPUNIT_ASSERT_EQUAL(std::string("a749930852c69ae5d2141d3766b1552d"), received->getFileInfo().getHash());			 -		} -		  		// http://xmpp.org/extensions/xep-0260.html#example-1  		void testParse_Xep0260_Example1() {  			PayloadsParserTester parser; diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript index 94ea6d3..4bdf66f 100644 --- a/Swiften/Parser/SConscript +++ b/Swiften/Parser/SConscript @@ -38,6 +38,7 @@ sources = [  		"PayloadParsers/JingleFileTransferDescriptionParser.cpp",  		"PayloadParsers/JingleFileTransferReceivedParser.cpp",  		"PayloadParsers/JingleFileTransferHashParser.cpp", +		"PayloadParsers/JingleFileTransferFileInfoParser.cpp",  		"PayloadParsers/StreamInitiationFileInfoParser.cpp",  		"PayloadParsers/CommandParser.cpp",  		"PayloadParsers/InBandRegistrationPayloadParser.cpp", diff --git a/Swiften/SConscript b/Swiften/SConscript index 877b084..147f7a6 100644 --- a/Swiften/SConscript +++ b/Swiften/SConscript @@ -235,6 +235,7 @@ if env["SCONS_STAGE"] == "build" :  			"Serializer/PayloadSerializers/MAMResultSerializer.cpp",  			"Serializer/PayloadSerializers/MAMQuerySerializer.cpp",  			"Serializer/PayloadSerializers/IsodeIQDelegationSerializer.cpp", +			"Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.cpp",  			"Serializer/PresenceSerializer.cpp",  			"Serializer/StanzaSerializer.cpp",  			"Serializer/StreamErrorSerializer.cpp", diff --git a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp index 4a4d678..a9a1ae3 100644 --- a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp +++ b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp @@ -32,6 +32,7 @@  #include <Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.h>  #include <Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.h>  #include <Swiften/Serializer/PayloadSerializers/JingleFileTransferReceivedSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h>  #include <Swiften/Serializer/PayloadSerializers/JingleIBBTransportPayloadSerializer.h>  #include <Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.h>  #include <Swiften/Serializer/PayloadSerializers/JingleS5BTransportPayloadSerializer.h> @@ -127,6 +128,7 @@ FullPayloadSerializerCollection::FullPayloadSerializerCollection() {  	serializers_.push_back(new IdleSerializer());  	serializers_.push_back(new StreamInitiationFileInfoSerializer()); +	serializers_.push_back(new JingleFileTransferFileInfoSerializer());  	serializers_.push_back(new JingleContentPayloadSerializer());  	serializers_.push_back(new JingleFileTransferDescriptionSerializer());  	serializers_.push_back(new JingleFileTransferHashSerializer()); diff --git a/Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.cpp b/Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.cpp index 16337ff..bbe1510 100644 --- a/Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.cpp @@ -4,17 +4,27 @@   * See Documentation/Licenses/BSD-simplified.txt for more information.   */ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +  #include <Swiften/Serializer/PayloadSerializers/JingleFileTransferDescriptionSerializer.h>  #include <boost/shared_ptr.hpp>  #include <boost/smart_ptr/make_shared.hpp> +#include <boost/lexical_cast.hpp>  #include <Swiften/Base/foreach.h> +#include <Swiften/Base/DateTime.h> +#include <Swiften/StringCodecs/Base64.h> +  #include <Swiften/Serializer/XML/XMLNode.h>  #include <Swiften/Serializer/XML/XMLElement.h>  #include <Swiften/Serializer/XML/XMLRawTextNode.h> -#include <Swiften/Serializer/PayloadSerializers/StreamInitiationFileInfoSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h>  namespace Swift { @@ -22,24 +32,11 @@ JingleFileTransferDescriptionSerializer::JingleFileTransferDescriptionSerializer  }  std::string JingleFileTransferDescriptionSerializer::serializePayload(boost::shared_ptr<JingleFileTransferDescription> payload) const { -	XMLElement description("description", "urn:xmpp:jingle:apps:file-transfer:3"); -	StreamInitiationFileInfoSerializer fileInfoSerializer; -	if (!payload->getOffers().empty()) { -		boost::shared_ptr<XMLElement> offers = boost::make_shared<XMLElement>("offer"); -		foreach(const StreamInitiationFileInfo &fileInfo, payload->getOffers()) { -			boost::shared_ptr<XMLRawTextNode> fileInfoXML = boost::make_shared<XMLRawTextNode>(fileInfoSerializer.serialize(boost::make_shared<StreamInitiationFileInfo>(fileInfo))); -			offers->addNode(fileInfoXML); -		} -		description.addNode(offers); -	} -	if (!payload->getRequests().empty()) { -		boost::shared_ptr<XMLElement> requests = boost::make_shared<XMLElement>("request"); -		foreach(const StreamInitiationFileInfo &fileInfo, payload->getRequests()) { -			boost::shared_ptr<XMLRawTextNode> fileInfoXML = boost::make_shared<XMLRawTextNode>(fileInfoSerializer.serialize(boost::make_shared<StreamInitiationFileInfo>(fileInfo))); -			requests->addNode(fileInfoXML); -		} -		description.addNode(requests); -	} +	XMLElement description("description", "urn:xmpp:jingle:apps:file-transfer:4"); + +	JingleFileTransferFileInfoSerializer fileInfoSerializer; +	boost::shared_ptr<XMLRawTextNode> fileInfoXML = boost::make_shared<XMLRawTextNode>(fileInfoSerializer.serialize(boost::make_shared<JingleFileTransferFileInfo>(payload->getFileInfo()))); +	description.addNode(fileInfoXML);  	return description.serialize();  } diff --git a/Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.cpp b/Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.cpp new file mode 100644 index 0000000..1a675d0 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h> + +#include <boost/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <boost/lexical_cast.hpp> + +#include <Swiften/Base/foreach.h> +#include <Swiften/Base/DateTime.h> +#include <Swiften/Serializer/XML/XMLElement.h> +#include <Swiften/Serializer/XML/XMLRawTextNode.h> +#include <Swiften/Serializer/XML/XMLTextNode.h> +#include <Swiften/StringCodecs/Base64.h> + +namespace Swift { + +JingleFileTransferFileInfoSerializer::JingleFileTransferFileInfoSerializer() { +} + +std::string JingleFileTransferFileInfoSerializer::serializePayload(boost::shared_ptr<JingleFileTransferFileInfo> fileInfo) const { + +	XMLElement fileElement("file", ""); + +	if (fileInfo->getDate() != stringToDateTime("")) { +		fileElement.addNode(boost::make_shared<XMLElement>("date", "", dateTimeToString(fileInfo->getDate()))); +	} + +	if (!fileInfo->getDescription().empty()) { +		fileElement.addNode(boost::make_shared<XMLElement>("desc", "", fileInfo->getDescription())); +	} + +	if (!fileInfo->getMediaType().empty()) { +		fileElement.addNode(boost::make_shared<XMLElement>("media-type", "", fileInfo->getMediaType())); +	} + +	if (!fileInfo->getName().empty()) { +		fileElement.addNode(boost::make_shared<XMLElement>("name", "", fileInfo->getName())); +	} + +	if (fileInfo->getSupportsRangeRequests()) { +		boost::shared_ptr<XMLElement> range = boost::make_shared<XMLElement>("range"); +		if (fileInfo->getRangeOffset() != 0) { +			range->setAttribute("offset", boost::lexical_cast<std::string>(fileInfo->getRangeOffset())); +		} +		fileElement.addNode(range); +	} + +	if (fileInfo->getSize() > 0) { +		fileElement.addNode(boost::make_shared<XMLElement>("size", "", boost::lexical_cast<std::string>(fileInfo->getSize()))); +	} + +	foreach (JingleFileTransferFileInfo::HashElementMap::value_type hashElement, fileInfo->getHashes()) { +		boost::shared_ptr<XMLElement> hash = boost::make_shared<XMLElement>("hash", "urn:xmpp:hashes:1", Base64::encode(hashElement.second)); +		hash->setAttribute("algo", hashElement.first); +		fileElement.addNode(hash); +	} + +	return fileElement.serialize(); +} + +} diff --git a/Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h b/Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h new file mode 100644 index 0000000..0c9f2de --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/JingleFileTransferFileInfo.h> + +#include <Swiften/Serializer/XML/XMLElement.h> + +namespace Swift { +	class PayloadSerializerCollection; + +	class SWIFTEN_API JingleFileTransferFileInfoSerializer : public GenericPayloadSerializer<JingleFileTransferFileInfo> { +		public: +			JingleFileTransferFileInfoSerializer(); + +			virtual std::string serializePayload(boost::shared_ptr<JingleFileTransferFileInfo>)  const; +	}; +} diff --git a/Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.cpp b/Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.cpp index 2bd3afa..f416ddc 100644 --- a/Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.cpp @@ -4,6 +4,12 @@   * See Documentation/Licenses/BSD-simplified.txt for more information.   */ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +  #include <Swiften/Serializer/PayloadSerializers/JingleFileTransferHashSerializer.h>  #include <string> @@ -16,7 +22,7 @@  #include <Swiften/Serializer/XML/XMLNode.h>  #include <Swiften/Serializer/XML/XMLElement.h>  #include <Swiften/Serializer/XML/XMLRawTextNode.h> - +#include <Swiften/Serializer/PayloadSerializers/JingleFileTransferFileInfoSerializer.h>  namespace Swift { @@ -27,17 +33,14 @@ std::string JingleFileTransferHashSerializer::serializePayload(boost::shared_ptr  	// code for version urn:xmpp:jingle:apps:file-transfer:2  	//XMLElement hash("hash", "urn:xmpp:jingle:apps:file-transfer:info:2", payload->getHash()); -	// code for version urn:xmpp:jingle:apps:file-transfer:3 -	XMLElement checksum("checksum", "urn:xmpp:jingle:apps:file-transfer:3"); -	boost::shared_ptr<XMLElement> file = boost::make_shared<XMLElement>("file"); +	// code for version urn:xmpp:jingle:apps:file-transfer:4 +	XMLElement checksum("checksum", "urn:xmpp:jingle:apps:file-transfer:4"); + +	JingleFileTransferFileInfoSerializer  fileSerializer; + +	boost::shared_ptr<XMLRawTextNode> file = boost::make_shared<XMLRawTextNode>(fileSerializer.serialize(boost::make_shared<JingleFileTransferFileInfo>(payload->getFileInfo()))); +  	checksum.addNode(file); -	boost::shared_ptr<XMLElement> hashes = boost::make_shared<XMLElement>("hashes", "urn:xmpp:hashes:0"); -	file->addNode(hashes); -	foreach(const JingleFileTransferHash::HashesMap::value_type& pair, payload->getHashes()) { -		boost::shared_ptr<XMLElement> hash = boost::make_shared<XMLElement>("hash", "", pair.second); -		hash->setAttribute("algo", pair.first); -		hashes->addNode(hash); -	}  	return checksum.serialize();  } diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp index e3ec8fc..722c039 100644 --- a/Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp +++ b/Swiften/Serializer/PayloadSerializers/UnitTest/JingleSerializersTest.cpp @@ -4,6 +4,12 @@   * See Documentation/Licenses/BSD-simplified.txt for more information.   */ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +  #include <boost/shared_ptr.hpp>  #include <boost/smart_ptr/make_shared.hpp> @@ -15,13 +21,14 @@  #include <Swiften/Serializer/PayloadSerializers/JinglePayloadSerializer.h>  #include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h>  #include <Swiften/Elements/JingleFileTransferDescription.h> -#include <Swiften/Elements/StreamInitiationFileInfo.h> +#include <Swiften/Elements/JingleFileTransferFileInfo.h>  #include <Swiften/Elements/JingleIBBTransportPayload.h>  #include <Swiften/Elements/JingleS5BTransportPayload.h>  #include <Swiften/Elements/JingleFileTransferHash.h>  #include <Swiften/Elements/JinglePayload.h>  #include <Swiften/Elements/JingleFileTransferReceived.h>  #include <Swiften/Base/DateTime.h> +#include <Swiften/StringCodecs/Base64.h>  using namespace Swift; @@ -38,7 +45,6 @@ class JingleSerializersTest : public CppUnit::TestFixture {  		CPPUNIT_TEST(testSerialize_Xep0234_Example3);  		CPPUNIT_TEST(testSerialize_Xep0234_Example5);  		CPPUNIT_TEST(testSerialize_Xep0234_Example8); -		CPPUNIT_TEST(testSerialize_Xep0234_Example10);  		CPPUNIT_TEST(testSerialize_Xep0234_Example13);  		CPPUNIT_TEST(testSerialize_Xep0260_Example1); @@ -179,30 +185,27 @@ class JingleSerializersTest : public CppUnit::TestFixture {  		// http://xmpp.org/extensions/xep-0234.html#example-1  		void testSerialize_Xep0234_Example1() { -			std::string expected =	"<description xmlns=\"urn:xmpp:jingle:apps:file-transfer:3\">" -							"<offer>" -								"<file" -									" date=\"1969-07-21T02:56:15Z\"" -									" hash=\"552da749930852c69ae5d2141d3766b1\"" -									" name=\"test.txt\"" -									" size=\"1022\"" -									" xmlns=\"http://jabber.org/protocol/si/profile/file-transfer\">" -									"<desc>This is a test. If this were a real file...</desc>" -									"<range/>" -								"</file>" -							"</offer>" -						"</description>"; +			std::string expected =	"<description xmlns=\"urn:xmpp:jingle:apps:file-transfer:4\">" +					"<file>" +						"<date>1969-07-21T02:56:15Z</date>" +						"<desc>This is a test. If this were a real file...</desc>" +						"<name>test.txt</name>" +						"<range/>" +						"<size>1022</size>" +						"<hash algo=\"sha-1\" xmlns=\"urn:xmpp:hashes:1\">VS2nSZMIUsaa5dIUHTdmsQ==</hash>" +					"</file>" +				"</description>";  			JingleFileTransferDescription::ref desc = boost::make_shared<JingleFileTransferDescription>(); -			StreamInitiationFileInfo fileInfo; +			JingleFileTransferFileInfo fileInfo;  			fileInfo.setDate(stringToDateTime("1969-07-21T02:56:15Z")); -			fileInfo.setHash("552da749930852c69ae5d2141d3766b1"); +			fileInfo.addHash(HashElement("sha-1", Base64::decode("VS2nSZMIUsaa5dIUHTdmsQ==")));  			fileInfo.setSize(1022);  			fileInfo.setName("test.txt");  			fileInfo.setDescription("This is a test. If this were a real file...");  			fileInfo.setSupportsRangeRequests(true); -			desc->addOffer(fileInfo); +			desc->setFileInfo(fileInfo);  			CPPUNIT_ASSERT_EQUAL(expected, boost::make_shared<JingleFileTransferDescriptionSerializer>()->serialize(desc));  		} @@ -215,18 +218,15 @@ class JingleSerializersTest : public CppUnit::TestFixture {  					" sid=\"851ba2\""  					" xmlns=\"urn:xmpp:jingle:1\">"  					"<content creator=\"initiator\" name=\"a-file-offer\">" -						"<description xmlns=\"urn:xmpp:jingle:apps:file-transfer:3\">" -							"<offer>" -								"<file" -									" date=\"1969-07-21T02:56:15Z\"" -									" hash=\"552da749930852c69ae5d2141d3766b1\"" -									" name=\"test.txt\"" -									" size=\"1022\"" -									" xmlns=\"http://jabber.org/protocol/si/profile/file-transfer\">" -									"<desc>This is a test. If this were a real file...</desc>" -									"<range/>" -								"</file>" -							"</offer>" +						"<description xmlns=\"urn:xmpp:jingle:apps:file-transfer:4\">" +							"<file>" +								"<date>1969-07-21T02:56:15Z</date>" +								"<desc>This is a test. If this were a real file...</desc>" +								"<name>test.txt</name>" +								"<range/>" +								"<size>1022</size>" +								"<hash algo=\"sha-1\" xmlns=\"urn:xmpp:hashes:1\">VS2nSZMIUsaa5dIUHTdmsQ==</hash>" +							"</file>"  						"</description>"  						/*"<transport xmlns=\"urn:xmpp:jingle:transports:s5b:1\""  							" mode=\"tcp\"" @@ -263,15 +263,15 @@ class JingleSerializersTest : public CppUnit::TestFixture {  			content->setName("a-file-offer");  			JingleFileTransferDescription::ref description = boost::make_shared<JingleFileTransferDescription>(); -			StreamInitiationFileInfo fileInfo; +			JingleFileTransferFileInfo fileInfo;  			fileInfo.setName("test.txt");  			fileInfo.setSize(1022); -			fileInfo.setHash("552da749930852c69ae5d2141d3766b1"); +			fileInfo.addHash(HashElement("sha-1", Base64::decode("VS2nSZMIUsaa5dIUHTdmsQ==")));  			fileInfo.setDate(stringToDateTime("1969-07-21T02:56:15Z"));  			fileInfo.setDescription("This is a test. If this were a real file...");  			fileInfo.setSupportsRangeRequests(true); -			description->addOffer(fileInfo); +			description->setFileInfo(fileInfo);  			content->addDescription(description);  			payload->addPayload(content); @@ -316,11 +316,9 @@ class JingleSerializersTest : public CppUnit::TestFixture {  					" initiator=\"romeo@montague.lit/orchard\""  					" sid=\"a73sjjvkla37jfea\""  					" xmlns=\"urn:xmpp:jingle:1\">" -					"<checksum xmlns=\"urn:xmpp:jingle:apps:file-transfer:3\">" +					"<checksum xmlns=\"urn:xmpp:jingle:apps:file-transfer:4\">"  						"<file>" -							"<hashes xmlns=\"urn:xmpp:hashes:0\">" -								"<hash algo=\"sha-1\">552da749930852c69ae5d2141d3766b1</hash>" -							"</hashes>" +							"<hash algo=\"sha-1\" xmlns=\"urn:xmpp:hashes:1\">VS2nSZMIUsaa5dIUHTdmsQ==</hash>"  						"</file>"  					"</checksum>"  				"</jingle>"; @@ -331,82 +329,12 @@ class JingleSerializersTest : public CppUnit::TestFixture {  			payload->setSessionID("a73sjjvkla37jfea");  			JingleFileTransferHash::ref hash = boost::make_shared<JingleFileTransferHash>(); -			hash->setHash("sha-1", "552da749930852c69ae5d2141d3766b1"); +			hash->getFileInfo().addHash(HashElement("sha-1", Base64::decode("VS2nSZMIUsaa5dIUHTdmsQ==")));  			payload->addPayload(hash);  			CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload));  		} -		 -		// http://xmpp.org/extensions/xep-0234.html#example-10 -		void testSerialize_Xep0234_Example10() { -			std::string expected =  -				"<jingle" -					" action=\"session-initiate\"" -					" initiator=\"romeo@montague.lit/orchard\"" -					" sid=\"uj3b2\"" -					" xmlns=\"urn:xmpp:jingle:1\">" -					"<content creator=\"initiator\" name=\"a-file-request\">" -						"<description" -							" xmlns=\"urn:xmpp:jingle:apps:file-transfer:3\">" -							"<request>" -								"<file" -									" hash=\"552da749930852c69ae5d2141d3766b1\"" -									" xmlns=\"http://jabber.org/protocol/si/profile/file-transfer\">" -									"<range offset=\"270336\"/>" -								"</file>" -							"</request>" -						"</description>" -						/*"<transport" -							" mode=\"tcp\"" -							" sid=\"xig361fj\"" -							" xmlns=\"urn:xmpp:jingle:transports:s5b:1\">" -							"<candidate" -								" cid=\"ht567dq\"" -								" host=\"192.169.1.10\"" -								" jid=\"juliet@capulet.lit/balcony\"" -								" port=\"6539\"" -								" priority=\"8257636\"" -								" type=\"direct\"/>" -							"<candidate" -								" cid=\"hr65dqyd\"" -								" host=\"134.102.201.180\"" -								" jid=\"juliet@capulet.lit/balcony\"" -								" port=\"16453\"" -								" priority=\"7929856\"" -								" type=\"assisted\"/>" -							"<candidate" -								" cid=\"grt654q2\"" -								" host=\"2001:638:708:30c9:219:d1ff:fea4:a17d\"" -								" jid=\"juliet@capulet.lit/balcony\"" -								" port=\"6539\"" -								" priority=\"8257606\"" -								" type=\"direct\"/>" -						"</transport>"*/ -					"</content>" -				"</jingle>"; -			 -			JinglePayload::ref payload = boost::make_shared<JinglePayload>(); -			payload->setAction(JinglePayload::SessionInitiate); -			payload->setInitiator(JID("romeo@montague.lit/orchard")); -			payload->setSessionID("uj3b2"); -			 -			StreamInitiationFileInfo fileInfo; -			fileInfo.setHash("552da749930852c69ae5d2141d3766b1"); -			fileInfo.setRangeOffset(270336); -			 -			JingleFileTransferDescription::ref desc = boost::make_shared<JingleFileTransferDescription>(); -			desc->addRequest(fileInfo); -			 -			JingleContentPayload::ref content = boost::make_shared<JingleContentPayload>(); -			content->setCreator(JingleContentPayload::InitiatorCreator); -			content->setName("a-file-request"); -			content->addDescription(desc); -			 -			payload->addPayload(content); -			 -			CPPUNIT_ASSERT_EQUAL(expected, createTestling()->serialize(payload)); -		}  		// http://xmpp.org/extensions/xep-0234.html#example-10  		void testSerialize_Xep0234_Example13() {  | 
 Swift