val.clear();
val.reserve(d_end - d_pos);
- while(d_pos != d_end) {
- if(!val.empty())
+ while (d_pos != d_end) {
+ if (!val.empty()) {
val.append(1, ' ');
+ }
skipSpaces();
- if(d_string[d_pos]!='"') { // special case 'plenus' - without quotes
- string::size_type pos = d_pos;
- while(pos != d_end && isalnum(d_string[pos]))
- pos++;
- if(pos == d_end) {
- val.append(1, '"');
- val.append(d_string.c_str() + d_pos, d_end - d_pos);
- val.append(1, '"');
- d_pos = d_end;
- break;
- }
- throw RecordTextException("Data field in DNS should start with quote (\") at position "+std::to_string(d_pos)+" of '"+d_string+"'");
- }
+ char delimiter{'"'};
+ bool quoted = d_string[d_pos] == '"';
+ // If the word is quoted, process up to the next quote; otherwise,
+ // process up to the next whitespace (but output it in quotes).
val.append(1, '"');
- while(++d_pos < d_end && d_string[d_pos]!='"') {
- if(d_string[d_pos]=='\\' && d_pos+1!=d_end) {
- val.append(1, d_string[d_pos++]);
+ if (quoted) {
+ ++d_pos;
+ }
+ else {
+ // RFC1035: ``a contiguous set of characters without interior spaces''
+ delimiter = ' ';
+ }
+ while (d_pos != d_end && d_string[d_pos] != delimiter) {
+ if (d_string[d_pos] == '\\' && d_pos + 1 != d_end) {
+ val.append(1, d_string[d_pos++]); // copy escape slash
char chr = d_string[d_pos];
if (chr >= '0' && chr <= '9') {
bool valid{false};
// part of the regular case.
}
val.append(1, d_string[d_pos]);
+ ++d_pos;
}
val.append(1,'"');
- if(d_pos == d_end)
- throw RecordTextException("Data field in DNS should end on a quote (\") in '"+d_string+"'");
- d_pos++;
- if(!multi)
+ if (quoted) {
+ // If we reached the end in a quoted section, the closing quote is missing.
+ if (d_pos == d_end) {
+ throw RecordTextException("Data field in DNS should end on a quote (\") in '"+d_string+"'");
+ }
+ // Skip closing quote
+ ++d_pos;
+ }
+ if (!multi) {
break;
+ }
}
}
// non-local name
(CASE_S(QType::PTR, "ptr.example.com.", "\x03ptr\x07""example\x03""com\x00"))
(CASE_S(QType::HINFO, "\"i686\" \"Linux\"", "\x04i686\x05Linux"))
- (BROKEN_CASE_L(QType::HINFO, "i686 \"Linux\"", "\"i686\" \"Linux\"", "\x04i686\x05Linux"))
+ (CASE_L(QType::HINFO, "i686 \"Linux\"", "\"i686\" \"Linux\"", "\x04i686\x05Linux"))
(CASE_L(QType::HINFO, "\"i686\" Linux", "\"i686\" \"Linux\"", "\x04i686\x05Linux"))
- (BROKEN_CASE_L(QType::HINFO, "i686 Linux", "\"i686\" \"Linux\"", "\x04i686\x05Linux"))
+ (CASE_L(QType::HINFO, "i686 Linux", "\"i686\" \"Linux\"", "\x04i686\x05Linux"))
// local name
(CASE_S(QType::MX, "10 mx.rec.test.", "\x00\x0a\x02mx\xc0\x11"))
// non-local name