Browse Source

[2535] Add charStringToString() to convert a CharString to a DNS textual representation

Mukund Sivaraman 12 years ago
parent
commit
77b42eabd7

+ 23 - 0
src/lib/dns/rdata/generic/detail/char_string.cc

@@ -91,6 +91,29 @@ strToCharString(const MasterToken::StringRegion& str_region,
     result[0] = result.size() - 1;
 }
 
+std::string
+charStringToString(const CharString& char_string) {
+    std::string s;
+    for (CharString::const_iterator it = char_string.begin() + 1;
+         it != char_string.end(); ++it) {
+        const uint8_t ch = *it;
+        if ((ch < 0x20) || (ch >= 0x7f)) {
+            // convert to escaped \xxx (decimal) format
+            s.push_back('\\');
+            s.push_back('0' + ((ch / 100) % 10));
+            s.push_back('0' + ((ch / 10) % 10));
+            s.push_back('0' + (ch % 10));
+            continue;
+        }
+        if ((ch == '"') || (ch == ';') || (ch == '\\')) {
+            s.push_back('\\');
+        }
+        s.push_back(ch);
+    }
+
+    return (s);
+}
+
 } // end of detail
 } // end of generic
 } // end of rdata

+ 15 - 0
src/lib/dns/rdata/generic/detail/char_string.h

@@ -17,6 +17,7 @@
 
 #include <dns/master_lexer.h>
 
+#include <string>
 #include <vector>
 #include <stdint.h>
 
@@ -51,6 +52,20 @@ typedef std::vector<uint8_t> CharString;
 void strToCharString(const MasterToken::StringRegion& str_region,
                      CharString& result);
 
+/// \brief Convert a CharString into a textual DNS character-string.
+///
+/// This method converts a binary 8-bit representation of a DNS
+/// character string into a textual string representation, escaping any
+/// special characters in the process. For example, characters like
+/// double-quotes, semi-colon and backspace are prefixed with backspace
+/// character, and characters not in the printable range of [0x20, 0x7e]
+/// (inclusive) are converted to the \xxx 3-digit decimal
+/// representation.
+///
+/// \param char_string The \c CharString to convert.
+/// \return A string representation of \c char_string.
+std::string charStringToString(const CharString& char_string);
+
 } // namespace detail
 } // namespace generic
 } // namespace rdata

+ 58 - 0
src/lib/dns/tests/rdata_char_string_unittest.cc

@@ -26,6 +26,7 @@ using namespace isc::dns;
 using namespace isc::dns::rdata;
 using isc::dns::rdata::generic::detail::CharString;
 using isc::dns::rdata::generic::detail::strToCharString;
+using isc::dns::rdata::generic::detail::charStringToString;
 using isc::util::unittests::matchWireData;
 
 namespace {
@@ -144,4 +145,61 @@ TEST_F(CharStringTest, badDDD) {
                  InvalidRdataText);
 }
 
+TEST_F(CharStringTest, charStringToString) {
+    const uint8_t double_quotes_buf[] = {
+        sizeof("Test\"Test\"") - 1,
+        'T', 'e', 's', 't', '"', 'T', 'e', 's', 't', '"'
+    };
+    const CharString double_quotes
+        (double_quotes_buf, double_quotes_buf + sizeof(double_quotes_buf));
+    EXPECT_EQ("Test\\\"Test\\\"",
+              charStringToString(double_quotes));
+
+    const uint8_t semicolon_buf[] = {
+        sizeof("Test;Test") - 1,
+        'T', 'e', 's', 't', ';', 'T', 'e', 's', 't'
+    };
+    const CharString semicolon
+        (semicolon_buf, semicolon_buf + sizeof(semicolon_buf));
+    EXPECT_EQ("Test\\;Test",
+              charStringToString(semicolon));
+
+    const uint8_t backslash_buf[] = {
+        sizeof("Test\\Test") - 1,
+        'T', 'e', 's', 't', '\\', 'T', 'e', 's', 't'
+    };
+    const CharString backslash
+        (backslash_buf, backslash_buf + sizeof(backslash_buf));
+    EXPECT_EQ("Test\\\\Test",
+              charStringToString(backslash));
+
+    const uint8_t before_x20_buf[] = {
+        sizeof("Test\x1fTest") - 1,
+        'T', 'e', 's', 't', 0x1f, 'T', 'e', 's', 't'
+    };
+    const CharString before_x20
+        (before_x20_buf, before_x20_buf + sizeof(before_x20_buf));
+    EXPECT_EQ("Test\\031Test",
+              charStringToString(before_x20));
+
+    const uint8_t from_x20_to_x7e_buf[] = {
+        sizeof("Test ~ Test") - 1,
+        'T', 'e', 's', 't', ' ', '~', ' ', 'T', 'e', 's', 't'
+    };
+    const CharString from_x20_to_x7e
+        (from_x20_to_x7e_buf,
+         from_x20_to_x7e_buf + sizeof(from_x20_to_x7e_buf));
+    EXPECT_EQ("Test ~ Test",
+              charStringToString(from_x20_to_x7e));
+
+    const uint8_t after_0x7e_buf[] = {
+        sizeof("Test\x7fTest") - 1,
+        'T', 'e', 's', 't', 0x7f, 'T', 'e', 's', 't'
+    };
+    const CharString after_0x7e
+        (after_0x7e_buf, after_0x7e_buf + sizeof(after_0x7e_buf));
+    EXPECT_EQ("Test\\127Test",
+              charStringToString(after_0x7e));
+}
+
 } // unnamed namespace