From b5fc240f1cf4e340e04177a23cb8cf827b9ca16b Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Wed, 17 Dec 2014 16:21:30 +0100 Subject: Update Jingle FT protocol to namespace verison urn:xmpp:jingle:apps:file-transfer:4. Test-Information: Adjusted unit tests and successfully build/run them on OS X 10.9.5. Change-Id: I63789e3fb351999f719157b54fa9fcf95f40fb07 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 + +namespace Swift { + /* + * @brief This class represents a XEP-0300 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 #include -#include +#include namespace Swift { class JingleFileTransferDescription : public JingleDescription { public: typedef boost::shared_ptr ref; - void addOffer(const StreamInitiationFileInfo& offer) { - offers.push_back(offer); + void setFileInfo(const JingleFileTransferFileInfo& fileInfo) { + fileInfo_ = fileInfo; } - - const std::vector& getOffers() const { - return offers; - } - - void addRequest(const StreamInitiationFileInfo& request) { - reqeusts.push_back(request); - } - - const std::vector& getRequests() const { - return reqeusts; + const JingleFileTransferFileInfo& getFileInfo() { + return fileInfo_; } private: - std::vector offers; - std::vector 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 +#include +#include + +#include +#include +#include + +#include +#include + +namespace Swift { + + /** + * @brief This class represents the file info used in XEP-0234. + */ + class JingleFileTransferFileInfo : public Payload { + typedef boost::shared_ptr 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 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& getHashes() const { + return hashes_; + } + + boost::optional getHash(const std::string& algorithm) const { + boost::optional ret; + if (hashes_.find(algorithm) != hashes_.end()) { + ret = boost::optional(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 @@ -11,25 +17,24 @@ #include #include +#include namespace Swift { class JingleFileTransferHash : public Payload { public: - typedef std::map HashesMap; -public: typedef boost::shared_ptr 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 DefaultFileTransferTransporter::createIBBSen boost::shared_ptr DefaultFileTransferTransporter::createIBBReceiveSession( const std::string& sessionID, unsigned long long size, boost::shared_ptr stream) { - closeLocalSession(); - closeRemoteSession(); + if (s5bServerManager->getServer()) { + closeLocalSession(); + closeRemoteSession(); + } boost::shared_ptr ibbSession = boost::make_shared( sessionID, initiator, responder, size, stream, router); return boost::make_shared(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 #include "Swiften/Disco/EntityCapsProvider.h" #include -#include +#include #include #include #include @@ -146,7 +146,7 @@ OutgoingFileTransfer::ref FileTransferManagerImpl::createOutgoingFileTransfer( const boost::posix_time::ptime& lastModified, boost::shared_ptr 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 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(contents)) { if (content->getTransport()) { JingleFileTransferDescription::ref description = content->getDescription(); - if (description && description->getOffers().size() == 1) { + if (description) { IncomingJingleFileTransfer::ref transfer = boost::make_shared( 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 +#include + #include #include #include +#include #include #include #include @@ -43,11 +46,9 @@ IncomingJingleFileTransfer::IncomingJingleFileTransfer( hashCalculator(NULL) { description = initialContent->getDescription(); 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()) { - 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()) { + 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 #include #include +#include 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 ref; @@ -43,7 +52,7 @@ namespace Swift { CryptoProvider*); ~IncomingJingleFileTransfer(); - virtual void accept(boost::shared_ptr, const FileTransferOptions&) SWIFTEN_OVERRIDE; + virtual void accept(boost::shared_ptr, 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 waitOnHashTimer; - std::string hashAlgorithm; - std::string hash; + std::map 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 md5Hash; - boost::optional sha1Hash; + boost::optional md5Hash; + boost::optional 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 OutgoingFileTransferManager::createOutgo const JID& from, const JID& recipient, boost::shared_ptr readBytestream, - const StreamInitiationFileInfo& fileInfo, + const JingleFileTransferFileInfo& fileInfo, const FileTransferOptions& config) { JingleSessionImpl::ref jingleSession = boost::make_shared( 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, - 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 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(); - 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(); - description->addOffer(fileInfo); + fileInfo.addHash(HashElement("sha-1", ByteArray())); + fileInfo.addHash(HashElement("md5", ByteArray())); + description->setFileInfo(fileInfo); JingleS5BTransportPayload::ref transport = boost::make_shared(); 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 #include #include -#include +#include #include #include #include @@ -40,7 +40,7 @@ namespace Swift { boost::shared_ptr, FileTransferTransporterFactory*, IDGenerator*, - const StreamInitiationFileInfo&, + const JingleFileTransferFileInfo&, const FileTransferOptions&, CryptoProvider*); virtual ~OutgoingJingleFileTransfer(); @@ -99,7 +99,7 @@ namespace Swift { private: IDGenerator* idGenerator; boost::shared_ptr 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 #include #include +#include +#include #include #include #include +#include #include +#include #include +#include #include #include #include +#include #include #include #include @@ -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 createTestling() { - // JID ourJID("our@jid.org/full"); - // return boost::shared_ptr(new IncomingJingleFileTransfer(ourJID, shared_ptr(session), jingleContentPayload, fakeRJTCSF.get(), fakeLJTCF.get(), iqRouter, bytestreamRegistry, bytestreamProxy, timerFactory, crypto.get())); - // } + shared_ptr createTestling() { + JID ourJID("our@jid.org/full"); + return boost::make_shared(ourJID, shared_ptr(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(PlatformCryptoProvider::create()); eventLoop = new DummyEventLoop(); session = boost::make_shared("foo@bar.com/baz", "mysession"); - // jingleContentPayload = make_shared(); + jingleContentPayload = make_shared(); // fakeRJTCSF = make_shared(); // fakeLJTCF = make_shared(); - // 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 desc = make_shared(); - desc->addOffer(StreamInitiationFileInfo("foo.txt", "", 10)); + desc->setFileInfo(JingleFileTransferFileInfo("foo.txt", "", 10)); jingleContentPayload->addDescription(desc); JingleIBBTransportPayload::ref tpRef = make_shared(); tpRef->setSessionID("mysession"); @@ -107,7 +121,7 @@ public: void test_OnlyIBBTransferReceiveWorks() { //1. create your test incoming file transfer shared_ptr desc = make_shared(); - desc->addOffer(StreamInitiationFileInfo("file.txt", "", 10)); + desc->setFileInfo(JingleFileTransferFileInfo("file.txt", "", 10)); jingleContentPayload->addDescription(desc); JingleIBBTransportPayload::ref tpRef = make_shared(); tpRef->setSessionID("mysession"); @@ -139,6 +153,8 @@ public: shared_ptr byteStream = make_shared(); fileTransfer->accept(byteStream); + // candidates are gathered + // check whether accept has been called FakeJingleSession::AcceptCall acceptCall = getCall(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(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 desc = make_shared(); - 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 crypto; boost::shared_ptr session; -#if 0 shared_ptr jingleContentPayload; - shared_ptr fakeRJTCSF; - shared_ptr fakeLJTCF; +// shared_ptr fakeRJTCSF; +// shared_ptr 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 +#include #include @@ -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 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 + +#include +#include +#include +#include +#include + +namespace Swift { + class SWIFTEN_API DummyConnectionServer : public ConnectionServer, public EventOwner, public boost::enable_shared_from_this { + 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 tryStart() { + return boost::optional(); + } + + 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 + +#include +#include + +namespace Swift { + +class EventLoop; + +class DummyConnectionServerFactory : public ConnectionServerFactory { +public: + DummyConnectionServerFactory(EventLoop* eventLoop) : eventLoop(eventLoop) {} + virtual ~DummyConnectionServerFactory() {} + + virtual boost::shared_ptr createConnectionServer(int port) { + return boost::make_shared(eventLoop, port); + } + + virtual boost::shared_ptr createConnectionServer(const Swift::HostAddress& hostAddress, int port) { + return boost::make_shared(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 #include #include +#include #include #include #include @@ -140,6 +141,7 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() { factories_.push_back(boost::make_shared >("transport", "urn:xmpp:jingle:transports:s5b:1")); factories_.push_back(boost::make_shared(this)); factories_.push_back(boost::make_shared >("file", "http://jabber.org/protocol/si/profile/file-transfer")); + factories_.push_back(boost::make_shared >("file", "urn:xmpp:jingle:apps:file-transfer:4")); factories_.push_back(boost::make_shared >("received", "urn:xmpp:jingle:apps:file-transfer:3")); factories_.push_back(boost::make_shared >("checksum")); factories_.push_back(boost::make_shared >("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 + +#include +#include #include #include -#include +#include +#include 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 info = boost::dynamic_pointer_cast(currentPayloadParser->getPayload()); - if (info) { - if (currentElement == OfferElement) { - getPayloadInternal()->addOffer(*info); - } else if (currentElement == RequestElement) { - getPayloadInternal()->addRequest(*info); - } - } + if (level == 0) { + boost::shared_ptr info = boost::dynamic_pointer_cast(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 @@ -20,18 +26,11 @@ class JingleFileTransferDescriptionParser : public GenericPayloadParser 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 @@ -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 + +#include +#include + +#include +#include + +namespace Swift { + +JingleFileTransferFileInfoParser::JingleFileTransferFileInfoParser() : level(0) { +} + +template boost::optional safeLexicalCast(const std::string& str) { + boost::optional ret; + try { + ret = boost::lexical_cast(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(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 size = safeLexicalCast(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 +#include + +namespace Swift { + +class JingleFileTransferFileInfoParser : public GenericPayloadParser { + 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 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 #include -#include +#include #include #include 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(); } + + 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 info = boost::dynamic_pointer_cast(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 @@ -20,8 +26,8 @@ public: virtual void handleCharacterData(const std::string& data); private: - std::string algo; - std::string hash; + int level; + boost::shared_ptr 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 #include #include 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 #include #include - +#include #include 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( "\n" - " \n" - " \n" - " \n" - " \n" - " This is a test. If this were a real file...\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" + " action='session-initiate'\n" + " initiator='romeo@montague.lit/orchard'\n" + " sid='851ba2'>\n" + "\n" + "\n" + "\n" + "1969-07-21T02:56:15Z\n" + "This is a test. If this were a real file...\n" + "text/plain\n" + "test.txt\n" + "\n" + "1022\n" + "VS2nSZMIUsaa5dIUHTdmsQ==\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" )); JinglePayload::ref jingle = parser.getPayload(); @@ -270,16 +267,15 @@ class JingleParserTest : public CppUnit::TestFixture { JingleFileTransferDescription::ref description = contents[0]->getDescription(); - - std::vector offers = description->getOffers(); - CPPUNIT_ASSERT_EQUAL(static_cast(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( "\n" - " \n" - " \n" - " \n" - " \n" - " This is a test. If this were a real file...\n" - " \n" - " \n" - " \n" - " \n" + " action='session-accept'\n" + " initiator='romeo@montague.lit/orchard'\n" + " sid='851ba2'>\n" + "\n" + "\n" + "\n" + "1969-07-21T02:56:15Z\n" + "This is a test. If this were a real file...\n" + "text/plain\n" + "test.txt\n" + "\n" + "1022\n" + "VS2nSZMIUsaa5dIUHTdmsQ==\n" + "\n" + "\n" " \n" @@ -340,16 +335,16 @@ class JingleParserTest : public CppUnit::TestFixture { JingleFileTransferDescription::ref description = contents[0]->getDescription(); + CPPUNIT_ASSERT(description); - std::vector offers = description->getOffers(); - CPPUNIT_ASSERT_EQUAL(static_cast(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" - " \n" + " \n" " \n" - " \n" - " 552da749930852c69ae5d2141d3766b1\n" - " \n" + " VS2nSZMIUsaa5dIUHTdmsQ==\n" " \n" " \n" "\n" @@ -410,12 +403,12 @@ class JingleParserTest : public CppUnit::TestFixture { JingleFileTransferHash::ref hash = jingle->getPayload(); 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( "\n" " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" + " \n" + " \n" + " VS2nSZMIUsaa5dIUHTdmsQ==\n" + " \n" + " \n" " \n" " getPayload(); CPPUNIT_ASSERT(content); - StreamInitiationFileInfo file = content->getDescription()->getRequests()[0]; - CPPUNIT_ASSERT_EQUAL(std::string("552da749930852c69ae5d2141d3766b1"), file.getHash()); - CPPUNIT_ASSERT_EQUAL(static_cast(270336), file.getRangeOffset()); + JingleFileTransferFileInfo file = content->getDescription()->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(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( - "\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n" - )); - - JinglePayload::ref jingle = parser.getPayload(); - 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(); - CPPUNIT_ASSERT(content); - CPPUNIT_ASSERT_EQUAL(JingleContentPayload::InitiatorCreator, content->getCreator()); - CPPUNIT_ASSERT_EQUAL(std::string("a-file-offer"), content->getName()); - - std::vector offers = content->getDescription()->getOffers(); - CPPUNIT_ASSERT_EQUAL(static_cast(3), offers.size()); - } - - // http://xmpp.org/extensions/xep-0234.html#example-12 - void testParse_Xep0234_Example12() { - PayloadsParserTester parser; - CPPUNIT_ASSERT(parser.parse( - "\n" - " \n" - " \n" - " \n" - "\n" - )); - - JinglePayload::ref jingle = parser.getPayload(); - 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 received = jingle->getPayload(); - 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 #include #include +#include #include #include #include @@ -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 #include #include +#include #include +#include +#include + #include #include #include -#include +#include namespace Swift { @@ -22,24 +32,11 @@ JingleFileTransferDescriptionSerializer::JingleFileTransferDescriptionSerializer } std::string JingleFileTransferDescriptionSerializer::serializePayload(boost::shared_ptr payload) const { - XMLElement description("description", "urn:xmpp:jingle:apps:file-transfer:3"); - StreamInitiationFileInfoSerializer fileInfoSerializer; - if (!payload->getOffers().empty()) { - boost::shared_ptr offers = boost::make_shared("offer"); - foreach(const StreamInitiationFileInfo &fileInfo, payload->getOffers()) { - boost::shared_ptr fileInfoXML = boost::make_shared(fileInfoSerializer.serialize(boost::make_shared(fileInfo))); - offers->addNode(fileInfoXML); - } - description.addNode(offers); - } - if (!payload->getRequests().empty()) { - boost::shared_ptr requests = boost::make_shared("request"); - foreach(const StreamInitiationFileInfo &fileInfo, payload->getRequests()) { - boost::shared_ptr fileInfoXML = boost::make_shared(fileInfoSerializer.serialize(boost::make_shared(fileInfo))); - requests->addNode(fileInfoXML); - } - description.addNode(requests); - } + XMLElement description("description", "urn:xmpp:jingle:apps:file-transfer:4"); + + JingleFileTransferFileInfoSerializer fileInfoSerializer; + boost::shared_ptr fileInfoXML = boost::make_shared(fileInfoSerializer.serialize(boost::make_shared(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 + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace Swift { + +JingleFileTransferFileInfoSerializer::JingleFileTransferFileInfoSerializer() { +} + +std::string JingleFileTransferFileInfoSerializer::serializePayload(boost::shared_ptr fileInfo) const { + + XMLElement fileElement("file", ""); + + if (fileInfo->getDate() != stringToDateTime("")) { + fileElement.addNode(boost::make_shared("date", "", dateTimeToString(fileInfo->getDate()))); + } + + if (!fileInfo->getDescription().empty()) { + fileElement.addNode(boost::make_shared("desc", "", fileInfo->getDescription())); + } + + if (!fileInfo->getMediaType().empty()) { + fileElement.addNode(boost::make_shared("media-type", "", fileInfo->getMediaType())); + } + + if (!fileInfo->getName().empty()) { + fileElement.addNode(boost::make_shared("name", "", fileInfo->getName())); + } + + if (fileInfo->getSupportsRangeRequests()) { + boost::shared_ptr range = boost::make_shared("range"); + if (fileInfo->getRangeOffset() != 0) { + range->setAttribute("offset", boost::lexical_cast(fileInfo->getRangeOffset())); + } + fileElement.addNode(range); + } + + if (fileInfo->getSize() > 0) { + fileElement.addNode(boost::make_shared("size", "", boost::lexical_cast(fileInfo->getSize()))); + } + + foreach (JingleFileTransferFileInfo::HashElementMap::value_type hashElement, fileInfo->getHashes()) { + boost::shared_ptr hash = boost::make_shared("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 +#include +#include + +#include + +namespace Swift { + class PayloadSerializerCollection; + + class SWIFTEN_API JingleFileTransferFileInfoSerializer : public GenericPayloadSerializer { + public: + JingleFileTransferFileInfoSerializer(); + + virtual std::string serializePayload(boost::shared_ptr) 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 #include @@ -16,7 +22,7 @@ #include #include #include - +#include 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 file = boost::make_shared("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 file = boost::make_shared(fileSerializer.serialize(boost::make_shared(payload->getFileInfo()))); + checksum.addNode(file); - boost::shared_ptr hashes = boost::make_shared("hashes", "urn:xmpp:hashes:0"); - file->addNode(hashes); - foreach(const JingleFileTransferHash::HashesMap::value_type& pair, payload->getHashes()) { - boost::shared_ptr hash = boost::make_shared("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 #include @@ -15,13 +21,14 @@ #include #include #include -#include +#include #include #include #include #include #include #include +#include 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 = "" - "" - "" - "This is a test. If this were a real file..." - "" - "" - "" - ""; + std::string expected = "" + "" + "1969-07-21T02:56:15Z" + "This is a test. If this were a real file..." + "test.txt" + "" + "1022" + "VS2nSZMIUsaa5dIUHTdmsQ==" + "" + ""; JingleFileTransferDescription::ref desc = boost::make_shared(); - 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()->serialize(desc)); } @@ -215,18 +218,15 @@ class JingleSerializersTest : public CppUnit::TestFixture { " sid=\"851ba2\"" " xmlns=\"urn:xmpp:jingle:1\">" "" - "" - "" - "" - "This is a test. If this were a real file..." - "" - "" - "" + "" + "" + "1969-07-21T02:56:15Z" + "This is a test. If this were a real file..." + "test.txt" + "" + "1022" + "VS2nSZMIUsaa5dIUHTdmsQ==" + "" "" /*"setName("a-file-offer"); JingleFileTransferDescription::ref description = boost::make_shared(); - 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\">" - "" + "" "" - "" - "552da749930852c69ae5d2141d3766b1" - "" + "VS2nSZMIUsaa5dIUHTdmsQ==" "" "" ""; @@ -331,82 +329,12 @@ class JingleSerializersTest : public CppUnit::TestFixture { payload->setSessionID("a73sjjvkla37jfea"); JingleFileTransferHash::ref hash = boost::make_shared(); - 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 = - "" - "" - "" - "" - "" - "" - "" - "" - "" - /*"" - "" - "" - "" - ""*/ - "" - ""; - - JinglePayload::ref payload = boost::make_shared(); - 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(); - desc->addRequest(fileInfo); - - JingleContentPayload::ref content = boost::make_shared(); - 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() { -- cgit v0.10.2-6-g49f6