Browse Source

[trac1112] Move <character-string> related functions to character_string.h/cc files
Move some duplicated code of toWire() to toWireHelper() function

Ocean Wang 13 years ago
parent
commit
b557ab47f3

+ 1 - 0
src/lib/dns/Makefile.am

@@ -94,6 +94,7 @@ libdns___la_SOURCES += tsig.h tsig.cc
 libdns___la_SOURCES += tsigerror.h tsigerror.cc
 libdns___la_SOURCES += tsigkey.h tsigkey.cc
 libdns___la_SOURCES += tsigrecord.h tsigrecord.cc
+libdns___la_SOURCES += character_string.h character_string.cc
 libdns___la_SOURCES += rdata/generic/detail/nsec_bitmap.h
 libdns___la_SOURCES += rdata/generic/detail/nsec_bitmap.cc
 

+ 94 - 0
src/lib/dns/character_string.cc

@@ -0,0 +1,94 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include "character_string.h"
+#include "rdata.h"
+
+using namespace std;
+using namespace isc::dns::rdata;
+
+namespace isc {
+namespace dns {
+
+std::string
+characterstr::getNextCharacterString(const std::string& input_str,
+                              std::string::const_iterator& input_iterator)
+{
+    string result;
+
+    // If the input string only contains white-spaces, it is an invalid
+    // <character-string>
+    if (input_iterator >= input_str.end()) {
+        isc_throw(InvalidRdataText, "Invalid text format, \
+                  <character-string> field is missing.");
+    }
+
+    // Whether the <character-string> is separated with double quotes (")
+    bool quotes_separated = (*input_iterator == '"');
+
+    if (quotes_separated) {
+        ++input_iterator;
+    }
+
+    while(input_iterator < input_str.end()){
+        if (quotes_separated) {
+            // If the <character-string> is seperated with quotes symbol and
+            // another quotes symbol is encountered, it is the end of the
+            // <character-string>
+            if (*input_iterator == '"') {
+                // Inside a " delimited string any character can occur, except
+                // for a " itself, which must be quoted using \ (back slash).
+                if (*(input_iterator - 1) == '\\') {
+                    // pop the '\' character
+                    result.resize(result.size() - 1);
+                } else {
+                    ++input_iterator;
+                    // Reach the end of character string
+                    break;
+                }
+            }
+        } else if (*input_iterator == ' ') {
+            // If the <character-string> is not seperated with quotes symbol,
+            // it is seperated with <space> char
+            break;
+        }
+
+        result.push_back(*input_iterator);
+
+        ++input_iterator;
+    }
+
+    if (result.size() > MAX_CHARSTRING_LEN) {
+        isc_throw(CharStringTooLong, "<character-string> is too long");
+    }
+
+    return (result);
+}
+
+std::string
+characterstr::getNextCharacterString(util::InputBuffer& buffer, size_t len) {
+    uint8_t str_len = buffer.readUint8();
+
+    size_t pos = buffer.getPosition();
+    if (len - pos < str_len) {
+        isc_throw(InvalidRdataLength, "Invalid string length");
+    }
+
+    uint8_t buf[MAX_CHARSTRING_LEN];
+    buffer.readData(buf, str_len);
+    return (string(buf, buf + str_len));
+}
+
+} // end of namespace dns
+} // end of namespace isc

+ 46 - 0
src/lib/dns/character_string.h

@@ -0,0 +1,46 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __CHARACTER_STRING_H
+#define __CHARACTER_STRING_H
+
+#include <string>
+#include <exceptions/exceptions.h>
+#include <util/buffer.h>
+
+namespace isc {
+namespace dns {
+namespace characterstr {
+    /// Get a <character-string> from a string
+    ///
+    /// \param input_str The input string
+    /// \param input_iterator The iterator from which to start extracting,
+    ///        the iterator will be updated to new position after the function
+    ///        is returned
+    /// \return A std::string that contains the extracted <character-string>
+    std::string getNextCharacterString(const std::string& input_str,
+                                       std::string::const_iterator& input_iterator);
+
+    /// Get a <character-string> from a input buffer
+    ///
+    /// \param buffer The input buffer
+    /// \param len The input buffer total length
+    /// \return A std::string that contains the extracted <character-string>
+    std::string getNextCharacterString(util::InputBuffer& buffer, size_t len);
+
+} // namespace characterstr
+} // namespace dns
+} // namespace isc
+
+#endif // __CHARACTER_STRING_H

