summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften')
-rw-r--r--Swiften/Avatars/UnitTest/AvatarManagerImplTest.cpp3
-rw-r--r--Swiften/Avatars/VCardUpdateAvatarManager.cpp6
-rw-r--r--Swiften/Base/Log.cpp17
-rw-r--r--Swiften/Base/Log.h11
-rw-r--r--Swiften/Base/Platform.h8
-rw-r--r--Swiften/ChangeLog.md21
-rw-r--r--Swiften/Client/ClientSession.cpp4
-rw-r--r--Swiften/MUC/MUCBookmarkManager.cpp2
-rw-r--r--Swiften/Network/Connector.cpp10
-rw-r--r--Swiften/Network/PlatformNATTraversalWorker.cpp4
-rw-r--r--Swiften/SConscript5
-rw-r--r--Swiften/TLS/CAPICertificate.cpp49
-rw-r--r--Swiften/TLS/Schannel/SchannelContext.cpp27
-rw-r--r--Swiften/VCards/UnitTest/VCardManagerTest.cpp127
-rw-r--r--Swiften/VCards/VCardManager.cpp5
15 files changed, 231 insertions, 68 deletions
diff --git a/Swiften/Avatars/UnitTest/AvatarManagerImplTest.cpp b/Swiften/Avatars/UnitTest/AvatarManagerImplTest.cpp
index 241f375..5a35410 100644
--- a/Swiften/Avatars/UnitTest/AvatarManagerImplTest.cpp
+++ b/Swiften/Avatars/UnitTest/AvatarManagerImplTest.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2016 Isode Limited.
+ * Copyright (c) 2014-2018 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -91,6 +91,7 @@ class AvatarManagerImplTest : public CppUnit::TestFixture {
/* send new presence to notify of blank avatar */
vcardUpdate = std::make_shared<VCardUpdate>();
+ vcardUpdate->setPhotoHash("da39a3ee5e6b4b0d3255bfef95601890afd80709");
presence = std::make_shared<Presence>();
presence->setTo(ownerJID);
presence->setFrom(personJID);
diff --git a/Swiften/Avatars/VCardUpdateAvatarManager.cpp b/Swiften/Avatars/VCardUpdateAvatarManager.cpp
index 3e8d87b..349af2f 100644
--- a/Swiften/Avatars/VCardUpdateAvatarManager.cpp
+++ b/Swiften/Avatars/VCardUpdateAvatarManager.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2016 Isode Limited.
+ * Copyright (c) 2010-2018 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -32,6 +32,10 @@ void VCardUpdateAvatarManager::handlePresenceReceived(std::shared_ptr<Presence>
return;
}
JID from = getAvatarJID(presence->getFrom());
+ if (update->getPhotoHash().size() != 40) {
+ SWIFT_LOG(debug) << "Invalid vCard avatar photo hash length. Must be hex-encoded SHA-1, i.e. 40 characters." << std::endl;
+ return;
+ }
if (getAvatarHash(from) == update->getPhotoHash()) {
return;
}
diff --git a/Swiften/Base/Log.cpp b/Swiften/Base/Log.cpp
index 0efac7e..9b16531 100644
--- a/Swiften/Base/Log.cpp
+++ b/Swiften/Base/Log.cpp
@@ -16,6 +16,7 @@
namespace Swift {
static Log::Severity logLevel = Log::warning;
+std::unique_ptr<FILE, Log::LogFileClose> Log::logfile;
Log::Log() {
}
@@ -25,8 +26,14 @@ Log::~Log() {
__android_log_print(ANDROID_LOG_VERBOSE, "Swift", stream.str().c_str(), 1);
#else
// Using stdio for thread safety (POSIX file i/o calls are guaranteed to be atomic)
- fprintf(stderr, "%s", stream.str().c_str());
- fflush(stderr);
+ if (logfile) {
+ fwrite(stream.str().c_str(), sizeof(char), stream.str().size(), logfile.get());
+ fflush(logfile.get());
+ }
+ else {
+ fwrite(stream.str().c_str(), sizeof(char), stream.str().size(), stderr);
+ fflush(stderr);
+ }
#endif
}
@@ -48,4 +55,10 @@ void Log::setLogLevel(Severity level) {
logLevel = level;
}
+void Log::setLogFile(const std::string& fileName) {
+ if (!fileName.empty()) {
+ logfile = std::unique_ptr<FILE, Log::LogFileClose>(fopen(fileName.c_str(), "a"));
+ }
+}
+
}
diff --git a/Swiften/Base/Log.h b/Swiften/Base/Log.h
index 33c969d..e3e04a5 100644
--- a/Swiften/Base/Log.h
+++ b/Swiften/Base/Log.h
@@ -6,6 +6,8 @@
#pragma once
+#include <cstdio>
+#include <memory>
#include <sstream>
#include <Swiften/Base/API.h>
@@ -29,9 +31,18 @@ namespace Swift {
static Severity getLogLevel();
static void setLogLevel(Severity level);
+ static void setLogFile(const std::string& fileName);
private:
+ struct LogFileClose {
+ void operator()(FILE* p) {
+ if (p) {
+ fclose(p);
+ }
+ }
+ };
std::ostringstream stream;
+ static std::unique_ptr<FILE, LogFileClose> logfile;
};
}
diff --git a/Swiften/Base/Platform.h b/Swiften/Base/Platform.h
index 4deba2b..22dff30 100644
--- a/Swiften/Base/Platform.h
+++ b/Swiften/Base/Platform.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 Isode Limited.
+ * Copyright (c) 2010-2019 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -43,9 +43,9 @@
#endif
// Endianness
-#include <boost/detail/endian.hpp>
-#if defined(BOOST_LITTLE_ENDIAN)
+#include <boost/predef/other/endian.h>
+#if defined(BOOST_ENDIAN_LITTLE_BYTE)
#define SWIFTEN_LITTLE_ENDIAN
-#elif defined(BOOST_BIG_ENDIAN)
+#elif defined(BOOST_ENDIAN_BIG_BYTE)
#define SWIFTEN_BIG_ENDIAN
#endif
diff --git a/Swiften/ChangeLog.md b/Swiften/ChangeLog.md
index d823954..23d5185 100644
--- a/Swiften/ChangeLog.md
+++ b/Swiften/ChangeLog.md
@@ -1,3 +1,24 @@
+4.0.1 (2018-03-28)
+------------------
+- Fix handling errors when fetching own vCard
+
+4.0 (2018-03-20)
+----------------
+- Moved code-base to C++11
+ - Use C++11 threading instead of Boost.Thread library
+ - Use C++11 smart pointers instead of Boost's
+- Migrated from Boost.Signals to Boost.Signals2
+- Build without warnings on our CI platforms
+- General cleanup like remove of superflous files and #include statements. This means header files that previously were included implictly need to be explicitly included now
+- Support IPv6 addresses in URLs
+- Handle sessions being closed by the server
+- Verify certificates when using HTTPS in BOSH connections
+- In memory caching of latest entity capabilites lookups
+- Changed source code style to use soft tabs (4 spaces wide) instead of hard tabs. Custom patches for Swiften will need to be reformatted accordingly
+- Require a TLS backend for building
+- Update 3rdParty/lcov to version 1.12
+- Fix several possible race conditions, smaller leaks, and other small bugs
+
4.0-rc1 ( 2017-05-17 )
----------------------
- Handle sessions being closed by the server
diff --git a/Swiften/Client/ClientSession.cpp b/Swiften/Client/ClientSession.cpp
index 661a832..bb9be58 100644
--- a/Swiften/Client/ClientSession.cpp
+++ b/Swiften/Client/ClientSession.cpp
@@ -231,13 +231,13 @@ void ClientSession::handleElement(std::shared_ptr<ToplevelElement> element) {
#ifdef SWIFTEN_PLATFORM_WIN32
if (singleSignOn) {
const boost::optional<std::string> authenticationHostname = streamFeatures->getAuthenticationHostname();
- bool gssapiSupported = streamFeatures->hasAuthenticationMechanism("GSSAPI") && authenticationHostname && !authenticationHostname->empty();
+ bool gssapiSupported = streamFeatures->hasAuthenticationMechanism("GSSAPI");
if (!gssapiSupported) {
finishSession(Error::NoSupportedAuthMechanismsError);
}
else {
- WindowsGSSAPIClientAuthenticator* gssapiAuthenticator = new WindowsGSSAPIClientAuthenticator(*authenticationHostname, localJID.getDomain(), authenticationPort);
+ WindowsGSSAPIClientAuthenticator* gssapiAuthenticator = new WindowsGSSAPIClientAuthenticator(authenticationHostname.value_or(""), localJID.getDomain(), authenticationPort);
std::shared_ptr<Error> error = std::make_shared<Error>(Error::AuthenticationFailedError);
authenticator = gssapiAuthenticator;
diff --git a/Swiften/MUC/MUCBookmarkManager.cpp b/Swiften/MUC/MUCBookmarkManager.cpp
index 9f8ae77..511c88a 100644
--- a/Swiften/MUC/MUCBookmarkManager.cpp
+++ b/Swiften/MUC/MUCBookmarkManager.cpp
@@ -25,7 +25,7 @@ MUCBookmarkManager::MUCBookmarkManager(IQRouter* iqRouter) {
}
void MUCBookmarkManager::handleBookmarksReceived(std::shared_ptr<Storage> payload, ErrorPayload::ref error) {
- if (error) {
+ if (error || !payload) {
return;
}
diff --git a/Swiften/Network/Connector.cpp b/Swiften/Network/Connector.cpp
index 457d8a9..5eddaba 100644
--- a/Swiften/Network/Connector.cpp
+++ b/Swiften/Network/Connector.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2016 Isode Limited.
+ * Copyright (c) 2010-2018 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -148,6 +148,13 @@ void Connector::handleConnectionConnectFinished(bool error) {
timer->stop();
timer.reset();
}
+ if (!currentConnection) {
+ // We've hit a race condition where multiple finisheds were on the eventloop queue at once.
+ // This is particularly likely on macOS where the hourly momentary wakeup while asleep
+ // can cause both a timeout and an onConnectFinished to be queued sequentially (SWIFT-232).
+ // Let the first one process as normal, but ignore the second.
+ return;
+ }
currentConnection->onConnectFinished.disconnect(boost::bind(&Connector::handleConnectionConnectFinished, shared_from_this(), _1));
if (error) {
currentConnection.reset();
@@ -189,6 +196,7 @@ void Connector::finish(std::shared_ptr<Connection> connection) {
void Connector::handleTimeout() {
SWIFT_LOG(debug) << "Timeout" << std::endl;
+ SWIFT_LOG_ASSERT(currentConnection, error) << "Connection not valid but triggered a timeout" <<std::endl;
handleConnectionConnectFinished(true);
}
diff --git a/Swiften/Network/PlatformNATTraversalWorker.cpp b/Swiften/Network/PlatformNATTraversalWorker.cpp
index f56de0b..eaa13b3 100644
--- a/Swiften/Network/PlatformNATTraversalWorker.cpp
+++ b/Swiften/Network/PlatformNATTraversalWorker.cpp
@@ -157,7 +157,7 @@ NATTraversalInterface* PlatformNATTraversalWorker::getNATTraversalInterface() co
miniUPnPInterface = new MiniUPnPInterface();
miniUPnPSupported = miniUPnPInterface->isAvailable();
}
- SWIFT_LOG(debug) << "UPnP NAT traversal supported: " << miniUPnPSupported << std::endl;
+ SWIFT_LOG(debug) << "UPnP NAT traversal supported: " << static_cast<bool>(miniUPnPSupported) << std::endl;
if (miniUPnPSupported) {
return miniUPnPInterface;
}
@@ -168,7 +168,7 @@ NATTraversalInterface* PlatformNATTraversalWorker::getNATTraversalInterface() co
natPMPInterface = new NATPMPInterface();
natPMPSupported = natPMPInterface->isAvailable();
}
- SWIFT_LOG(debug) << "NAT-PMP NAT traversal supported: " << natPMPSupported << std::endl;
+ SWIFT_LOG(debug) << "NAT-PMP NAT traversal supported: " << static_cast<bool>(natPMPSupported) << std::endl;
if (natPMPSupported) {
return natPMPInterface;
}
diff --git a/Swiften/SConscript b/Swiften/SConscript
index e0f87ce..f52637b 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -618,8 +618,9 @@ if env["SCONS_STAGE"] == "build" :
# Install swiften
if swiften_env.get("SWIFTEN_INSTALLDIR", "") :
- swiften_env.Install(os.path.join(swiften_env["SWIFTEN_INSTALLDIR"], "lib"), swiften_lib)
+ swiften_libdir = swiften_env.get("SWIFTEN_LIBDIR", "lib")
+ swiften_env.Install(os.path.join(swiften_env["SWIFTEN_INSTALLDIR"], swiften_libdir), swiften_lib)
for alias in myenv["SWIFTEN_LIBRARY_ALIASES"] :
- myenv.Command(myenv.File(os.path.join(swiften_env["SWIFTEN_INSTALLDIR"], "lib", alias)), [env.Value(swiften_lib[0].name), swiften_lib[0]], symlink)
+ myenv.Command(myenv.File(os.path.join(swiften_env["SWIFTEN_INSTALLDIR"], swiften_libdir, alias)), [env.Value(swiften_lib[0].name), swiften_lib[0]], symlink)
for include in swiften_includes :
swiften_env.Install(os.path.join(swiften_env["SWIFTEN_INSTALLDIR"], "include", os.path.dirname(include)), "#/" + include)
diff --git a/Swiften/TLS/CAPICertificate.cpp b/Swiften/TLS/CAPICertificate.cpp
index a46b9f6..f10ad47 100644
--- a/Swiften/TLS/CAPICertificate.cpp
+++ b/Swiften/TLS/CAPICertificate.cpp
@@ -14,6 +14,7 @@
#include <Swiften/Base/Log.h>
#include <Swiften/Network/TimerFactory.h>
#include <Swiften/StringCodecs/Hexify.h>
+#include <Swiften/TLS/Schannel/SchannelUtil.h>
// Size of the SHA1 hash
#define SHA1_HASH_LEN 20
@@ -43,6 +44,7 @@ CAPICertificate::CAPICertificate(const std::string& capiUri, TimerFactory* timer
}
CAPICertificate::~CAPICertificate() {
+ SWIFT_LOG(debug) << "Destroying the CAPICertificate" << std::endl;
if (smartCardTimer_) {
smartCardTimer_->stop();
smartCardTimer_->onTick.disconnect(boost::bind(&CAPICertificate::handleSmartCardTimerTick, this));
@@ -50,7 +52,9 @@ CAPICertificate::~CAPICertificate() {
}
if (certStoreHandle_) {
- CertCloseStore(certStoreHandle_, 0);
+ if (CertCloseStore(certStoreHandle_, 0) == FALSE) {
+ SWIFT_LOG(debug) << "Failed to close the certificate store handle" << std::endl;
+ }
}
if (cardHandle_) {
@@ -80,7 +84,7 @@ const std::string& CAPICertificate::getSmartCardReaderName() const {
return smartCardReaderName_;
}
-PCCERT_CONTEXT findCertificateInStore (HCERTSTORE certStoreHandle, const std::string &certName) {
+PCCERT_CONTEXT findCertificateInStore(HCERTSTORE certStoreHandle, const std::string &certName) {
if (!boost::iequals(certName.substr(0, 5), "sha1:")) {
// Find client certificate. Note that this sample just searches for a
@@ -105,8 +109,7 @@ PCCERT_CONTEXT findCertificateInStore (HCERTSTORE certStoreHandle, const std::st
}
-
-void CAPICertificate::setUri (const std::string& capiUri) {
+void CAPICertificate::setUri(const std::string& capiUri) {
valid_ = false;
/* Syntax: "certstore:" <cert_store> ":" <hash> ":" <hash_of_cert> */
@@ -118,7 +121,7 @@ void CAPICertificate::setUri (const std::string& capiUri) {
/* Substring of subject: uses "storename" */
std::string capiIdentity = capiUri.substr(10);
std::string newCertStoreName;
- size_t pos = capiIdentity.find_first_of (':');
+ size_t pos = capiIdentity.find_first_of(':');
if (pos == std::string::npos) {
/* Using the default certificate store */
@@ -146,49 +149,38 @@ void CAPICertificate::setUri (const std::string& capiUri) {
certStore_ = newCertStoreName;
- PCCERT_CONTEXT certContext = findCertificateInStore (certStoreHandle_, certName_);
-
+ ScopedCertContext certContext(findCertificateInStore(certStoreHandle_, certName_));
if (!certContext) {
return;
}
-
/* Now verify that we can have access to the corresponding private key */
DWORD len;
- CRYPT_KEY_PROV_INFO *pinfo;
- HCRYPTPROV hprov;
- HCRYPTKEY key;
-
if (!CertGetCertificateContextProperty(certContext,
CERT_KEY_PROV_INFO_PROP_ID,
NULL,
&len)) {
- CertFreeCertificateContext(certContext);
+ SWIFT_LOG(error) << "Error while retrieving context properties" << std::endl;
return;
}
- pinfo = static_cast<CRYPT_KEY_PROV_INFO *>(malloc(len));
+ std::shared_ptr<CRYPT_KEY_PROV_INFO> pinfo(static_cast<CRYPT_KEY_PROV_INFO *>(malloc(len)), free);
if (!pinfo) {
- CertFreeCertificateContext(certContext);
return;
}
- if (!CertGetCertificateContextProperty(certContext, CERT_KEY_PROV_INFO_PROP_ID, pinfo, &len)) {
- CertFreeCertificateContext(certContext);
- free(pinfo);
+ if (!CertGetCertificateContextProperty(certContext, CERT_KEY_PROV_INFO_PROP_ID, pinfo.get(), &len)) {
return;
}
+ certContext.FreeContext();
- CertFreeCertificateContext(certContext);
-
+ HCRYPTPROV hprov;
// Now verify if we have access to the private key
if (!CryptAcquireContextW(&hprov, pinfo->pwszContainerName, pinfo->pwszProvName, pinfo->dwProvType, 0)) {
- free(pinfo);
return;
}
-
char smartCardReader[1024];
DWORD bufferLength = sizeof(smartCardReader);
if (!CryptGetProvParam(hprov, PP_SMARTCARD_READER, (BYTE *)&smartCardReader, &bufferLength, 0)) {
@@ -205,19 +197,19 @@ void CAPICertificate::setUri (const std::string& capiUri) {
smartCardTimer_ = timerFactory_->createTimer(SMARTCARD_EJECTION_CHECK_FREQUENCY_MILLISECONDS);
}
else {
- ///Need to handle an error here
+ CryptReleaseContext(hprov, 0);
+ return;
}
}
+ HCRYPTKEY key;
if (!CryptGetUserKey(hprov, pinfo->dwKeySpec, &key)) {
CryptReleaseContext(hprov, 0);
- free(pinfo);
return;
}
CryptDestroyKey(key);
CryptReleaseContext(hprov, 0);
- free(pinfo);
if (smartCardTimer_) {
smartCardTimer_->onTick.connect(boost::bind(&CAPICertificate::handleSmartCardTimerTick, this));
@@ -227,7 +219,7 @@ void CAPICertificate::setUri (const std::string& capiUri) {
valid_ = true;
}
-static void smartcard_check_status (SCARDCONTEXT hContext,
+static void smartcard_check_status(SCARDCONTEXT hContext,
const char* pReader,
SCARDHANDLE hCardHandle, /* Can be 0 on the first call */
SCARDHANDLE* newCardHandle, /* The handle returned */
@@ -288,7 +280,7 @@ static void smartcard_check_status (SCARDCONTEXT hContext,
}
}
-bool CAPICertificate::checkIfSmartCardPresent () {
+bool CAPICertificate::checkIfSmartCardPresent() {
if (!smartCardReaderName_.empty()) {
DWORD dwState;
smartcard_check_status(scardContext_, smartCardReaderName_.c_str(), cardHandle_, &cardHandle_, &dwState);
@@ -317,8 +309,6 @@ bool CAPICertificate::checkIfSmartCardPresent () {
break;
}
-
-
switch (dwState) {
case SCARD_ABSENT:
return false;
@@ -342,6 +332,7 @@ bool CAPICertificate::checkIfSmartCardPresent () {
void CAPICertificate::handleSmartCardTimerTick() {
bool poll = checkIfSmartCardPresent();
if (lastPollingResult_ && !poll) {
+ SWIFT_LOG(debug) << "CAPI Certificate detected that the certificate card was removed" << std::endl;
onCertificateCardRemoved();
}
lastPollingResult_ = poll;
diff --git a/Swiften/TLS/Schannel/SchannelContext.cpp b/Swiften/TLS/Schannel/SchannelContext.cpp
index 5799157..c07d009 100644
--- a/Swiften/TLS/Schannel/SchannelContext.cpp
+++ b/Swiften/TLS/Schannel/SchannelContext.cpp
@@ -16,6 +16,7 @@
#include <WinHTTP.h> /* For SECURITY_FLAG_IGNORE_CERT_CN_INVALID */
+#include <Swiften/Base/Log.h>
#include <Swiften/TLS/CAPICertificate.h>
#include <Swiften/TLS/Schannel/SchannelCertificate.h>
@@ -39,13 +40,20 @@ SchannelContext::SchannelContext(bool tls1_0Workaround) : state_(Start), secCont
//------------------------------------------------------------------------
SchannelContext::~SchannelContext() {
- if (myCertStore_) CertCloseStore(myCertStore_, 0);
+ SWIFT_LOG(debug) << "Destroying SchannelContext" << std::endl;
+ if (myCertStore_) {
+ if (CertCloseStore(myCertStore_, 0) == FALSE) {
+ SWIFT_LOG(debug) << "Failed to close the certificate store" << std::endl;
+ }
+ }
}
//------------------------------------------------------------------------
void SchannelContext::determineStreamSizes() {
- QueryContextAttributes(contextHandle_, SECPKG_ATTR_STREAM_SIZES, &streamSizes_);
+ if (QueryContextAttributes(contextHandle_, SECPKG_ATTR_STREAM_SIZES, &streamSizes_) != SEC_E_OK) {
+ SWIFT_LOG(debug) << "QueryContextAttributes failed to determinate the stream size" << std::endl;
+ }
}
//------------------------------------------------------------------------
@@ -267,8 +275,8 @@ void SchannelContext::continueHandshake(const SafeByteArray& data) {
SecBuffer inBuffers[2];
// Provide Schannel with the remote host's handshake data
- inBuffers[0].pvBuffer = (char*)(&receivedData_[0]);
- inBuffers[0].cbBuffer = (unsigned long)receivedData_.size();
+ inBuffers[0].pvBuffer = static_cast<char*>(&receivedData_[0]);
+ inBuffers[0].cbBuffer = static_cast<unsigned long>(receivedData_.size());
inBuffers[0].BufferType = SECBUFFER_TOKEN;
inBuffers[1].pvBuffer = NULL;
@@ -483,8 +491,8 @@ void SchannelContext::decryptAndProcessData(const SafeByteArray& data) {
// contexts. Additionally, a second SECBUFFER_TOKEN type buffer that contains a security token
// must also be supplied.
//
- inBuffers[0].pvBuffer = (char*)(&receivedData_[0]);
- inBuffers[0].cbBuffer = (unsigned long)receivedData_.size();
+ inBuffers[0].pvBuffer = static_cast<char*>(&receivedData_[0]);
+ inBuffers[0].cbBuffer = static_cast<unsigned long>(receivedData_.size());
inBuffers[0].BufferType = SECBUFFER_DATA;
inBuffers[1].BufferType = SECBUFFER_EMPTY;
@@ -578,7 +586,7 @@ void SchannelContext::encryptAndSendData(const SafeByteArray& data) {
outBuffers[0].BufferType = SECBUFFER_STREAM_HEADER;
outBuffers[1].pvBuffer = &sendBuffer[0] + streamSizes_.cbHeader;
- outBuffers[1].cbBuffer = (unsigned long)bytesToSend;
+ outBuffers[1].cbBuffer = static_cast<unsigned long>(bytesToSend);
outBuffers[1].BufferType = SECBUFFER_DATA;
outBuffers[2].pvBuffer = &sendBuffer[0] + streamSizes_.cbHeader + bytesToSend;
@@ -645,6 +653,7 @@ std::vector<Certificate::ref> SchannelContext::getPeerCertificateChain() const {
SECURITY_STATUS status = QueryContextAttributes(contextHandle_, SECPKG_ATTR_REMOTE_CERT_CONTEXT, pServerCert.Reset());
if (status != SEC_E_OK) {
+ SWIFT_LOG(debug) << "Error while Querying the Certificate Chain" << std::endl;
return certificateChain;
}
certificateChain.push_back(std::make_shared<SchannelCertificate>(pServerCert));
@@ -678,6 +687,10 @@ ByteArray SchannelContext::getFinishMessage() const {
if (ret == SEC_E_OK) {
return createByteArray(((unsigned char*) bindings.Bindings) + bindings.Bindings->dwApplicationDataOffset + 11 /* tls-unique:*/, bindings.Bindings->cbApplicationDataLength - 11);
}
+ else {
+ SWIFT_LOG(debug) << "Error while retrieving Finish Message" << std::endl;
+ }
+
return ByteArray();
}
diff --git a/Swiften/VCards/UnitTest/VCardManagerTest.cpp b/Swiften/VCards/UnitTest/VCardManagerTest.cpp
index 3d5338d..669c3ff 100644
--- a/Swiften/VCards/UnitTest/VCardManagerTest.cpp
+++ b/Swiften/VCards/UnitTest/VCardManagerTest.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2016 Isode Limited.
+ * Copyright (c) 2010-2018 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -31,7 +31,17 @@ class VCardManagerTest : public CppUnit::TestFixture {
CPPUNIT_TEST(testRequest_Error);
CPPUNIT_TEST(testRequest_VCardAlreadyRequested);
CPPUNIT_TEST(testRequest_AfterPreviousRequest);
- CPPUNIT_TEST(testRequestOwnVCard);
+
+ CPPUNIT_TEST(testRequestVCard_ReturnFullVCard);
+ CPPUNIT_TEST(testRequestVCard_ReturnEmptyVCard);
+ CPPUNIT_TEST(testRequestVCard_ReturnItemNotFoundError);
+ CPPUNIT_TEST(testRequestVCard_ReturnFeatureNotImplementedError);
+
+ CPPUNIT_TEST(testRequestOwnVCard_ReturnFullVCard);
+ CPPUNIT_TEST(testRequestOwnVCard_ReturnEmptyVCard);
+ CPPUNIT_TEST(testRequestOwnVCard_ReturnItemNotFoundError);
+ CPPUNIT_TEST(testRequestOwnVCard_ReturnFeatureNotImplementedError);
+
CPPUNIT_TEST(testCreateSetVCardRequest);
CPPUNIT_TEST(testCreateSetVCardRequest_Error);
CPPUNIT_TEST_SUITE_END();
@@ -54,7 +64,7 @@ class VCardManagerTest : public CppUnit::TestFixture {
}
void testGet_NewVCardRequestsVCard() {
- std::shared_ptr<VCardManager> testling = createManager();
+ auto testling = createManager();
VCard::ref result = testling->getVCardAndRequestWhenNeeded(JID("foo@bar.com/baz"));
CPPUNIT_ASSERT(!result);
@@ -63,7 +73,7 @@ class VCardManagerTest : public CppUnit::TestFixture {
}
void testGet_ExistingVCard() {
- std::shared_ptr<VCardManager> testling = createManager();
+ auto testling = createManager();
VCard::ref vcard(new VCard());
vcard->setFullName("Foo Bar");
vcardStorage->setVCard(JID("foo@bar.com/baz"), vcard);
@@ -75,7 +85,7 @@ class VCardManagerTest : public CppUnit::TestFixture {
}
void testRequest_RequestsVCard() {
- std::shared_ptr<VCardManager> testling = createManager();
+ auto testling = createManager();
testling->requestVCard(JID("foo@bar.com/baz"));
CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size()));
@@ -83,7 +93,7 @@ class VCardManagerTest : public CppUnit::TestFixture {
}
void testRequest_ReceiveEmitsNotification() {
- std::shared_ptr<VCardManager> testling = createManager();
+ auto testling = createManager();
testling->requestVCard(JID("foo@bar.com/baz"));
stanzaChannel->onIQReceived(createVCardResult());
@@ -96,7 +106,7 @@ class VCardManagerTest : public CppUnit::TestFixture {
}
void testRequest_Error() {
- std::shared_ptr<VCardManager> testling = createManager();
+ auto testling = createManager();
testling->requestVCard(JID("foo@bar.com/baz"));
stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID()));
@@ -105,7 +115,7 @@ class VCardManagerTest : public CppUnit::TestFixture {
}
void testRequest_VCardAlreadyRequested() {
- std::shared_ptr<VCardManager> testling = createManager();
+ auto testling = createManager();
testling->requestVCard(JID("foo@bar.com/baz"));
VCard::ref result = testling->getVCardAndRequestWhenNeeded(JID("foo@bar.com/baz"));
@@ -114,7 +124,7 @@ class VCardManagerTest : public CppUnit::TestFixture {
}
void testRequest_AfterPreviousRequest() {
- std::shared_ptr<VCardManager> testling = createManager();
+ auto testling = createManager();
testling->requestVCard(JID("foo@bar.com/baz"));
stanzaChannel->onIQReceived(createVCardResult());
testling->requestVCard(JID("foo@bar.com/baz"));
@@ -123,8 +133,60 @@ class VCardManagerTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(1, JID("foo@bar.com/baz"), IQ::Get));
}
- void testRequestOwnVCard() {
- std::shared_ptr<VCardManager> testling = createManager();
+ void testRequestVCard_ReturnFullVCard() {
+ auto testling = createManager();
+ testling->requestVCard(JID("foo@bar.com/baz"));
+ stanzaChannel->onIQReceived(createVCardResult());
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size()));
+ CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID("foo@bar.com/baz"), IQ::Get));
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size()));
+ CPPUNIT_ASSERT_EQUAL(JID("foo@bar.com/baz"), changes[0].first);
+ CPPUNIT_ASSERT_EQUAL(std::string("Foo Bar"), changes[0].second->getFullName());
+ CPPUNIT_ASSERT_EQUAL(false, changes[0].second->isEmpty());
+ }
+
+ void testRequestVCard_ReturnEmptyVCard() {
+ auto testling = createManager();
+ testling->requestVCard(JID("foo@bar.com/baz"));
+ stanzaChannel->onIQReceived([&](){
+ auto vcard = std::make_shared<VCard>();
+ return IQ::createResult(JID("foo@bar.com/baz"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), vcard);
+ }());
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size()));
+ CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID("foo@bar.com/baz"), IQ::Get));
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size()));
+ CPPUNIT_ASSERT_EQUAL(true, changes[0].second->isEmpty());
+ }
+
+ void testRequestVCard_ReturnItemNotFoundError() {
+ auto testling = createManager();
+ testling->requestVCard(JID("foo@bar.com/baz"));
+ stanzaChannel->onIQReceived([&](){
+ return IQ::createError(JID("foo@bar.com/baz"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), ErrorPayload::ItemNotFound);
+ }());
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size()));
+ CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID("foo@bar.com/baz"), IQ::Get));
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size()));
+ CPPUNIT_ASSERT_EQUAL(true, changes[0].second->isEmpty());
+ }
+
+ void testRequestVCard_ReturnFeatureNotImplementedError() {
+ auto testling = createManager();
+ testling->requestVCard(JID("foo@bar.com/baz"));
+ stanzaChannel->onIQReceived([&](){
+ return IQ::createError(JID("foo@bar.com/baz"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), ErrorPayload::FeatureNotImplemented);
+ }());
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size()));
+ CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID("foo@bar.com/baz"), IQ::Get));
+ CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size()));
+ }
+
+ void testRequestOwnVCard_ReturnFullVCard() {
+ auto testling = createManager();
testling->requestVCard(ownJID);
stanzaChannel->onIQReceived(createOwnVCardResult());
@@ -139,8 +201,47 @@ class VCardManagerTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT_EQUAL(std::string("Myself"), ownChanges[0]->getFullName());
}
+ void testRequestOwnVCard_ReturnEmptyVCard() {
+ auto testling = createManager();
+ testling->requestVCard(ownJID);
+ stanzaChannel->onIQReceived([&](){
+ auto vcard = std::make_shared<VCard>();
+ return IQ::createResult(JID(), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), vcard);
+ }());
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size()));
+ CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID(), IQ::Get));
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size()));
+ CPPUNIT_ASSERT_EQUAL(true, changes[0].second->isEmpty());
+ }
+
+ void testRequestOwnVCard_ReturnItemNotFoundError() {
+ auto testling = createManager();
+ testling->requestVCard(ownJID);
+ stanzaChannel->onIQReceived([&](){
+ return IQ::createError(JID(), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), ErrorPayload::ItemNotFound);
+ }());
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size()));
+ CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID(), IQ::Get));
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size()));
+ CPPUNIT_ASSERT_EQUAL(true, changes[0].second->isEmpty());
+ }
+
+ void testRequestOwnVCard_ReturnFeatureNotImplementedError() {
+ auto testling = createManager();
+ testling->requestVCard(ownJID);
+ stanzaChannel->onIQReceived([&](){
+ return IQ::createError(JID(), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), ErrorPayload::FeatureNotImplemented);
+ }());
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size()));
+ CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<VCard>(0, JID(), IQ::Get));
+ CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size()));
+ }
+
void testCreateSetVCardRequest() {
- std::shared_ptr<VCardManager> testling = createManager();
+ auto testling = createManager();
VCard::ref vcard = std::make_shared<VCard>();
vcard->setFullName("New Name");
SetVCardRequest::ref request = testling->createSetVCardRequest(vcard);
@@ -154,7 +255,7 @@ class VCardManagerTest : public CppUnit::TestFixture {
}
void testCreateSetVCardRequest_Error() {
- std::shared_ptr<VCardManager> testling = createManager();
+ auto testling = createManager();
VCard::ref vcard = std::make_shared<VCard>();
vcard->setFullName("New Name");
SetVCardRequest::ref request = testling->createSetVCardRequest(vcard);
diff --git a/Swiften/VCards/VCardManager.cpp b/Swiften/VCards/VCardManager.cpp
index 95b96fa..9423702 100644
--- a/Swiften/VCards/VCardManager.cpp
+++ b/Swiften/VCards/VCardManager.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2016 Isode Limited.
+ * Copyright (c) 2010-2018 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -50,10 +50,9 @@ void VCardManager::requestOwnVCard() {
requestVCard(JID());
}
-
void VCardManager::handleVCardReceived(const JID& actualJID, VCard::ref vcard, ErrorPayload::ref error) {
requestedVCards.erase(actualJID);
- if (!error) {
+ if (!error || (error && error->getCondition() == ErrorPayload::ItemNotFound)) {
if (!vcard) {
vcard = VCard::ref(new VCard());
}