From 8ec22a9c5591584fd1725ed028d714c51b7509d3 Mon Sep 17 00:00:00 2001
From: Richard Maudsley <richard.maudsley@isode.com>
Date: Thu, 17 Jul 2014 10:46:50 +0100
Subject: Fix invalid characters being allowed in JID domains

Test-Information:

Prepare valid and invalid JIDs and make sure that isValid() is reported correctly. Added unit tests.

Change-Id: Ic4d86f8b6ea9defc517ada2f8e3cc54979237cf4

diff --git a/Slimber/Qt/SConscript b/Slimber/Qt/SConscript
index 054d8b6..b4f0bc3 100644
--- a/Slimber/Qt/SConscript
+++ b/Slimber/Qt/SConscript
@@ -8,13 +8,19 @@ myenv.UseFlags(env["SLIMBER_FLAGS"])
 myenv.UseFlags(env["LIMBER_FLAGS"])
 myenv.UseFlags(env["SWIFTOOLS_FLAGS"])
 myenv.UseFlags(env["SWIFTEN_FLAGS"])
-myenv.UseFlags(env["LIBIDN_FLAGS"])
 myenv.UseFlags(env["BOOST_FLAGS"])
 myenv.UseFlags(env.get("LIBXML_FLAGS", ""))
 myenv.UseFlags(env.get("EXPAT_FLAGS", ""))
 myenv.UseFlags(env.get("AVAHI_FLAGS", ""))
 myenv.UseFlags(myenv["PLATFORM_FLAGS"])
 
+if myenv.get("HAVE_ICU") :
+	myenv.MergeFlags(env["ICU_FLAGS"])
+	myenv.Append(CPPDEFINES = ["HAVE_ICU"])
+if myenv.get("HAVE_LIBIDN") :
+	myenv.MergeFlags(env["LIBIDN_FLAGS"])
+	myenv.Append(CPPDEFINES = ["HAVE_LIBIDN"])
+
 myenv.Tool("qt4", toolpath = ["#/BuildTools/SCons/Tools"])
 myenv.Tool("nsis", toolpath = ["#/BuildTools/SCons/Tools"])
 myenv.EnableQt4Modules(['QtCore', 'QtGui'], debug = False)