+ 6 - 71
src/lib/dns/rdata/generic/hinfo_13.cc

@@ -24,10 +24,14 @@
 #include <dns/messagerenderer.h>
 #include <dns/rdata.h>
 #include <dns/rdataclass.h>
+#include <dns/character_string.h>
+#include <util/strutil.h>
 
 using namespace std;
 using namespace boost;
 using namespace isc::util;
+using namespace isc::dns;
+using namespace isc::dns::characterstr;
 
 // BEGIN_ISC_NAMESPACE
 // BEGIN_RDATA_NAMESPACE
@@ -65,20 +69,12 @@ HINFO::toText() const {
 
 void
 HINFO::toWire(OutputBuffer& buffer) const {
-    buffer.writeUint8(cpu_.size());
-    buffer.writeData(cpu_.c_str(), cpu_.size());
-
-    buffer.writeUint8(os_.size());
-    buffer.writeData(os_.c_str(), os_.size());
+    toWireHelper(buffer);
 }
 
 void
 HINFO::toWire(AbstractMessageRenderer& renderer) const {
-    renderer.writeUint8(cpu_.size());
-    renderer.writeData(cpu_.c_str(), cpu_.size());
-
-    renderer.writeUint8(os_.size());
-    renderer.writeData(os_.c_str(), os_.size());
+    toWireHelper(renderer);
 }
 
 int
@@ -129,66 +125,5 @@ HINFO::skipLeftSpaces(const std::string& input_str,
     }
 }
 
-std::string
-HINFO::getNextCharacterString(const std::string& input_str,
-                              std::string::const_iterator& input_iterator)
-{
-    string result;
-
-    // If the input string only contains white-spaces, it is an invalid
-    // <character-string>
-    if (input_iterator >= input_str.end()) {
-        isc_throw(InvalidRdataText, "Invalid HINFO text format, \
-                  <character-string> field is missing.");
-    }
-
-    // Whether the <character-string> is separated with double quotes (")
-    bool quotes_separated = (*input_iterator == '"');
-
-    if (quotes_separated) {
-        ++input_iterator;
-    }
-
-    while(input_iterator < input_str.end()){
-        if (quotes_separated) {
-            // If the <character-string> is seperated with quotes symbol and
-            // another quotes symbol is encountered, it is the end of the
-            // <character-string>
-            if (*input_iterator == '"') {
-                ++input_iterator;
-                break;
-            }
-        } else if (*input_iterator == ' ') {
-            // If the <character-string> is not seperated with quotes symbol,
-            // it is seperated with <space> char
-            break;
-        }
-
-        result.push_back(*input_iterator);
-
-        ++input_iterator;
-    }
-
-    if (result.size() > MAX_CHARSTRING_LEN) {
-        isc_throw(CharStringTooLong, "HINFO <character-string> is too long");
-    }
-
-    return (result);
-}
-
-std::string
-HINFO::getNextCharacterString(InputBuffer& buffer, size_t len) {
-    uint8_t str_len = buffer.readUint8();
-
-    size_t pos = buffer.getPosition();
-    if (len - pos < str_len) {
-        isc_throw(InvalidRdataLength, "Invalid HINFO string length");
-    }
-
-    uint8_t buf[MAX_CHARSTRING_LEN];
-    buffer.readData(buf, str_len);
-    return (string(buf, buf + str_len));
-}
-
 // END_RDATA_NAMESPACE
 // END_ISC_NAMESPACE

+ 9 - 14
src/lib/dns/rdata/generic/hinfo_13.h

