diff options
| -rw-r--r-- | Swiften/JID/JID.cpp | 41 | ||||
| -rw-r--r-- | Swiften/JID/JID.h | 1 | ||||
| -rw-r--r-- | Swiften/JID/UnitTest/JIDTest.cpp | 46 | 
3 files changed, 85 insertions, 3 deletions
diff --git a/Swiften/JID/JID.cpp b/Swiften/JID/JID.cpp index fff88e9..5c6ea9d 100644 --- a/Swiften/JID/JID.cpp +++ b/Swiften/JID/JID.cpp @@ -13,6 +13,7 @@  #include <Swiften/Base/String.h>  #include <Swiften/IDN/IDNConverter.h>  #include <Swiften/JID/JID.h> +#include <Swiften/Network/HostAddress.h>  #ifndef SWIFTEN_JID_NO_DEFAULT_IDN_CONVERTER  #include <memory> @@ -97,14 +98,47 @@ void JID::initializeFromString(const std::string& jid) {      }  } +void JID::setComponents(const std::string& node, const std::string& domain, const std::string& resource) { +    domain_ = domain; +    try { +        node_ = idnConverter->getStringPrepared(node, IDNConverter::XMPPNodePrep); +        resource_ = idnConverter->getStringPrepared(resource, IDNConverter::XMPPResourcePrep); +    } +    catch (...) { +        valid_ = false; +        return; +    } +}  void JID::nameprepAndSetComponents(const std::string& node, const std::string& domain, const std::string& resource) { -    if (domain.empty() || !idnConverter->getIDNAEncoded(domain)) { +    if (domain.empty() || (hasResource_ && resource.empty())) {          valid_ = false;          return;      } -    if (hasResource_ && resource.empty()) { +    // Handling IPv6 addresses according to RFC 3986 rules +    // saying that they are enclosed in square brackets +    // which we have to remove when passing to HostAddress +    if (domain.size() > 2 && domain.front() == '[' && domain.back() == ']') { +        auto inner = std::string(domain.begin() + 1, domain.end() - 1); +        auto hostAddress = HostAddress::fromString(inner); +        if (hostAddress && hostAddress->isValid()) { +            setComponents(node, domain, resource); +            return; +        } +    } + +    const auto isAnyOfNonNumericAndNotDot = std::any_of(std::begin(domain), std::end(domain), [](char c) {return !::isdigit(c) && c != '.'; }); + +    if (!isAnyOfNonNumericAndNotDot) { +        auto hostAddress = HostAddress::fromString(domain); +        if (hostAddress && hostAddress->isValid()) { +            setComponents(node, domain, resource); +            return; +        } +    } + +    if (!isAnyOfNonNumericAndNotDot || !idnConverter->getIDNAEncoded(domain)) {          valid_ = false;          return;      } @@ -118,7 +152,8 @@ void JID::nameprepAndSetComponents(const std::string& node, const std::string& d              domain_ = idnConverter->getStringPrepared(domain, IDNConverter::NamePrep);          }          resource_ = idnConverter->getStringPrepared(resource, IDNConverter::XMPPResourcePrep); -    } catch (...) { +    } +    catch (...) {          valid_ = false;          return;      } diff --git a/Swiften/JID/JID.h b/Swiften/JID/JID.h index dc92f53..e98b796 100644 --- a/Swiften/JID/JID.h +++ b/Swiften/JID/JID.h @@ -184,6 +184,7 @@ namespace Swift {          private:              void nameprepAndSetComponents(const std::string& node, const std::string& domain, const std::string& resource); +            void setComponents(const std::string& node, const std::string& domain, const std::string& resource);              void initializeFromString(const std::string&);          private: diff --git a/Swiften/JID/UnitTest/JIDTest.cpp b/Swiften/JID/UnitTest/JIDTest.cpp index 0753fb5..894378d 100644 --- a/Swiften/JID/UnitTest/JIDTest.cpp +++ b/Swiften/JID/UnitTest/JIDTest.cpp @@ -71,6 +71,12 @@ class JIDTest : public CppUnit::TestFixture          CPPUNIT_TEST(testGetUnescapedNode);          CPPUNIT_TEST(testGetUnescapedNode_XEP106Examples);          CPPUNIT_TEST(testStringPrepFailures); +        CPPUNIT_TEST(testConstructorWithString_DomainIPv4); +        CPPUNIT_TEST(testConstructorWithString_DomainNOTIPv4); +        CPPUNIT_TEST(testConstructorWithString_ValidDomainNOTIPv4); +        CPPUNIT_TEST(testConstructorWithString_DomainIPv6); +        CPPUNIT_TEST(testConstructorWithString_DomainInvalidIPv6); +        CPPUNIT_TEST(testConstructorWithString_DomainIPv6NoBrackets);          CPPUNIT_TEST_SUITE_END();      public: @@ -492,6 +498,46 @@ class JIDTest : public CppUnit::TestFixture              CPPUNIT_ASSERT_EQUAL(std::string("c:\\cool stuff"), JID("c\\3a\\cool\\20stuff@example.com").getUnescapedNode());              CPPUNIT_ASSERT_EQUAL(std::string("c:\\5commas"), JID("c\\3a\\5c5commas@example.com").getUnescapedNode());          } + +        void testConstructorWithString_DomainIPv4() { +            JID testling("foo@192.34.12.1/resource"); + +            CPPUNIT_ASSERT_EQUAL(std::string("foo"), testling.getNode()); +            CPPUNIT_ASSERT_EQUAL(std::string("192.34.12.1"), testling.getDomain()); +            CPPUNIT_ASSERT_EQUAL(std::string("resource"), testling.getResource()); +            CPPUNIT_ASSERT(!testling.isBare()); +            CPPUNIT_ASSERT(testling.isValid()); +        } + +        void testConstructorWithString_DomainNOTIPv4() { +            JID testling("foo@500.34.12.1/resource"); +            CPPUNIT_ASSERT(!testling.isValid()); +        } + +        void testConstructorWithString_ValidDomainNOTIPv4() { +            JID testling("foo@500.34.12.1a/resource"); +            CPPUNIT_ASSERT(testling.isValid()); +        } + +        void testConstructorWithString_DomainIPv6() { +            JID testling("foo@[fe80::a857:33ff:febd:3580]/resource"); + +            CPPUNIT_ASSERT_EQUAL(std::string("foo"), testling.getNode()); +            CPPUNIT_ASSERT_EQUAL(std::string("[fe80::a857:33ff:febd:3580]"), testling.getDomain()); +            CPPUNIT_ASSERT_EQUAL(std::string("resource"), testling.getResource()); +            CPPUNIT_ASSERT(!testling.isBare()); +            CPPUNIT_ASSERT(testling.isValid()); +        } + +        void testConstructorWithString_DomainInvalidIPv6() { +            JID testling("foo@[1111::a1111:1111:111!:!!!!]/resource"); +            CPPUNIT_ASSERT(!testling.isValid()); +        } + +        void testConstructorWithString_DomainIPv6NoBrackets() { +            JID testling("foo@fe80::a857:33ff:febd:3580/resource"); +            CPPUNIT_ASSERT(!testling.isValid()); +        }  };  CPPUNIT_TEST_SUITE_REGISTRATION(JIDTest);  | 
 Swift