diff options
25 files changed, 94 insertions, 37 deletions
diff --git a/Slimber/Qt/SConscript b/Slimber/Qt/SConscript index 054d8b6..b4f0bc3 100644 --- a/Slimber/Qt/SConscript +++ b/Slimber/Qt/SConscript @@ -2,25 +2,31 @@ import os, shutil, datetime Import("env") myenv = env.Clone() myenv["CXXFLAGS"] = filter(lambda x : x != "-Wfloat-equal", myenv["CXXFLAGS"]) 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) myenv.Append(CPPPATH = ["."]) if env["PLATFORM"] == "win32" : myenv.Append(LINKFLAGS = ["/SUBSYSTEM:WINDOWS"]) myenv.Append(LIBS = "qtmain") diff --git a/Sluift/sluift.cpp b/Sluift/sluift.cpp index 5e837c1..bef2e3d 100644 --- a/Sluift/sluift.cpp +++ b/Sluift/sluift.cpp @@ -340,19 +340,25 @@ SLUIFT_LUA_FUNCTION(Base64, decode) { return 1; } /******************************************************************************* * IDN Functions ******************************************************************************/ 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; } SLUIFT_LUA_FUNCTION(IDN, stringprep) { IDNConverter* converter = Sluift::globals.networkFactories.getIDNConverter(); IDNConverter::StringPrepProfile profile; std::string profileString = Lua::checkString(L, 2); if (profileString == "nameprep") { profile = IDNConverter::NamePrep; 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 @@ -129,29 +129,29 @@ SafeByteArray ICUConverter::getStringPrepared(const SafeByteArray& s, StringPrep return SafeByteArray(); } std::vector<char, SafeAllocator<char> > preparedData = getStringPreparedDetail(s, profile); if (preparedData.empty()) { throw std::exception(); } 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 @@ -11,12 +11,12 @@ #include <Swiften/Base/Override.h> #include <Swiften/IDN/IDNConverter.h> namespace Swift { class SWIFTEN_API ICUConverter : public IDNConverter { public: 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 @@ -3,29 +3,30 @@ * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <string> #include <Swiften/Base/API.h> #include <Swiften/Base/SafeByteArray.h> +#include <boost/optional.hpp> namespace Swift { class SWIFTEN_API IDNConverter { public: virtual ~IDNConverter(); enum StringPrepProfile { NamePrep, XMPPNodePrep, XMPPResourcePrep, SASLPrep }; virtual std::string getStringPrepared(const std::string& s, StringPrepProfile profile) = 0; 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 @@ -59,22 +59,22 @@ std::string LibIDNConverter::getStringPrepared(const std::string& s, StringPrepP SafeByteArray LibIDNConverter::getStringPrepared(const SafeByteArray& s, StringPrepProfile profile) { std::vector<char, SafeAllocator<char> > preparedData = getStringPreparedInternal<SafeByteArray, std::vector<char, SafeAllocator<char> > >(s, profile); if (preparedData.empty()) { throw std::exception(); } 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 @@ -11,13 +11,13 @@ #include <Swiften/Base/Override.h> #include <Swiften/IDN/IDNConverter.h> namespace Swift { class SWIFTEN_API LibIDNConverter : public IDNConverter { public: 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 @@ -13,18 +13,19 @@ using namespace Swift; class IDNConverterTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(IDNConverterTest); CPPUNIT_TEST(testStringPrep); CPPUNIT_TEST(testStringPrep_Empty); CPPUNIT_TEST(testGetEncoded); CPPUNIT_TEST(testGetEncoded_International); + CPPUNIT_TEST(testGetEncoded_Invalid); CPPUNIT_TEST_SUITE_END(); public: void setUp() { testling = boost::shared_ptr<IDNConverter>(PlatformIDNConverter::create()); } void testStringPrep() { std::string result = testling->getStringPrepared("tron\xc3\x87on", IDNConverter::NamePrep); @@ -33,24 +34,30 @@ class IDNConverterTest : public CppUnit::TestFixture { } void testStringPrep_Empty() { CPPUNIT_ASSERT_EQUAL(std::string(""), testling->getStringPrepared("", IDNConverter::NamePrep)); CPPUNIT_ASSERT_EQUAL(std::string(""), testling->getStringPrepared("", IDNConverter::XMPPNodePrep)); CPPUNIT_ASSERT_EQUAL(std::string(""), testling->getStringPrepared("", IDNConverter::XMPPResourcePrep)); } 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; }; CPPUNIT_TEST_SUITE_REGISTRATION(IDNConverterTest); 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 @@ -171,19 +171,19 @@ void JID::initializeFromString(const std::string& jid) { nameprepAndSetComponents("", nodeAndDomain.first, resource); } else { nameprepAndSetComponents(nodeAndDomain.first, nodeAndDomain.second, resource); } } 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; } #ifndef SWIFTEN_CACHE_JID_PREP node_ = idnConverter->getStringPrepared(node, IDNConverter::XMPPNodePrep); domain_ = idnConverter->getStringPrepared(domain, IDNConverter::NamePrep); resource_ = idnConverter->getStringPrepared(resource, IDNConverter::XMPPResourcePrep); #else boost::mutex::scoped_lock lock(namePrepCacheMutex); 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 @@ -13,18 +13,19 @@ using namespace Swift; class JIDTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(JIDTest); CPPUNIT_TEST(testConstructorWithString); CPPUNIT_TEST(testConstructorWithString_NoResource); 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); CPPUNIT_TEST(testConstructorWithString_EmptyNode); CPPUNIT_TEST(testConstructorWithString_IllegalResource); CPPUNIT_TEST(testConstructorWithString_SpacesInNode); CPPUNIT_TEST(testConstructorWithStrings); CPPUNIT_TEST(testConstructorWithStrings_EmptyDomain); CPPUNIT_TEST(testIsBare); @@ -101,18 +102,22 @@ class JIDTest : public CppUnit::TestFixture void testConstructorWithString_OnlyDomain() { JID testling("bar"); CPPUNIT_ASSERT_EQUAL(std::string(""), testling.getNode()); CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.getDomain()); CPPUNIT_ASSERT_EQUAL(std::string(""), testling.getResource()); CPPUNIT_ASSERT(testling.isBare()); } + void testConstructorWithString_InvalidDomain() { + CPPUNIT_ASSERT(!JID("foo@bar,baz").isValid()); + } + void testConstructorWithString_UpperCaseNode() { JID testling("Fo\xCE\xA9@bar"); CPPUNIT_ASSERT_EQUAL(std::string("fo\xCF\x89"), testling.getNode()); CPPUNIT_ASSERT_EQUAL(std::string("bar"), testling.getDomain()); } void testConstructorWithString_UpperCaseDomain() { JID testling("Fo\xCE\xA9"); 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 @@ -11,20 +11,20 @@ namespace Swift { CachingDomainNameResolver::CachingDomainNameResolver(DomainNameResolver* realResolver, EventLoop*) : realResolver(realResolver) { } 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) { //TODO: Cache return realResolver->createAddressQuery(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 @@ -16,16 +16,16 @@ */ namespace Swift { class EventLoop; class CachingDomainNameResolver : public DomainNameResolver { public: 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: DomainNameResolver* realResolver; }; } 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 @@ -30,19 +30,19 @@ void Connector::start() { assert(!currentConnection); assert(!serviceQuery); assert(!timer); queriedAllServices = false; if (timeoutMilliseconds > 0) { timer = timerFactory->createTimer(timeoutMilliseconds); 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(); } else { queryAddress(hostname); } } void Connector::stop() { 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 @@ -14,13 +14,13 @@ namespace Swift { class DomainNameServiceQuery; class DomainNameAddressQuery; class SWIFTEN_API DomainNameResolver { 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 @@ -7,26 +7,34 @@ #include <Swiften/Network/PlatformDomainNameAddressQuery.h> #include <boost/asio/ip/tcp.hpp> #include <Swiften/Network/PlatformDomainNameResolver.h> #include <Swiften/EventLoop/EventLoop.h> 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() { getResolver()->addQueryToQueue(shared_from_this()); } 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"); try { //std::cout << "PlatformDomainNameResolver::doRun(): Resolving" << std::endl; boost::asio::ip::tcp::resolver::iterator endpointIterator = resolver.resolve(query); //std::cout << "PlatformDomainNameResolver::doRun(): Resolved" << std::endl; if (endpointIterator == boost::asio::ip::tcp::resolver::iterator()) { //std::cout << "PlatformDomainNameResolver::doRun(): Error 1" << std::endl; 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 @@ -14,25 +14,26 @@ #include <Swiften/EventLoop/EventOwner.h> #include <string> namespace Swift { class PlatformDomainNameResolver; class EventLoop; 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(); private: void runBlocking(); void emitError(); 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 @@ -32,20 +32,25 @@ PlatformDomainNameResolver::PlatformDomainNameResolver(IDNConverter* idnConverte } PlatformDomainNameResolver::~PlatformDomainNameResolver() { stopRequested = true; addQueryToQueue(boost::shared_ptr<PlatformDomainNameQuery>()); thread->join(); 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) { return boost::shared_ptr<DomainNameAddressQuery>(new PlatformDomainNameAddressQuery(idnConverter->getIDNAEncoded(name), eventLoop, this)); } void PlatformDomainNameResolver::run() { while (!stopRequested) { PlatformDomainNameQuery::ref query; 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 @@ -20,19 +20,19 @@ namespace Swift { class IDNConverter; class EventLoop; class SWIFTEN_API PlatformDomainNameResolver : public DomainNameResolver { public: 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: void run(); void addQueryToQueue(PlatformDomainNameQuery::ref); private: friend class PlatformDomainNameServiceQuery; friend class PlatformDomainNameAddressQuery; 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 @@ -32,26 +32,35 @@ #include <Swiften/Base/foreach.h> #include <Swiften/Base/BoostRandomGenerator.h> #include <Swiften/Base/Log.h> #include <Swiften/Network/PlatformDomainNameResolver.h> 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() { getResolver()->addQueryToQueue(shared_from_this()); } void PlatformDomainNameServiceQuery::runBlocking() { + if (!serviceValid) { + emitError(); + return; + } + SWIFT_LOG(debug) << "Querying " << service << std::endl; std::vector<DomainNameServiceQuery::Result> records; #if defined(SWIFTEN_PLATFORM_WINDOWS) DNS_RECORD* responses; // FIXME: This conversion doesn't work if unicode is deffed above if (DnsQuery(service.c_str(), DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &responses, NULL) != ERROR_SUCCESS) { emitError(); 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 @@ -12,22 +12,23 @@ #include <Swiften/EventLoop/EventOwner.h> #include <string> #include <Swiften/Network/PlatformDomainNameQuery.h> namespace Swift { class EventLoop; 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(); private: void runBlocking(); void emitError(); 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 @@ -102,18 +102,18 @@ void StaticDomainNameResolver::addXMPPClientService(const std::string& domain, c addService("_xmpp-client._tcp." + domain, ServiceQuery::Result(hostname, address.getPort(), 0, 0)); addAddress(hostname, address.getAddress()); } void StaticDomainNameResolver::addXMPPClientService(const std::string& domain, const std::string& hostname, int port) { 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) { return boost::shared_ptr<DomainNameAddressQuery>(new AddressQuery(name, this, eventLoop, owner)); } } 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 @@ -42,19 +42,19 @@ namespace Swift { bool getIsResponsive() const { return isResponsive; } void setIsResponsive(bool b) { 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; bool isResponsive; AddressesMap addresses; ServicesCollection services; boost::shared_ptr<EventOwner> owner; }; } 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 @@ -154,19 +154,19 @@ class DomainNameResolverTest : public CppUnit::TestFixture { } CPPUNIT_ASSERT_EQUAL(numQueries, allAddressQueryResults.size()); for (size_t i = 0; i < numQueries; ++i) { CPPUNIT_ASSERT_EQUAL(std::string("10.0.0.0"), allAddressQueryResults[i].toString()); } } 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(); CPPUNIT_ASSERT_EQUAL(4, static_cast<int>(serviceQueryResult.size())); CPPUNIT_ASSERT_EQUAL(std::string("xmpp1.test.swift.im"), serviceQueryResult[0].hostname); CPPUNIT_ASSERT_EQUAL(5000, serviceQueryResult[0].port); CPPUNIT_ASSERT_EQUAL(0, serviceQueryResult[0].priority); CPPUNIT_ASSERT_EQUAL(1, serviceQueryResult[0].weight); @@ -196,20 +196,20 @@ class DomainNameResolverTest : public CppUnit::TestFixture { void handleAddressQueryResult(const std::vector<HostAddress>& addresses, boost::optional<DomainNameResolveError> error) { addressQueryResult = addresses; std::sort(addressQueryResult.begin(), addressQueryResult.end(), CompareHostAddresses()); allAddressQueryResults.insert(allAddressQueryResults.begin(), addresses.begin(), addresses.end()); addressQueryError = error; 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; } void handleServiceQueryResult(const std::vector<DomainNameServiceQuery::Result>& result) { serviceQueryResult = result; resultsAvailable = true; } 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 @@ -7,21 +7,25 @@ #include <Swiften/TLS/ServerIdentityVerifier.h> #include <boost/algorithm/string.hpp> #include <Swiften/Base/foreach.h> #include <Swiften/IDN/IDNConverter.h> 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) { bool hasSAN = false; if (certificate == NULL) { return false; } // DNS names @@ -61,18 +65,21 @@ bool ServerIdentityVerifier::certificateVerifies(Certificate::ref certificate) { return true; } } } return false; } 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; size_t dotIndex = matchDomain.find('.'); if (dotIndex != matchDomain.npos) { matchDomain = matchDomain.substr(dotIndex + 1, matchDomain.npos); } return matchString == matchDomain; } 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 @@ -23,11 +23,12 @@ namespace Swift { bool certificateVerifies(Certificate::ref); private: bool matchesDomain(const std::string&) const ; bool matchesAddress(const std::string&) const; private: std::string domain; std::string encodedDomain; + bool domainValid; }; } |