@@ -51,22 +51,17 @@ private:
     void skipLeftSpaces(const std::string& input_str,
                         std::string::const_iterator& input_iterator);
 
-    /// Get a <character-string> from a string
+    /// Helper template function for toWire()
     ///
-    /// \param input_str The input string
-    /// \param input_iterator The iterator from which to start extracting,
-    ///        the iterator will be updated to new position after the function
-    ///        is returned
-    /// \return A std::string that contains the extracted <character-string>
-    std::string getNextCharacterString(const std::string& input_str,
-                                       std::string::const_iterator& input_iterator);
+    /// \param outputer Where to write data in
+    template <typename T>
+    void toWireHelper(T& outputer) const {
+        outputer.writeUint8(cpu_.size());
+        outputer.writeData(cpu_.c_str(), cpu_.size());
 
-    /// Get a <character-string> from a input buffer
-    ///
-    /// \param buffer The input buffer
-    /// \param len The input buffer total length
-    /// \return A std::string that contains the extracted <character-string>
-    std::string getNextCharacterString(util::InputBuffer& buffer, size_t len);
+        outputer.writeUint8(os_.size());
+        outputer.writeData(os_.c_str(), os_.size());
+    }
 
     std::string cpu_;
     std::string os_;

+ 5 - 99
src/lib/dns/rdata/generic/naptr_35.cc

@@ -20,6 +20,7 @@
 
 #include <exceptions/exceptions.h>
 
+#include <dns/character_string.h>
 #include <dns/name.h>
 #include <dns/messagerenderer.h>
 #include <dns/rdata.h>
@@ -28,6 +29,8 @@
 using namespace std;
 using namespace boost;
 using namespace isc::util;
+using namespace isc::dns;
+using namespace isc::dns::characterstr;
 
 // BEGIN_ISC_NAMESPACE
 // BEGIN_RDATA_NAMESPACE
@@ -56,79 +59,6 @@ skipLeftSpaces(const std::string& input_str,
     }
 }
 
-/// Get a <character-string> from a string
-///
-/// \param input_str The input string
-/// \param input_iterator The iterator from which to start extracting,
-///        the iterator will be updated to new position after the function
-///        is returned
-/// \return A std::string that contains the extracted <character-string>
-std::string
-getNextCharacterString(const std::string& input_str,
-                       std::string::const_iterator& input_iterator)
-{
-    string result;
-
-    // If the input string only contains white-spaces, it is an invalid
-    // <character-string>
-    if (input_iterator >= input_str.end()) {
-        isc_throw(InvalidRdataText, "Invalid NAPTR text format, \
-                  <character-string> field is missing.");
-    }
-
-    // Whether the <character-string> is separated with double quotes (")
-    bool quotes_separated = (*input_iterator == '"');
-
-    if (quotes_separated) {
-        ++input_iterator;
-    }
-
-    while(input_iterator < input_str.end()){
-        if (quotes_separated) {
-            // If the <character-string> is seperated with quotes symbol and
-            // another quotes symbol is encountered, it is the end of the
-            // <character-string>
-            if (*input_iterator == '"') {
-                ++input_iterator;
-                break;
-            }
-        } else if (*input_iterator == ' ') {
-            // If the <character-string> is not seperated with quotes symbol,
-            // it is seperated with <space> char
-            break;
-        }
-
-        result.push_back(*input_iterator);
-
-        ++input_iterator;
-    }
-
-    if (result.size() > MAX_CHARSTRING_LEN) {
-        isc_throw(CharStringTooLong, "NAPTR <character-string> is too long");
-    }
-
-    return (result);
-}
-
-/// Get a <character-string> from a input buffer
-///
-/// \param buffer The input buffer
-/// \param len The input buffer total length
-/// \return A std::string that contains the extracted <character-string>
-std::string
-getNextCharacterString(InputBuffer& buffer, size_t len) {
-    uint8_t str_len = buffer.readUint8();
-
-    size_t pos = buffer.getPosition();
-    if (len - pos < str_len) {
-        isc_throw(InvalidRdataLength, "Invalid NAPTR string length");
-    }
-
-    uint8_t buf[MAX_CHARSTRING_LEN];
-    buffer.readData(buf, str_len);
-    return (string(buf, buf + str_len));
-}
-
 } // Anonymous namespace
 
 NAPTR::NAPTR(InputBuffer& buffer, size_t len):
