summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swiften/IDN/LibIDNConverter.cpp7
-rw-r--r--Swiften/IDN/SConscript1
-rw-r--r--Swiften/IDN/UnitTest/IDNConverterTest.cpp114
3 files changed, 70 insertions, 52 deletions
diff --git a/Swiften/IDN/LibIDNConverter.cpp b/Swiften/IDN/LibIDNConverter.cpp
index 0c01352..2325015 100644
--- a/Swiften/IDN/LibIDNConverter.cpp
+++ b/Swiften/IDN/LibIDNConverter.cpp
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2012-2016 Isode Limited. 2 * Copyright (c) 2012-2018 Isode Limited.
3 * All rights reserved. 3 * All rights reserved.
4 * See the COPYING file for more information. 4 * See the COPYING file for more information.
5 */ 5 */
@@ -24,7 +24,7 @@ extern "C" {
24using namespace Swift; 24using namespace Swift;
25 25
26namespace { 26namespace {
27 static const int MAX_STRINGPREP_SIZE = 1024; 27 static const size_t MAX_STRINGPREP_SIZE = 1024;
28 28
29 const Stringprep_profile* getLibIDNProfile(IDNConverter::StringPrepProfile profile) { 29 const Stringprep_profile* getLibIDNProfile(IDNConverter::StringPrepProfile profile) {
30 switch(profile) { 30 switch(profile) {
@@ -44,7 +44,8 @@ namespace {
44 return ContainerType(); 44 return ContainerType();
45 } 45 }
46 46
47 input.resize(MAX_STRINGPREP_SIZE); 47 // Ensure we have enough space for stringprepping, and that input is always NUL terminated
48 input.resize(std::max(MAX_STRINGPREP_SIZE, input.size() + 1));
48 if (stringprep(&input[0], MAX_STRINGPREP_SIZE, static_cast<Stringprep_profile_flags>(0), getLibIDNProfile(profile)) == 0) { 49 if (stringprep(&input[0], MAX_STRINGPREP_SIZE, static_cast<Stringprep_profile_flags>(0), getLibIDNProfile(profile)) == 0) {
49 return input; 50 return input;
50 } 51 }
diff --git a/Swiften/IDN/SConscript b/Swiften/IDN/SConscript
index 28596f7..0afad0e 100644
--- a/Swiften/IDN/SConscript
+++ b/Swiften/IDN/SConscript
@@ -23,6 +23,7 @@ swiften_env.Append(SWIFTEN_OBJECTS = [objects])
23if env["TEST"] : 23if env["TEST"] :
24 test_env = myenv.Clone() 24 test_env = myenv.Clone()
25 test_env.UseFlags(swiften_env["CPPUNIT_FLAGS"]) 25 test_env.UseFlags(swiften_env["CPPUNIT_FLAGS"])
26 test_env.UseFlags(myenv.get("GOOGLETEST_FLAGS", ""))
26 env.Append(UNITTEST_OBJECTS = test_env.SwiftenObject([ 27 env.Append(UNITTEST_OBJECTS = test_env.SwiftenObject([
27 File("UnitTest/IDNConverterTest.cpp"), 28 File("UnitTest/IDNConverterTest.cpp"),
28 File("UnitTest/UTF8ValidatorTest.cpp") 29 File("UnitTest/UTF8ValidatorTest.cpp")
diff --git a/Swiften/IDN/UnitTest/IDNConverterTest.cpp b/Swiften/IDN/UnitTest/IDNConverterTest.cpp
index 508a28c..c5f94d0 100644
--- a/Swiften/IDN/UnitTest/IDNConverterTest.cpp
+++ b/Swiften/IDN/UnitTest/IDNConverterTest.cpp
@@ -1,64 +1,80 @@
1/* 1/*
2 * Copyright (c) 2010-2016 Isode Limited. 2 * Copyright (c) 2010-2018 Isode Limited.
3 * All rights reserved. 3 * All rights reserved.
4 * See the COPYING file for more information. 4 * See the COPYING file for more information.
5 */ 5 */
6 6
7#include <memory> 7#include <memory>
8 8
9#include <cppunit/extensions/HelperMacros.h> 9#include <gtest/gtest.h>
10#include <cppunit/extensions/TestFactoryRegistry.h>
11 10
12#include <Swiften/IDN/IDNConverter.h> 11#include <Swiften/IDN/IDNConverter.h>
13#include <Swiften/IDN/PlatformIDNConverter.h> 12#include <Swiften/IDN/PlatformIDNConverter.h>
14 13
15using namespace Swift; 14using namespace Swift;
16 15
17class IDNConverterTest : public CppUnit::TestFixture { 16class IDNConverterTest : public ::testing::Test {
18 CPPUNIT_TEST_SUITE(IDNConverterTest); 17
19 CPPUNIT_TEST(testStringPrep); 18protected:
20 CPPUNIT_TEST(testStringPrep_Empty); 19 virtual void SetUp() {
21 CPPUNIT_TEST(testGetEncoded); 20 testling_ = std::shared_ptr<IDNConverter>(PlatformIDNConverter::create());
22 CPPUNIT_TEST(testGetEncoded_International); 21 }
23 CPPUNIT_TEST(testGetEncoded_Invalid); 22
24 CPPUNIT_TEST_SUITE_END(); 23 std::shared_ptr<IDNConverter> testling_;
25
26 public:
27 void setUp() {
28 testling = std::shared_ptr<IDNConverter>(PlatformIDNConverter::create());
29 }
30
31 void testStringPrep() {
32 std::string result = testling->getStringPrepared("tron\xc3\x87on", IDNConverter::NamePrep);
33
34 CPPUNIT_ASSERT_EQUAL(std::string("tron\xc3\xa7on"), result);
35 }
36
37 void testStringPrep_Empty() {
38 CPPUNIT_ASSERT_EQUAL(std::string(""), testling->getStringPrepared("", IDNConverter::NamePrep));
39 CPPUNIT_ASSERT_EQUAL(std::string(""), testling->getStringPrepared("", IDNConverter::XMPPNodePrep));
40 CPPUNIT_ASSERT_EQUAL(std::string(""), testling->getStringPrepared("", IDNConverter::XMPPResourcePrep));
41 }
42
43 void testGetEncoded() {
44 boost::optional<std::string> result = testling->getIDNAEncoded("www.swift.im");
45 CPPUNIT_ASSERT(!!result);
46 CPPUNIT_ASSERT_EQUAL(std::string("www.swift.im"), *result);
47 }
48
49 void testGetEncoded_International() {
50 boost::optional<std::string> result = testling->getIDNAEncoded("www.tron\xc3\x87on.com");
51 CPPUNIT_ASSERT(!!result);
52 CPPUNIT_ASSERT_EQUAL(std::string("www.xn--tronon-zua.com"), *result);
53 }
54
55 void testGetEncoded_Invalid() {
56 boost::optional<std::string> result = testling->getIDNAEncoded("www.foo,bar.com");
57 CPPUNIT_ASSERT(!result);
58 }
59
60 private:
61 std::shared_ptr<IDNConverter> testling;
62}; 24};
63 25
64CPPUNIT_TEST_SUITE_REGISTRATION(IDNConverterTest); 26TEST_F(IDNConverterTest, testStringPrep) {
27 std::string result = testling_->getStringPrepared("tron\xc3\x87on", IDNConverter::NamePrep);
28
29 ASSERT_EQ(std::string("tron\xc3\xa7on"), result);
30}
31
32TEST_F(IDNConverterTest, testStringPrep_Empty) {
33 ASSERT_EQ(std::string(""), testling_->getStringPrepared("", IDNConverter::NamePrep));
34 ASSERT_EQ(std::string(""), testling_->getStringPrepared("", IDNConverter::XMPPNodePrep));
35 ASSERT_EQ(std::string(""), testling_->getStringPrepared("", IDNConverter::XMPPResourcePrep));
36}
37
38TEST_F(IDNConverterTest, testStringPrep_MaximumOutputSize) {
39 const std::string input(1023, 'x');
40 ASSERT_EQ(input, testling_->getStringPrepared(input, IDNConverter::NamePrep));
41 ASSERT_EQ(input, testling_->getStringPrepared(input, IDNConverter::XMPPNodePrep));
42 ASSERT_EQ(input, testling_->getStringPrepared(input, IDNConverter::XMPPResourcePrep));
43}
44
45TEST_F(IDNConverterTest, testStringPrep_TooLong) {
46 const std::string input(1024, 'x');
47 ASSERT_THROW(testling_->getStringPrepared(input, IDNConverter::NamePrep), std::exception);
48 ASSERT_THROW(testling_->getStringPrepared(input, IDNConverter::XMPPNodePrep), std::exception);
49 ASSERT_THROW(testling_->getStringPrepared(input, IDNConverter::XMPPResourcePrep), std::exception);
50}
51
52TEST_F(IDNConverterTest, testStringPrep_ShrinkingBelow1023) {
53 std::string input;
54 std::string expected;
55 // The four byte \u03b1\u0313 UTF-8 string will shrink to the three byte \u1f00
56 for (auto i = 0; i < 300; ++i) {
57 input +="\xce\xb1\xcc\x93"; // UTF-8 repesentation of U+03B1 U+0313
58 expected += "\xe1\xbc\x80"; // UTF-8 representation of U+1F00
59 }
60 ASSERT_EQ(expected, testling_->getStringPrepared(input, IDNConverter::NamePrep));
61 ASSERT_EQ(expected, testling_->getStringPrepared(input, IDNConverter::XMPPNodePrep));
62 ASSERT_EQ(expected, testling_->getStringPrepared(input, IDNConverter::XMPPResourcePrep));
63}
64
65TEST_F(IDNConverterTest, testGetEncoded) {
66 boost::optional<std::string> result = testling_->getIDNAEncoded("www.swift.im");
67 ASSERT_TRUE(!!result);
68 ASSERT_EQ(std::string("www.swift.im"), *result);
69}
70
71TEST_F(IDNConverterTest, testGetEncoded_International) {
72 boost::optional<std::string> result = testling_->getIDNAEncoded("www.tron\xc3\x87on.com");
73 ASSERT_TRUE(result);
74 ASSERT_EQ(std::string("www.xn--tronon-zua.com"), *result);
75}
76
77TEST_F(IDNConverterTest, testGetEncoded_Invalid) {
78 boost::optional<std::string> result = testling_->getIDNAEncoded("www.foo,bar.com");
79 ASSERT_FALSE(result);
80}