Skip to content

Commit

Permalink
Update.
Browse files Browse the repository at this point in the history
  • Loading branch information
elgs committed Apr 6, 2016
1 parent a515d55 commit 1dceeb6
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 74 deletions.
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dns-zonefile",
"version": "0.1.17",
"version": "0.1.18",
"homepage": "https://github.com/elgs/dns-zonefile",
"authors": [
"elgs <[email protected]>"
Expand Down
163 changes: 91 additions & 72 deletions lib/zonefile.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,49 +221,83 @@
return arrText.join('').replace(/\(|\)/gim, ' ');
};

var normalizeRR = function (rr, rrType) {
var hasName = false;
var hasTtl = false;
if (rr.match(/^\s+/)) {
hasName = false;
} else {
hasName = true;
}
var rrArray = splitArgs(rr, null, true);
var typeIndex = rrArray.lastIndexOf(rrType);
if (typeIndex === 0 || rrArray[typeIndex - 1] !== 'IN') {
rrArray.splice(typeIndex, 0, 'IN');
}

// According to RFC 1035:
// <rr> contents take one of the following forms:
// [<TTL>] [<class>] <type> <RDATA> -- We assume this one
// [<class>] [<TTL>] <type> <RDATA>
if (hasName) {
if (!isNaN(rrArray[1])) {
hasTtl = true;
}
} else {
if (!isNaN(rrArray[0])) {
hasTtl = true;
}
}
return {
tokens: rrArray,
hasName: hasName,
hasTtl: hasTtl,
typeIndex: typeIndex
};
};