diff --git a/Sluift/sluift.cpp b/Sluift/sluift.cpp
index 5e837c1..bef2e3d 100644
--- a/Sluift/sluift.cpp
+++ b/Sluift/sluift.cpp
@@ -346,7 +346,13 @@ SLUIFT_LUA_FUNCTION(Base64, decode) {
 
 SLUIFT_LUA_FUNCTION(IDN, encode) {
 	IDNConverter* converter = Sluift::globals.networkFactories.getIDNConverter();
-	lua_pushstring(L, converter->getIDNAEncoded(Lua::checkString(L, 1)).c_str());
+	boost::optional<std::string> encoded = converter->getIDNAEncoded(Lua::checkString(L, 1));
+	if (!encoded) {
+		lua_pushnil(L);
+		lua_pushstring(L, "Error encoding domain name");
+		return 2;
+	}
+	lua_pushstring(L, encoded->c_str());
 	return 1;
 }
 
diff --git a/Swiften/IDN/ICUConverter.cpp b/Swiften/IDN/ICUConverter.cpp
index 18ff231..f698eb9 100644
--- a/Swiften/IDN/ICUConverter.cpp
+++ b/Swiften/IDN/ICUConverter.cpp
@@ -135,20 +135,20 @@ SafeByteArray ICUConverter::getStringPrepared(const SafeByteArray& s, StringPrep
 	return createSafeByteArray(reinterpret_cast<const char*>(vecptr(preparedData)));
 }
 
-std::string ICUConverter::getIDNAEncoded(const std::string& domain) {
+boost::optional<std::string> ICUConverter::getIDNAEncoded(const std::string& domain) {
 	UErrorCode status = U_ZERO_ERROR;
 	ICUString icuInput = convertToICUString(domain);
 	ICUString icuResult;
 	icuResult.resize(icuInput.size());
 	UParseError parseError;
-	int32_t icuResultLength = uidna_IDNToASCII(vecptr(icuInput), numeric_cast<int32_t>(icuInput.size()), vecptr(icuResult), numeric_cast<int32_t>(icuResult.size()), UIDNA_DEFAULT, &parseError, &status);
+	int32_t icuResultLength = uidna_IDNToASCII(vecptr(icuInput), numeric_cast<int32_t>(icuInput.size()), vecptr(icuResult), numeric_cast<int32_t>(icuResult.size()), UIDNA_USE_STD3_RULES, &parseError, &status);
 	if (status == U_BUFFER_OVERFLOW_ERROR) {
 		status = U_ZERO_ERROR;
 		icuResult.resize(numeric_cast<size_t>(icuResultLength));
-		icuResultLength = uidna_IDNToASCII(vecptr(icuInput), numeric_cast<int32_t>(icuInput.size()), vecptr(icuResult), numeric_cast<int32_t>(icuResult.size()), UIDNA_DEFAULT, &parseError, &status);
+		icuResultLength = uidna_IDNToASCII(vecptr(icuInput), numeric_cast<int32_t>(icuInput.size()), vecptr(icuResult), numeric_cast<int32_t>(icuResult.size()), UIDNA_USE_STD3_RULES, &parseError, &status);
 	}
 	if (U_FAILURE(status)) {
-		return domain;
+		return boost::optional<std::string>();
 	}
 	icuResult.resize(numeric_cast<size_t>(icuResultLength));
 	return convertToString(icuResult);
diff --git a/Swiften/IDN/ICUConverter.h b/Swiften/IDN/ICUConverter.h
index 8ba9bb5..05eafcc 100644
--- a/Swiften/IDN/ICUConverter.h
+++ b/Swiften/IDN/ICUConverter.h
@@ -17,6 +17,6 @@ namespace Swift {
 			virtual std::string getStringPrepared(const std::string& s, StringPrepProfile profile) SWIFTEN_OVERRIDE;
 			virtual SafeByteArray getStringPrepared(const SafeByteArray& s, StringPrepProfile profile) SWIFTEN_OVERRIDE;
 
-			virtual std::string getIDNAEncoded(const std::string& s) SWIFTEN_OVERRIDE;
+			virtual boost::optional<std::string> getIDNAEncoded(const std::string& s) SWIFTEN_OVERRIDE;
 	};
 }
diff --git a/Swiften/IDN/IDNConverter.h b/Swiften/IDN/IDNConverter.h
index c55d969..f6974bc 100644
--- a/Swiften/IDN/IDNConverter.h
+++ b/Swiften/IDN/IDNConverter.h
@@ -9,6 +9,7 @@
 #include <string>
 #include <Swiften/Base/API.h>
 #include <Swiften/Base/SafeByteArray.h>
+#include <boost/optional.hpp>
 
 namespace Swift {
 	class SWIFTEN_API IDNConverter {
@@ -26,6 +27,6 @@ namespace Swift {
 			virtual SafeByteArray getStringPrepared(const SafeByteArray& s, StringPrepProfile profile) = 0;
 
 			// Thread-safe
-			virtual std::string getIDNAEncoded(const std::string& s) = 0;
+			virtual boost::optional<std::string> getIDNAEncoded(const std::string& s) = 0;
 	};
 }
diff --git a/Swiften/IDN/LibIDNConverter.cpp b/Swiften/IDN/LibIDNConverter.cpp
index c4a1c18..45b1d14 100644
--- a/Swiften/IDN/LibIDNConverter.cpp
+++ b/Swiften/IDN/LibIDNConverter.cpp
@@ -65,15 +65,15 @@ SafeByteArray LibIDNConverter::getStringPrepared(const SafeByteArray& s, StringP
 	return createSafeByteArray(reinterpret_cast<const char*>(vecptr(preparedData)));
 }
 
-std::string LibIDNConverter::getIDNAEncoded(const std::string& domain) {
+boost::optional<std::string> LibIDNConverter::getIDNAEncoded(const std::string& domain) {
 	char* output;
-	if (idna_to_ascii_8z(domain.c_str(), &output, 0) == IDNA_SUCCESS) {
+	if (idna_to_ascii_8z(domain.c_str(), &output, IDNA_USE_STD3_ASCII_RULES) == IDNA_SUCCESS) {
 		std::string result(output);
 		free(output);
 		return result;
 	}
 	else {
-		return domain;
+		return boost::optional<std::string>();
 	}
 }
 
diff --git a/Swiften/IDN/LibIDNConverter.h b/Swiften/IDN/LibIDNConverter.h
index 23f6bbd..4cfff1a 100644
--- a/Swiften/IDN/LibIDNConverter.h
+++ b/Swiften/IDN/LibIDNConverter.h
@@ -17,7 +17,7 @@ namespace Swift {
 			virtual std::string getStringPrepared(const std::string& s, StringPrepProfile profile) SWIFTEN_OVERRIDE;
 			virtual SafeByteArray getStringPrepared(const SafeByteArray& s, StringPrepProfile profile) SWIFTEN_OVERRIDE;
 
-			virtual std::string getIDNAEncoded(const std::string& s) SWIFTEN_OVERRIDE;
+			virtual boost::optional<std::string> getIDNAEncoded(const std::string& s) SWIFTEN_OVERRIDE;
 	};
 }
 
diff --git a/Swiften/IDN/UnitTest/IDNConverterTest.cpp b/Swiften/IDN/UnitTest/IDNConverterTest.cpp
index 285cf4b..a66e141 100644
--- a/Swiften/IDN/UnitTest/IDNConverterTest.cpp
+++ b/Swiften/IDN/UnitTest/IDNConverterTest.cpp
@@ -19,6 +19,7 @@ class IDNConverterTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST(testStringPrep_Empty);
 		CPPUNIT_TEST(testGetEncoded);
 		CPPUNIT_TEST(testGetEncoded_International);
+		CPPUNIT_TEST(testGetEncoded_Invalid);
 		CPPUNIT_TEST_SUITE_END();
 
 	public:
@@ -39,15 +40,21 @@ class IDNConverterTest : public CppUnit::TestFixture {
 		}
 
 		void testGetEncoded() {
-			std::string result = testling->getIDNAEncoded("www.swift.im");
-			CPPUNIT_ASSERT_EQUAL(std::string("www.swift.im"), result);
+			boost::optional<std::string> result = testling->getIDNAEncoded("www.swift.im");
+			CPPUNIT_ASSERT(!!result);
+			CPPUNIT_ASSERT_EQUAL(std::string("www.swift.im"), *result);
 		}
 
 		void testGetEncoded_International() {
-			std::string result = testling->getIDNAEncoded("www.tron\xc3\x87on.com");
-			CPPUNIT_ASSERT_EQUAL(std::string("www.xn--tronon-zua.com"), result); 
+			boost::optional<std::string> result = testling->getIDNAEncoded("www.tron\xc3\x87on.com");
+			CPPUNIT_ASSERT(!!result);
+			CPPUNIT_ASSERT_EQUAL(std::string("www.xn--tronon-zua.com"), *result); 
 		}
 
+		void testGetEncoded_Invalid() {
+			boost::optional<std::string> result = testling->getIDNAEncoded("www.foo,bar.com");
+			CPPUNIT_ASSERT(!result);
+		}
 
 	private:
 		boost::shared_ptr<IDNConverter> testling;
diff --git a/Swiften/JID/JID.cpp b/Swiften/JID/JID.cpp
index 0f2d8d1..fcd49f9 100644
--- a/Swiften/JID/JID.cpp
+++ b/Swiften/JID/JID.cpp
@@ -177,7 +177,7 @@ void JID::initializeFromString(const std::string& jid) {
 
 
 void JID::nameprepAndSetComponents(const std::string& node, const std::string& domain, const std::string& resource) {
-	if (domain.empty()) {
+	if (domain.empty() || !idnConverter->getIDNAEncoded(domain)) {
 		valid_ = false;
 		return;
 	}
diff --git a/Swiften/JID/UnitTest/JIDTest.cpp b/Swiften/JID/UnitTest/JIDTest.cpp
index 72ca884..03203de 100644
--- a/Swiften/JID/UnitTest/JIDTest.cpp
+++ b/Swiften/JID/UnitTest/JIDTest.cpp
@@ -19,6 +19,7 @@ class JIDTest : public CppUnit::TestFixture
 		CPPUNIT_TEST(testConstructorWithString_NoNode);
 		CPPUNIT_TEST(testConstructorWithString_EmptyResource);
 		CPPUNIT_TEST(testConstructorWithString_OnlyDomain);
+		CPPUNIT_TEST(testConstructorWithString_InvalidDomain);
 		CPPUNIT_TEST(testConstructorWithString_UpperCaseNode);
 		CPPUNIT_TEST(testConstructorWithString_UpperCaseDomain);
 		CPPUNIT_TEST(testConstructorWithString_UpperCaseResource);
@@ -107,6 +108,10 @@ class JIDTest : public CppUnit::TestFixture
 			CPPUNIT_ASSERT(testling.isBare());
 		}
 
+		void testConstructorWithString_InvalidDomain() {
+			CPPUNIT_ASSERT(!JID("foo@bar,baz").isValid());
+		}
+
 		void testConstructorWithString_UpperCaseNode() {
 			JID testling("Fo\xCE\xA9@bar");
 
diff --git a/Swiften/Network/CachingDomainNameResolver.cpp b/Swiften/Network/CachingDomainNameResolver.cpp
index 4cf8286..fea14a3 100644
--- a/Swiften/Network/CachingDomainNameResolver.cpp
+++ b/Swiften/Network/CachingDomainNameResolver.cpp
@@ -17,9 +17,9 @@ CachingDomainNameResolver::~CachingDomainNameResolver() {
 
 }
 
-DomainNameServiceQuery::ref CachingDomainNameResolver::createServiceQuery(const std::string& name) {
+DomainNameServiceQuery::ref CachingDomainNameResolver::createServiceQuery(const std::string& serviceLookupPrefix, const std::string& domain) {
 	//TODO: Cache
-	return realResolver->createServiceQuery(name);
+	return realResolver->createServiceQuery(serviceLookupPrefix, domain);
 }
 
 DomainNameAddressQuery::ref CachingDomainNameResolver::createAddressQuery(const std::string& name) {
diff --git a/Swiften/Network/CachingDomainNameResolver.h b/Swiften/Network/CachingDomainNameResolver.h
index 66b4d68..3d50676 100644
--- a/Swiften/Network/CachingDomainNameResolver.h
+++ b/Swiften/Network/CachingDomainNameResolver.h
@@ -22,7 +22,7 @@ namespace Swift {
 			CachingDomainNameResolver(DomainNameResolver* realResolver, EventLoop* eventLoop);
 			~CachingDomainNameResolver();
 
-			virtual DomainNameServiceQuery::ref createServiceQuery(const std::string& name);
+			virtual DomainNameServiceQuery::ref createServiceQuery(const std::string& serviceLookupPrefix, const std::string& domain);
 			virtual DomainNameAddressQuery::ref createAddressQuery(const std::string& name);
 
 		private:
diff --git a/Swiften/Network/Connector.cpp b/Swiften/Network/Connector.cpp
index da2490f..1db1eac 100644
--- a/Swiften/Network/Connector.cpp
+++ b/Swiften/Network/Connector.cpp
@@ -36,7 +36,7 @@ void Connector::start() {
 		timer->onTick.connect(boost::bind(&Connector::handleTimeout, shared_from_this()));
 	}
 	if (serviceLookupPrefix) {
-		serviceQuery = resolver->createServiceQuery((*serviceLookupPrefix) + hostname);
+		serviceQuery = resolver->createServiceQuery(*serviceLookupPrefix, hostname);
 		serviceQuery->onResult.connect(boost::bind(&Connector::handleServiceQueryResult, shared_from_this(), _1));
 		serviceQuery->run();
 	}
diff --git a/Swiften/Network/DomainNameResolver.h b/Swiften/Network/DomainNameResolver.h
index 491586a..dc7013e 100644
--- a/Swiften/Network/DomainNameResolver.h
+++ b/Swiften/Network/DomainNameResolver.h
@@ -20,7 +20,7 @@ namespace Swift {
 		public:
 			virtual ~DomainNameResolver();
 
-			virtual boost::shared_ptr<DomainNameServiceQuery> createServiceQuery(const std::string& name) = 0;
+			virtual boost::shared_ptr<DomainNameServiceQuery> createServiceQuery(const std::string& serviceLookupPrefix, const std::string& domain) = 0;
 			virtual boost::shared_ptr<DomainNameAddressQuery> createAddressQuery(const std::string& name) = 0;
 	};
 }
diff --git a/Swiften/Network/PlatformDomainNameAddressQuery.cpp b/Swiften/Network/PlatformDomainNameAddressQuery.cpp
index ec7e663..91d15b9 100644
--- a/Swiften/Network/PlatformDomainNameAddressQuery.cpp
+++ b/Swiften/Network/PlatformDomainNameAddressQuery.cpp
@@ -13,7 +13,11 @@
 
 namespace Swift {
 
-PlatformDomainNameAddressQuery::PlatformDomainNameAddressQuery(const std::string& host, EventLoop* eventLoop, PlatformDomainNameResolver* resolver) : PlatformDomainNameQuery(resolver), hostname(host), eventLoop(eventLoop) {
+PlatformDomainNameAddressQuery::PlatformDomainNameAddressQuery(const boost::optional<std::string>& host, EventLoop* eventLoop, PlatformDomainNameResolver* resolver) : PlatformDomainNameQuery(resolver), hostnameValid(false), eventLoop(eventLoop) {
+	if (!!host) {
+		hostname = *host;
+		hostnameValid = true;
+	}
 }
 
 void PlatformDomainNameAddressQuery::run() {
@@ -21,6 +25,10 @@ void PlatformDomainNameAddressQuery::run() {
 }
 
 void PlatformDomainNameAddressQuery::runBlocking() {
+	if (!hostnameValid) {
+		emitError();
+		return;
+	}
 	//std::cout << "PlatformDomainNameResolver::doRun()" << std::endl;
 	boost::asio::ip::tcp::resolver resolver(ioService);
 	boost::asio::ip::tcp::resolver::query query(hostname, "5222");
diff --git a/Swiften/Network/PlatformDomainNameAddressQuery.h b/Swiften/Network/PlatformDomainNameAddressQuery.h
index e1dc05f..9e89086 100644
--- a/Swiften/Network/PlatformDomainNameAddressQuery.h
+++ b/Swiften/Network/PlatformDomainNameAddressQuery.h
@@ -20,7 +20,7 @@ namespace Swift {
 
 	class PlatformDomainNameAddressQuery : public DomainNameAddressQuery, public PlatformDomainNameQuery, public boost::enable_shared_from_this<PlatformDomainNameAddressQuery>, public EventOwner {
 		public:
-			PlatformDomainNameAddressQuery(const std::string& host, EventLoop* eventLoop, PlatformDomainNameResolver*);
+			PlatformDomainNameAddressQuery(const boost::optional<std::string>& host, EventLoop* eventLoop, PlatformDomainNameResolver*);
 
 			void run();
 
@@ -31,6 +31,7 @@ namespace Swift {
 		private:
 			boost::asio::io_service ioService;
 			std::string hostname;
+			bool hostnameValid;
 			EventLoop* eventLoop;
 	};
 }
diff --git a/Swiften/Network/PlatformDomainNameResolver.cpp b/Swiften/Network/PlatformDomainNameResolver.cpp
index 677f1d5..b65e884 100644
--- a/Swiften/Network/PlatformDomainNameResolver.cpp
+++ b/Swiften/Network/PlatformDomainNameResolver.cpp
@@ -38,8 +38,13 @@ PlatformDomainNameResolver::~PlatformDomainNameResolver() {
 	delete thread;
 }
 
-boost::shared_ptr<DomainNameServiceQuery> PlatformDomainNameResolver::createServiceQuery(const std::string& name) {
-	return boost::shared_ptr<DomainNameServiceQuery>(new PlatformDomainNameServiceQuery(idnConverter->getIDNAEncoded(name), eventLoop, this));
+boost::shared_ptr<DomainNameServiceQuery> PlatformDomainNameResolver::createServiceQuery(const std::string& serviceLookupPrefix, const std::string& domain) {
+	boost::optional<std::string> encodedDomain = idnConverter->getIDNAEncoded(domain);
+	std::string result;
+	if (encodedDomain) {
+		result = serviceLookupPrefix + *encodedDomain;
+	}
+	return boost::shared_ptr<DomainNameServiceQuery>(new PlatformDomainNameServiceQuery(result, eventLoop, this));
 }
 
 boost::shared_ptr<DomainNameAddressQuery> PlatformDomainNameResolver::createAddressQuery(const std::string& name) {
diff --git a/Swiften/Network/PlatformDomainNameResolver.h b/Swiften/Network/PlatformDomainNameResolver.h
index 25d87cf..6c3bf10 100644
--- a/Swiften/Network/PlatformDomainNameResolver.h
+++ b/Swiften/Network/PlatformDomainNameResolver.h
@@ -26,7 +26,7 @@ namespace Swift {
 			PlatformDomainNameResolver(IDNConverter* idnConverter, EventLoop* eventLoop);
 			~PlatformDomainNameResolver();
 
-			virtual DomainNameServiceQuery::ref createServiceQuery(const std::string& name);
+			virtual DomainNameServiceQuery::ref createServiceQuery(const std::string& serviceLookupPrefix, const std::string& domain);
 			virtual DomainNameAddressQuery::ref createAddressQuery(const std::string& name);
 
 		private:
diff --git a/Swiften/Network/PlatformDomainNameServiceQuery.cpp b/Swiften/Network/PlatformDomainNameServiceQuery.cpp
index 5788d2f..58cf8d2 100644
--- a/Swiften/Network/PlatformDomainNameServiceQuery.cpp
+++ b/Swiften/Network/PlatformDomainNameServiceQuery.cpp
@@ -38,7 +38,11 @@ using namespace Swift;
 
 namespace Swift {
 
-PlatformDomainNameServiceQuery::PlatformDomainNameServiceQuery(const std::string& service, EventLoop* eventLoop, PlatformDomainNameResolver* resolver) : PlatformDomainNameQuery(resolver), eventLoop(eventLoop), service(service) {
+PlatformDomainNameServiceQuery::PlatformDomainNameServiceQuery(const boost::optional<std::string>& serviceName, EventLoop* eventLoop, PlatformDomainNameResolver* resolver) : PlatformDomainNameQuery(resolver), eventLoop(eventLoop), serviceValid(false) {
+	if (!!serviceName) {
+		service = *serviceName;
+		serviceValid = true;
+	}
 }
 
 void PlatformDomainNameServiceQuery::run() {
@@ -46,6 +50,11 @@ void PlatformDomainNameServiceQuery::run() {
 }
 
 void PlatformDomainNameServiceQuery::runBlocking() {
+	if (!serviceValid) {
+		emitError();
+		return;
+	}
+
 	SWIFT_LOG(debug) << "Querying " << service << std::endl;
 
 	std::vector<DomainNameServiceQuery::Result> records;
diff --git a/Swiften/Network/PlatformDomainNameServiceQuery.h b/Swiften/Network/PlatformDomainNameServiceQuery.h
index 310e639..e105479 100644
--- a/Swiften/Network/PlatformDomainNameServiceQuery.h
+++ b/Swiften/Network/PlatformDomainNameServiceQuery.h
@@ -18,7 +18,7 @@ namespace Swift {
 
 	class PlatformDomainNameServiceQuery : public DomainNameServiceQuery, public PlatformDomainNameQuery, public boost::enable_shared_from_this<PlatformDomainNameServiceQuery>, public EventOwner {
 		public:
-			PlatformDomainNameServiceQuery(const std::string& service, EventLoop* eventLoop, PlatformDomainNameResolver* resolver);
+			PlatformDomainNameServiceQuery(const boost::optional<std::string>& serviceName, EventLoop* eventLoop, PlatformDomainNameResolver* resolver);
 
 			virtual void run();
 
@@ -29,5 +29,6 @@ namespace Swift {
 		private:
 			EventLoop* eventLoop;
 			std::string service;
+			bool serviceValid;
 	};
 }
diff --git a/Swiften/Network/StaticDomainNameResolver.cpp b/Swiften/Network/StaticDomainNameResolver.cpp
index ee18ee5..17d9c3b 100644
--- a/Swiften/Network/StaticDomainNameResolver.cpp
+++ b/Swiften/Network/StaticDomainNameResolver.cpp
@@ -108,8 +108,8 @@ void StaticDomainNameResolver::addXMPPClientService(const std::string& domain, c
 	addService("_xmpp-client._tcp." + domain, ServiceQuery::Result(hostname, port, 0, 0));
 }
 
-boost::shared_ptr<DomainNameServiceQuery> StaticDomainNameResolver::createServiceQuery(const std::string& name) {
-	return boost::shared_ptr<DomainNameServiceQuery>(new ServiceQuery(name, this, eventLoop, owner));
+boost::shared_ptr<DomainNameServiceQuery> StaticDomainNameResolver::createServiceQuery(const std::string& serviceLookupPrefix, const std::string& domain) {
+	return boost::shared_ptr<DomainNameServiceQuery>(new ServiceQuery(serviceLookupPrefix + domain, this, eventLoop, owner));
 }
 
 boost::shared_ptr<DomainNameAddressQuery> StaticDomainNameResolver::createAddressQuery(const std::string& name) {
diff --git a/Swiften/Network/StaticDomainNameResolver.h b/Swiften/Network/StaticDomainNameResolver.h
index 386179b..81ff040 100644
--- a/Swiften/Network/StaticDomainNameResolver.h
+++ b/Swiften/Network/StaticDomainNameResolver.h
@@ -48,7 +48,7 @@ namespace Swift {
 				isResponsive = b;
 			}
 
-			virtual boost::shared_ptr<DomainNameServiceQuery> createServiceQuery(const std::string& name);
+			virtual boost::shared_ptr<DomainNameServiceQuery> createServiceQuery(const std::string& serviceLookupPrefix, const std::string& domain);
 			virtual boost::shared_ptr<DomainNameAddressQuery> createAddressQuery(const std::string& name);
 		private:
 			EventLoop* eventLoop;
diff --git a/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp b/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp
index bc4f1a3..6d25f49 100644
--- a/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp
+++ b/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp
@@ -160,7 +160,7 @@ class DomainNameResolverTest : public CppUnit::TestFixture {
 		}
 
 		void testResolveService() {
-			boost::shared_ptr<DomainNameServiceQuery> query(createServiceQuery("_xmpp-client._tcp.xmpp-srv.test.swift.im"));
+			boost::shared_ptr<DomainNameServiceQuery> query(createServiceQuery("_xmpp-client._tcp.", "xmpp-srv.test.swift.im"));
 
 			query->run();
 			waitForResults();
@@ -202,8 +202,8 @@ class DomainNameResolverTest : public CppUnit::TestFixture {
 				resultsAvailable = true;
 			}
 
-			boost::shared_ptr<DomainNameServiceQuery> createServiceQuery(const std::string& domain) {
-				boost::shared_ptr<DomainNameServiceQuery> result = resolver->createServiceQuery(domain);
+			boost::shared_ptr<DomainNameServiceQuery> createServiceQuery(const std::string& serviceLookupPrefix, const std::string& domain) {
+				boost::shared_ptr<DomainNameServiceQuery> result = resolver->createServiceQuery(serviceLookupPrefix, domain);
 				result->onResult.connect(boost::bind(&DomainNameResolverTest::handleServiceQueryResult, this, _1));
 				return result;
 			}
diff --git a/Swiften/TLS/ServerIdentityVerifier.cpp b/Swiften/TLS/ServerIdentityVerifier.cpp
index 02459b9..0608a03 100644
--- a/Swiften/TLS/ServerIdentityVerifier.cpp
+++ b/Swiften/TLS/ServerIdentityVerifier.cpp
@@ -13,9 +13,13 @@
 
 namespace Swift {
 
-ServerIdentityVerifier::ServerIdentityVerifier(const JID& jid, IDNConverter* idnConverter) {
+ServerIdentityVerifier::ServerIdentityVerifier(const JID& jid, IDNConverter* idnConverter) : domainValid(false) {
 	domain = jid.getDomain();
-	encodedDomain = idnConverter->getIDNAEncoded(domain);
+	boost::optional<std::string> domainResult = idnConverter->getIDNAEncoded(domain);
+	if (!!domainResult) {
+		encodedDomain = *domainResult;
+		domainValid = true;
+	}
 }
 
 bool ServerIdentityVerifier::certificateVerifies(Certificate::ref certificate) {
@@ -67,6 +71,9 @@ bool ServerIdentityVerifier::certificateVerifies(Certificate::ref certificate) {
 }
 
 bool ServerIdentityVerifier::matchesDomain(const std::string& s) const {
+	if (!domainValid) {
+		return false;
+	}
 	if (boost::starts_with(s, "*.")) {
 		std::string matchString(s.substr(2, s.npos));
 		std::string matchDomain = encodedDomain;
diff --git a/Swiften/TLS/ServerIdentityVerifier.h b/Swiften/TLS/ServerIdentityVerifier.h
index 4167ce8..ea08749 100644
--- a/Swiften/TLS/ServerIdentityVerifier.h
+++ b/Swiften/TLS/ServerIdentityVerifier.h
@@ -29,5 +29,6 @@ namespace Swift {
 		private:
 			std::string domain;
 			std::string encodedDomain;
+			bool domainValid;
 	};
 }
-- 
cgit v0.10.2-6-g49f6