diff options
| author | Tobias Markmann <tm@ayena.de> | 2016-06-07 19:40:15 (GMT) | 
|---|---|---|
| committer | Kevin Smith <kevin.smith@isode.com> | 2016-06-14 20:04:42 (GMT) | 
| commit | 0d5dcec01a396ab64c559a5b0cd04eb38f2f1954 (patch) | |
| tree | 64bc61c8f51313787717afacfd5a8e4cc777b778 | |
| parent | 1dbcf543910b85b53a95461ed4770264e0ddbc4c (diff) | |
| download | swift-0d5dcec01a396ab64c559a5b0cd04eb38f2f1954.zip swift-0d5dcec01a396ab64c559a5b0cd04eb38f2f1954.tar.bz2 | |
Add support for URLs with IPv6 addresses in Swift::URL
Test-Information:
Added unit tests and test cases from RFC 2732.
All tests pass on OS X 10.11.5.
Change-Id: Ic76e57985109912871c05d12253f73d3653bd7a3
| -rw-r--r-- | Swiften/Base/URL.cpp | 45 | ||||
| -rw-r--r-- | Swiften/Base/UnitTest/URLTest.cpp | 123 | 
2 files changed, 159 insertions, 9 deletions
| diff --git a/Swiften/Base/URL.cpp b/Swiften/Base/URL.cpp index a9a1140..4a47a11 100644 --- a/Swiften/Base/URL.cpp +++ b/Swiften/Base/URL.cpp @@ -1,11 +1,12 @@  /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */  #include <Swiften/Base/URL.h> +#include <algorithm>  #include <iostream>  namespace Swift { @@ -62,18 +63,39 @@ URL URL::fromString(const std::string& urlString) {          std::string host;          boost::optional<int> port; -        colonIndex = hostAndPort.find(':'); -        if (colonIndex != std::string::npos) { -            host = unescape(hostAndPort.substr(0, colonIndex)); -            try { -                port = boost::lexical_cast<int>(hostAndPort.substr(colonIndex + 1)); +        if (hostAndPort[0] == '[') { +            // handle IPv6 address literals +            size_t addressEndIndex = hostAndPort.find(']'); +            if (addressEndIndex != std::string::npos) { +                host = hostAndPort.substr(1, addressEndIndex - 1); +                colonIndex = hostAndPort.find(':', addressEndIndex); +                if (colonIndex != std::string::npos) { +                    try { +                        port = boost::lexical_cast<int>(hostAndPort.substr(colonIndex + 1)); +                    } +                    catch (const boost::bad_lexical_cast&) { +                        return URL(); +                    } +                }              } -            catch (const boost::bad_lexical_cast&) { +            else {                  return URL();              }          }          else { -            host = unescape(hostAndPort); +            colonIndex = hostAndPort.find(':'); +            if (colonIndex != std::string::npos) { +                host = unescape(hostAndPort.substr(0, colonIndex)); +                try { +                    port = boost::lexical_cast<int>(hostAndPort.substr(colonIndex + 1)); +                } +                catch (const boost::bad_lexical_cast&) { +                    return URL(); +                } +            } +            else { +                host = unescape(hostAndPort); +            }          }          if (port) { @@ -102,7 +124,12 @@ std::string URL::toString() const {          }          result += "@";      } -    result += host; +    if (host.find(':') != std::string::npos) { +        result += "[" + host + "]"; +    } +    else { +        result += host; +    }      if (port) {          result += ":";          result += boost::lexical_cast<std::string>(*port); diff --git a/Swiften/Base/UnitTest/URLTest.cpp b/Swiften/Base/UnitTest/URLTest.cpp index 2d2ceba..c38398a 100644 --- a/Swiften/Base/UnitTest/URLTest.cpp +++ b/Swiften/Base/UnitTest/URLTest.cpp @@ -24,8 +24,13 @@ class URLTest : public CppUnit::TestFixture {          CPPUNIT_TEST(testFromString_WithUserInfo);          CPPUNIT_TEST(testFromString_NonASCIIHost);          CPPUNIT_TEST(testFromString_NonASCIIPath); +        CPPUNIT_TEST(testFromString_IPv4Address); +        CPPUNIT_TEST(testFromString_IPv4AddressWithPort); +        CPPUNIT_TEST(testFromString_IPv6Address); +        CPPUNIT_TEST(testFromString_IPv6AddressWithPort);          CPPUNIT_TEST(testToString);          CPPUNIT_TEST(testToString_WithPort); +        CPPUNIT_TEST(test_FromString_ToString_IPv6RFC2732);          CPPUNIT_TEST_SUITE_END();      public: @@ -103,6 +108,124 @@ class URLTest : public CppUnit::TestFixture {              CPPUNIT_ASSERT_EQUAL(std::string("/baz/tron\xc3\xa7on/bam"), url.getPath());          } +        void testFromString_IPv4Address() { +            URL url = URL::fromString("http://127.0.0.1/foobar"); + +            CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); +            CPPUNIT_ASSERT_EQUAL(std::string("127.0.0.1"), url.getHost()); +            CPPUNIT_ASSERT_EQUAL(std::string("/foobar"), url.getPath()); +        } + +        void testFromString_IPv4AddressWithPort() { +            URL url = URL::fromString("http://127.0.0.1:12345/foobar"); + +            CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); +            CPPUNIT_ASSERT_EQUAL(std::string("127.0.0.1"), url.getHost()); +            CPPUNIT_ASSERT_EQUAL(12345, url.getPort().get_value_or(0)); +            CPPUNIT_ASSERT_EQUAL(std::string("/foobar"), url.getPath()); +        } + +        void testFromString_IPv6Address() { +            URL url = URL::fromString("http://[fdf8:f53b:82e4::53]/foobar"); + +            CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); +            CPPUNIT_ASSERT_EQUAL(std::string("fdf8:f53b:82e4::53"), url.getHost()); +        } + +        void testFromString_IPv6AddressWithPort() { +            URL url = URL::fromString("http://[fdf8:f53b:82e4::53]:12435/foobar"); + +            CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); +            CPPUNIT_ASSERT_EQUAL(std::string("fdf8:f53b:82e4::53"), url.getHost()); +            CPPUNIT_ASSERT_EQUAL(12435, url.getPort().get_value_or(0)); +        } + +        void test_FromString_ToString_IPv6RFC2732() { +            { +                const char* testVector = "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html"; +                URL url = URL::fromString(testVector); + +                CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); +                CPPUNIT_ASSERT_EQUAL(std::string("FEDC:BA98:7654:3210:FEDC:BA98:7654:3210"), url.getHost()); +                CPPUNIT_ASSERT_EQUAL(80, url.getPort().get_value_or(2)); +                CPPUNIT_ASSERT_EQUAL(std::string("/index.html"), url.getPath()); + +                CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); +            } + +            { +                const char* testVector = "http://[1080:0:0:0:8:800:200C:417A]/index.html"; +                URL url = URL::fromString(testVector); + +                CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); +                CPPUNIT_ASSERT_EQUAL(std::string("1080:0:0:0:8:800:200C:417A"), url.getHost()); +                CPPUNIT_ASSERT_EQUAL(2, url.getPort().get_value_or(2)); +                CPPUNIT_ASSERT_EQUAL(std::string("/index.html"), url.getPath()); + +                CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); +            } + +            { +                const char* testVector = "http://[3ffe:2a00:100:7031::1]"; +                URL url = URL::fromString(testVector); + +                CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); +                CPPUNIT_ASSERT_EQUAL(std::string("3ffe:2a00:100:7031::1"), url.getHost()); +                CPPUNIT_ASSERT_EQUAL(2, url.getPort().get_value_or(2)); +                CPPUNIT_ASSERT_EQUAL(std::string(""), url.getPath()); + +                CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); +            } + +            { +                const char* testVector = "http://[1080::8:800:200C:417A]/foo"; +                URL url = URL::fromString(testVector); + +                CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); +                CPPUNIT_ASSERT_EQUAL(std::string("1080::8:800:200C:417A"), url.getHost()); +                CPPUNIT_ASSERT_EQUAL(2, url.getPort().get_value_or(2)); +                CPPUNIT_ASSERT_EQUAL(std::string("/foo"), url.getPath()); + +                CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); +            } + +            { +                const char* testVector = "http://[::192.9.5.5]/ipng"; +                URL url = URL::fromString(testVector); + +                CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); +                CPPUNIT_ASSERT_EQUAL(std::string("::192.9.5.5"), url.getHost()); +                CPPUNIT_ASSERT_EQUAL(2, url.getPort().get_value_or(2)); +                CPPUNIT_ASSERT_EQUAL(std::string("/ipng"), url.getPath()); + +                CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); +            } + +            { +                const char* testVector = "http://[::FFFF:129.144.52.38]:80/index.html"; +                URL url = URL::fromString(testVector); + +                CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); +                CPPUNIT_ASSERT_EQUAL(std::string("::FFFF:129.144.52.38"), url.getHost()); +                CPPUNIT_ASSERT_EQUAL(80, url.getPort().get_value_or(2)); +                CPPUNIT_ASSERT_EQUAL(std::string("/index.html"), url.getPath()); + +                CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); +            } + +            { +                const char* testVector = "http://[2010:836B:4179::836B:4179]"; +                URL url = URL::fromString(testVector); + +                CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); +                CPPUNIT_ASSERT_EQUAL(std::string("2010:836B:4179::836B:4179"), url.getHost()); +                CPPUNIT_ASSERT_EQUAL(2, url.getPort().get_value_or(2)); +                CPPUNIT_ASSERT_EQUAL(std::string(), url.getPath()); + +                CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); +            } +        } +          void testToString() {              CPPUNIT_ASSERT_EQUAL(std::string("http://foo.bar/baz/bam"), URL("http", "foo.bar", "/baz/bam").toString());          } | 
 Swift
 Swift