var parseRRs = function (text) {
var ret = {};
var rrs = text.split('\n');
for (var i in rrs) {
var rr = rrs[i] || '';
rr = rr.trim();
if (!rr) {
if (!rr.trim()) {
continue;
}
var rrArray = splitArgs(rr, null, true);
if (rrArray.indexOf('TXT') >= 0) {
ret.txt = ret.txt || [];
ret.txt.push(parseTXT(rrArray, ret.txt));
ret.txt.push(parseTXT(normalizeRR(rr, 'TXT'), ret.txt));
} else if (rrArray.indexOf('$ORIGIN') === 0) {
ret.$origin = rrArray[1];
} else if (rrArray.indexOf('$TTL') === 0) {
ret.$ttl = rrArray[1];
} else if (rrArray.indexOf('SOA') >= 0) {
ret.soa = parseSOA(rrArray, ret.soa);
ret.soa = parseSOA(rrArray);
} else if (rrArray.indexOf('NS') >= 0) {
ret.ns = ret.ns || [];
ret.ns.push(parseNS(rrArray, ret.ns));
ret.ns.push(parseNS(normalizeRR(rr, 'NS'), ret.ns));
} else if (rrArray.indexOf('A') >= 0) {
ret.a = ret.a || [];
ret.a.push(parseA(rrArray, ret.a));
ret.a.push(parseA(normalizeRR(rr, 'A'), ret.a));
} else if (rrArray.indexOf('AAAA') >= 0) {
ret.aaaa = ret.aaaa || [];
ret.aaaa.push(parseAAAA(rrArray, ret.aaaa));
ret.aaaa.push(parseAAAA(normalizeRR(rr, 'AAAA'), ret.aaaa));
} else if (rrArray.indexOf('CNAME') >= 0) {
ret.cname = ret.cname || [];
ret.cname.push(parseCNAME(rrArray, ret.cname));
ret.cname.push(parseCNAME(normalizeRR(rr, 'CNAME'), ret.cname));
} else if (rrArray.indexOf('MX') >= 0) {
ret.mx = ret.mx || [];
ret.mx.push(parseMX(rrArray, ret.mx));
ret.mx.push(parseMX(normalizeRR(rr, 'MX'), ret.mx));
} else if (rrArray.indexOf('PTR') >= 0) {
ret.ptr = ret.ptr || [];
ret.ptr.push(parsePTR(rrArray, ret.ptr, ret.$origin));
ret.ptr.push(parsePTR(normalizeRR(rr, 'PTR'), ret.ptr, ret.$origin));
} else if (rrArray.indexOf('SRV') >= 0) {
ret.srv = ret.srv || [];
ret.srv.push(parseSRV(rrArray, ret.srv));
ret.srv.push(parseSRV(normalizeRR(rr, 'SRV'), ret.srv));
} else if (rrArray.indexOf('SPF') >= 0) {
ret.spf = ret.spf || [];
ret.spf.push(parseSPF(rrArray, ret.spf));
ret.spf.push(parseSPF(normalizeRR(rr, 'SPF'), ret.spf));
}
}
return ret;
Expand All @@ -284,11 +318,9 @@
return soa;
};

var parseNS = function (rrTokens, recordsSoFar) {
if (rrTokens.lastIndexOf('IN') === 0) {
rrTokens.shift();
}
if (rrTokens.lastIndexOf('NS') === 0) {
var parseNS = function (rrData, recordsSoFar) {
var rrTokens = rrData.tokens;
if (!rrData.hasName) {
if (recordsSoFar.length) {
rrTokens.unshift(recordsSoFar[recordsSoFar.length - 1].name);
} else {
Expand All @@ -302,15 +334,13 @@
host: rrTokens[l - 1]
};

if (!isNaN(rrTokens[1])) result.ttl = parseInt(rrTokens[1], 10);
if (rrData.hasTtl) result.ttl = parseInt(rrTokens[1], 10);
return result;
};

var parseA = function (rrTokens, recordsSoFar) {
if (rrTokens.lastIndexOf('IN') === 0) {
rrTokens.shift();
}
if (rrTokens.lastIndexOf('A') === 0) {
var parseA = function (rrData, recordsSoFar) {
var rrTokens = rrData.tokens;
if (!rrData.hasName) {
if (recordsSoFar.length) {
rrTokens.unshift(recordsSoFar[recordsSoFar.length - 1].name);
} else {
Expand All @@ -324,15 +354,13 @@
ip: rrTokens[l - 1]
};

if (!isNaN(rrTokens[1])) result.ttl = parseInt(rrTokens[1], 10);
if (rrData.hasTtl) result.ttl = parseInt(rrTokens[1], 10);
return result;
};

var parseAAAA = function (rrTokens, recordsSoFar) {
if (rrTokens.lastIndexOf('IN') === 0) {
rrTokens.shift();
}
if (rrTokens.lastIndexOf('AAAA') === 0) {
var parseAAAA = function (rrData, recordsSoFar) {
var rrTokens = rrData.tokens;
if (!rrData.hasName) {
if (recordsSoFar.length) {
rrTokens.unshift(recordsSoFar[recordsSoFar.length - 1].name);
} else {
Expand All @@ -346,15 +374,13 @@
ip: rrTokens[l - 1]
};

if (!isNaN(rrTokens[1])) result.ttl = parseInt(rrTokens[1], 10);
if (rrData.hasTtl) result.ttl = parseInt(rrTokens[1], 10);
return result;
};

var parseCNAME = function (rrTokens, recordsSoFar) {
if (rrTokens.lastIndexOf('IN') === 0) {
rrTokens.shift();
}
if (rrTokens.lastIndexOf('CNAME') === 0) {
var parseCNAME = function (rrData, recordsSoFar) {
var rrTokens = rrData.tokens;
if (!rrData.hasName) {
if (recordsSoFar.length) {
rrTokens.unshift(recordsSoFar[recordsSoFar.length - 1].name);
} else {
Expand All @@ -368,15 +394,13 @@
alias: rrTokens[l - 1]
};

if (!isNaN(rrTokens[1])) result.ttl = parseInt(rrTokens[1], 10);
if (rrData.hasTtl) result.ttl = parseInt(rrTokens[1], 10);
return result;
};

var parseMX = function (rrTokens, recordsSoFar) {
if (rrTokens.lastIndexOf('IN') === 0) {
rrTokens.shift();
}
if (rrTokens.lastIndexOf('MX') === 0) {
var parseMX = function (rrData, recordsSoFar) {
var rrTokens = rrData.tokens;
if (!rrData.hasName) {
if (recordsSoFar.length) {
rrTokens.unshift(recordsSoFar[recordsSoFar.length - 1].name);
} else {
Expand All @@ -391,15 +415,13 @@
host: rrTokens[l - 1]
};

if (!isNaN(rrTokens[1])) result.ttl = parseInt(rrTokens[1], 10);
if (rrData.hasTtl) result.ttl = parseInt(rrTokens[1], 10);
return result;
};

var parseTXT = function (rrTokens, recordsSoFar) {
if (rrTokens.lastIndexOf('IN') === 0) {
rrTokens.shift();
}
if (rrTokens.lastIndexOf('TXT') === 0) {
var parseTXT = function (rrData, recordsSoFar) {
var rrTokens = rrData.tokens;
if (!rrData.hasName) {
if (recordsSoFar.length) {
rrTokens.unshift(recordsSoFar[recordsSoFar.length - 1].name);
} else {
Expand All @@ -413,15 +435,13 @@
txt: rrTokens[l - 1]
};

if (!isNaN(rrTokens[1])) result.ttl = parseInt(rrTokens[1], 10);
if (rrData.hasTtl) result.ttl = parseInt(rrTokens[1], 10);
return result;
};

var parsePTR = function (rrTokens, recordsSoFar, currentOrigin) {
if (rrTokens.lastIndexOf('IN') === 0) {
rrTokens.shift();
}
if (rrTokens.lastIndexOf('PTR') === 0 && recordsSoFar[recordsSoFar.length - 1]) {
var parsePTR = function (rrData, recordsSoFar, currentOrigin) {
var rrTokens = rrData.tokens;
if (!rrData.hasName && recordsSoFar[recordsSoFar.length - 1]) {
rrTokens.unshift(recordsSoFar[recordsSoFar.length - 1].name);
}

Expand All @@ -432,15 +452,13 @@
host: rrTokens[l - 1]
};

if (!isNaN(rrTokens[1])) result.ttl = parseInt(rrTokens[1], 10);
if (rrData.hasTtl) result.ttl = parseInt(rrTokens[1], 10);
return result;
};

var parseSRV = function (rrTokens, recordsSoFar) {
if (rrTokens.lastIndexOf('IN') === 0) {
rrTokens.shift();
}
if (rrTokens.lastIndexOf('SRV') === 0) {
var parseSRV = function (rrData, recordsSoFar) {
var rrTokens = rrData.tokens;
if (!rrData.hasName) {
if (recordsSoFar.length) {
rrTokens.unshift(recordsSoFar[recordsSoFar.length - 1].name);
} else {
Expand All @@ -457,29 +475,31 @@
port: parseInt(rrTokens[l - 2], 10)
};

if (!isNaN(rrTokens[1])) result.ttl = parseInt(rrTokens[1], 10);
if (rrData.hasTtl) result.ttl = parseInt(rrTokens[1], 10);
return result;
};

var parseSPF = function (rrTokens, recordsSoFar) {
if (rrTokens.lastIndexOf('IN') === 0) {
rrTokens.shift();
}
if (rrTokens.lastIndexOf('SPF') === 0) {
var parseSPF = function (rrData, recordsSoFar) {
var rrTokens = rrData.tokens;
if (!rrData.hasName) {
if (recordsSoFar.length) {
rrTokens.unshift(recordsSoFar[recordsSoFar.length - 1].name);
} else {
rrTokens.unshift('@');
}
}

var l = rrTokens.length;
var result = {
name: rrTokens[0],
data: rrTokens[l - 1]
data: ''
};

if (!isNaN(rrTokens[1])) result.ttl = parseInt(rrTokens[1], 10);
var l = rrTokens.length;
while (l-- > (rrData.hasTtl ? 4 : 3)) {
result.data = rrTokens[l] + ' ' + result.data.trim();
}

if (rrData.hasTtl) result.ttl = parseInt(rrTokens[1], 10);
return result;
};

Expand Down Expand Up @@ -513,16 +533,15 @@
ret.push(tokenBuffer.join(''));
tokenBuffer = [];
} else if (!!sep) {
ret.push('');
ret.push(element);
}

} else {
tokenBuffer.push(element);
}
}
if (tokenBuffer && tokenBuffer.length > 0) {
if (tokenBuffer.length > 0) {
ret.push(tokenBuffer.join(''));
} else {
} else if (!!sep) {
ret.push('');
}
return ret;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dns-zonefile",
"version": "0.1.17",
"version": "0.1.18",
"description": "A DNS zone file parser and generator.",
"main": "./lib/zonefile.js",
"bin": {
Expand Down
5 changes: 5 additions & 0 deletions test/zonefile_forward.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,10 @@ mail AAAA 2001:db8::1
mail1 CNAME mail
mail2 CNAME mail

test IN SPF "v=spf1" "mx:gcloud-node.com." "-all"
test1 SPF "v=spf2" "mx:gcloud-node.com." "-all"
IN SPF "v=spf3" "mx:gcloud-node.com." "-all "
SPF "v=spf4" "mx:gcloud-node.com." "-all"

treefrog.ca. IN TXT "v=spf1 a mx a:mail.treefrog.ca a:webmail.treefrog.ca ip4:76.75.250.33 ?all"
treemonkey.ca. IN TXT "v=DKIM1\; k=rsa\; p=MIGf..."

0 comments on commit 1dceeb6

Please sign in to comment.