@@ -194,36 +124,12 @@ NAPTR::NAPTR(const NAPTR& naptr):
 
 void
 NAPTR::toWire(OutputBuffer& buffer) const {
-    buffer.writeUint16(order_);
-    buffer.writeUint16(preference_);
-
-    buffer.writeUint8(flags_.size());
-    buffer.writeData(flags_.c_str(), flags_.size());
-
-    buffer.writeUint8(services_.size());
-    buffer.writeData(services_.c_str(), services_.size());
-
-    buffer.writeUint8(regexp_.size());
-    buffer.writeData(regexp_.c_str(), regexp_.size());
-
-    replacement_.toWire(buffer);
+    toWireHelper(buffer);
 }
 
 void
 NAPTR::toWire(AbstractMessageRenderer& renderer) const {
-    renderer.writeUint16(order_);
-    renderer.writeUint16(preference_);
-
-    renderer.writeUint8(flags_.size());
-    renderer.writeData(flags_.c_str(), flags_.size());
-
-    renderer.writeUint8(services_.size());
-    renderer.writeData(services_.c_str(), services_.size());
-
-    renderer.writeUint8(regexp_.size());
-    renderer.writeData(regexp_.c_str(), regexp_.size());
-
-    replacement_.toWire(renderer);
+    toWireHelper(renderer);
 }
 
 string

+ 20 - 0
src/lib/dns/rdata/generic/naptr_35.h

@@ -46,6 +46,26 @@ public:
     const std::string& getRegexp() const;
     const Name& getReplacement() const;
 private:
+    /// Helper template function for toWire()
+    ///
+    /// \param outputer Where to write data in
+    template <typename T>
+    void toWireHelper(T& outputer) const {
+        outputer.writeUint16(order_);
+        outputer.writeUint16(preference_);
+
+        outputer.writeUint8(flags_.size());
+        outputer.writeData(flags_.c_str(), flags_.size());
+
+        outputer.writeUint8(services_.size());
+        outputer.writeData(services_.c_str(), services_.size());
+
+        outputer.writeUint8(regexp_.size());
+        outputer.writeData(regexp_.c_str(), regexp_.size());
+
+        replacement_.toWire(outputer);
+    }
+
     uint16_t order_;
     uint16_t preference_;
     std::string flags_;

+ 5 - 0
src/lib/dns/tests/rdata_hinfo_unittest.cc

@@ -39,6 +39,7 @@ class Rdata_HINFO_Test : public RdataTest {
 static uint8_t hinfo_rdata[] = {0x07,0x50,0x65,0x6e,0x74,0x69,0x75,0x6d,0x05,
     0x4c,0x69,0x6e,0x75,0x78};
 static const char *hinfo_str = "\"Pentium\" \"Linux\"";
+static const char *hinfo_str1 = "\"Pen\\\"tium\" \"Linux\"";
 
 static const char *hinfo_str_small1 = "\"Lentium\" \"Linux\"";
 static const char *hinfo_str_small2 = "\"Pentium\" \"Kinux\"";
@@ -49,6 +50,10 @@ TEST_F(Rdata_HINFO_Test, createFromText) {
     HINFO hinfo(hinfo_str);
     EXPECT_EQ(string("Pentium"), hinfo.getCPU());
     EXPECT_EQ(string("Linux"), hinfo.getOS());
+
+    // Test the text with double quotes in the middle of string
+    HINFO hinfo1(hinfo_str1);
+    EXPECT_EQ(string("Pen\"tium"), hinfo1.getCPU());
 }
 
 TEST_F(Rdata_HINFO_Test, badText) {