#include "utility.hh"
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/classification.hpp>
+#include <boost/algorithm/string/replace.hpp>
#include <iostream>
#include "base32.hh"
return ret;
}
+void RecordTextWriter::xfrSVCBValueList(const vector<string> &val) {
+ bool shouldQuote{false};
+ vector<string> escaped;
+ escaped.reserve(val.size());
+ for (auto const &v : val) {
+ if (v.find_first_of(' ') != string::npos) {
+ shouldQuote = true;
+ }
+ string tmp = txtEscape(v);
+ boost::replace_all(tmp, ",", "\\,");
+ escaped.push_back(tmp);
+ }
+ if (shouldQuote) {
+ d_string.append(1, '"');
+ }
+ d_string.append(boost::join(escaped, ","));
+ if (shouldQuote) {
+ d_string.append(1, '"');
+ }
+}
+
void RecordTextWriter::xfrSvcParamKeyVals(const set<SvcParam>& val) {
for (auto const ¶m : val) {
if (!d_string.empty())
d_string.append(ComboAddress::caContainerToString(param.getIPHints(), false));
break;
case SvcParam::alpn:
- // This is safe, as this value needs no quotes
- d_string.append(boost::join(param.getALPN(), ","));
+ xfrSVCBValueList(param.getALPN());
break;
case SvcParam::mandatory:
{
void xfrSvcParamKeyVals(const set<SvcParam>& val);
bool eof() { return true; };
+ void xfrSVCBValueList(const vector<string> &val);
+
const string getRemaining() const {
return "";
}
(CASE_S(QType::SVCB, "16 foo.powerdns.org. mandatory=alpn alpn=h2,h3 ipv4hint=192.0.2.1", "\0\x10\3foo\x08powerdns\x03org\x00\x00\x00\x00\x02\x00\x01\x00\x01\x00\x06\x02h2\x02h3\x00\x04\x00\x04\xc0\x00\x02\x01"))
(CASE_L(QType::SVCB, "16 foo.powerdns.org. alpn=h2,h3 mandatory=alpn ipv4hint=192.0.2.1", "16 foo.powerdns.org. mandatory=alpn alpn=h2,h3 ipv4hint=192.0.2.1", "\0\x10\3foo\x08powerdns\x03org\x00\x00\x00\x00\x02\x00\x01\x00\x01\x00\x06\x02h2\x02h3\x00\x04\x00\x04\xc0\x00\x02\x01"))
+ // IPv4hint is quoted
+ (CASE_L(QType::SVCB, "16 foo.powerdns.org. alpn=h2,h3 mandatory=alpn ipv4hint=\"192.0.2.1\"", "16 foo.powerdns.org. mandatory=alpn alpn=h2,h3 ipv4hint=192.0.2.1", "\0\x10\3foo\x08powerdns\x03org\x00\x00\x00\x00\x02\x00\x01\x00\x01\x00\x06\x02h2\x02h3\x00\x04\x00\x04\xc0\x00\x02\x01"))
+ // Escaped ALPN value
+ (CASE_S(QType::SVCB, "1 foo.powerdns.org. alpn=h3\\,cool,h2", "\0\x01\3foo\x08powerdns\x03org\x00\x00\x01\x00\x0b\x07h3,cool\x02h2"))
+ // Escaped _and_ spaced ALPN value
+ (CASE_S(QType::SVCB, "1 foo.powerdns.org. alpn=\"h3\\,co ol,h2\"", "\0\x01\3foo\x08powerdns\x03org\x00\x00\x01\x00\x0c\x08h3,co ol\x02h2"))
+
(CASE_S(QType::SPF, "\"v=spf1 a:mail.rec.test ~all\"", "\x1bv=spf1 a:mail.rec.test ~all"))
(CASE_S(QType::EUI48, "00-11-22-33-44-55", "\x00\x11\x22\x33\x44\x55"))
(CASE_S(QType::EUI64, "00-11-22-33-44-55-66-77", "\x00\x11\x22\x33\x44\x55\x66\x77"))