bind-record-manager
Version:
Nodejs module for Parse and Generate recordFile of Bind DNS. Manager system
227 lines (201 loc) • 8.61 kB
JavaScript
const fs = require("fs")
class RecordManager {
constructor(recordFilePath=undefined) {
this.recordFilePath = recordFilePath
this.rawData = undefined
this.rawDataList = undefined
this.parsedData = undefined
this.removeCommentsRegex = /\\"|"(?:\\"|[^"])*"|((^|[^\\])\;((?!(#)).)*)/g
this.removeBlankLineRegex = /^(?:[\t ]*(?:\r?\n|\r))+/gm
//
this.recordTemplate = {
mx: "{name}\tIN\tMX\t{preference}\t{host}\t ;#{id}\n",
ns: "{name}\tIN\tNS\t{host}\t ;#{id}\n",
a: "{name}\tIN\tA\t{host}\t ;#{id}\n",
soa: `{name}\tIN\tSOA\t{mname}\t{rname} (\n{serial}\t;serial\n{refresh}\t;refresh\n{retry}\t;retry\n{expire}\t;expire\n{minimum}\t;minimum ttl\n)\t ;#{id}\n`,
aaaa: "{name}\tIN\tAAAA\t{host}\t ;#{id}\n",
cname: "{name}\tIN\tCNAME\t{host}\t ;#{id}\n",
txt: "{name}\tIN\tTXT\t{txt}\t ;#{id}\n",
srv: "{name}\tIN\tSRV\t{priority}\t{weight}\t{port}\t{target}\t ;#{id}\n"
}
this.generatorPattern = "{origin}\n{ttl}\n\n; SOA Record\n{soa}\n; NS Records\n{ns}\n\n; MX Records\n{mx}\n\n; A Records\n{a}\n\n; AAAA Records\n{aaaa}\n\n; CNAME Records\n{cname}\n\n; TXT Records\n{txt}\n\n; SRV Records\n{srv}"
}
setRawData(rawData=undefined) {
this.rawData = rawData ? rawData : fs.readFileSync(this.recordFilePath, 'utf-8')
}
getRawData() {
return this.rawData
}
setRemoveCommentsRegex(regex) {
this.removeCommentsRegex = regex
}
getRemoveCommentsRegex() {
return this.removeCommentsRegex
}
getRemoveBlankLineRegex() {
return this.removeBlankLineRegex
}
setRemoveBlankLineRegex(regex) {
this.removeBlankLineRegex = regex
}
setRawDataList(list) {
this.rawDataList = list
}
getRawDataList() {
return this.rawDataList
}
setParsedData(object) {
this.parsedData = object
}
getParsedData() {
return this.parsedData
}
getRecordTemplate() {
return this.recordTemplate
}
setRecordTemplate(object) {
this.recordTemplate = object
}
getGeneratorPattern() {
return this.generatorPattern
}
setGeneratorPattern(string) {
this.generatorPattern = string
}
removeComments() {
let changed = this.getRawData().replace(this.getRemoveCommentsRegex(), function (manual, pat) {
return !pat ? manual : ""
})
this.setRawData(changed)
}
flatten() {
let captured = []
let regex = /\([\s\S]*?\)/gim
let match = regex.exec(this.getRawData())
while (match !== null) {
match.replacement = match[0].replace(/\s+/gm, ' ')
captured.push(match)
match = regex.exec(this.getRawData())
}
let arrText = this.getRawData().split('')
for (match of captured) {
arrText.splice(match.index, match[0].length, match.replacement)
}
this.setRawData(arrText.join('').replace(/\(|\)/gim, ' '))
}
removeBlankLine() {
this.setRawData(this.getRawData().replace(this.getRemoveBlankLineRegex(), ''))
}
splitRecords() {
let recordList = this.getRawData().split('\n')
if(recordList[recordList.length - 1] === '') recordList.pop()
this.setRawDataList(recordList)
}
splitElementsOfRecords() {
const regex = /\S+/g
var rawDatalist = this.getRawDataList()
var elementList = []
for (let index = 0; index < rawDatalist.length; index++) {
elementList.push(rawDatalist[index].match(regex))
}
this.setRawDataList(elementList)
}
generateRecordObject() {
var recordObject = {}
this.getRawDataList().forEach(recordElementList => {
if(recordElementList[0] === '$TTL' || recordElementList[0] === '$ORIGIN')
recordObject[recordElementList[0]] = recordElementList[1]
else {
if(recordElementList[2] === 'SOA')
recordObject[recordElementList[2]] = {
id: recordElementList[recordElementList.length - 1].replace("#", ''),
name: recordElementList[0],
mname: recordElementList[3],
rname: recordElementList[4],
serial: recordElementList[5],
refresh: recordElementList[6],
retry: recordElementList[7],
expire: recordElementList[8],
minimum: recordElementList[9]
}
else {
if(!recordObject[recordElementList[2]]) recordObject[recordElementList[2]] = []
var pattern = {id: recordElementList[recordElementList.length - 1].replace("#", ''),
name: recordElementList[0]}
switch (recordElementList[2]) {
case "NS":
pattern = {...pattern, host: recordElementList[3] }
break;
case "MX":
pattern = {...pattern, host: recordElementList[4],
preference:recordElementList[3] }
break;
case "A":
pattern = {...pattern, host: recordElementList[3] }
break;
case "AAAA":
pattern = {...pattern, host: recordElementList[3] }
break;
case "CNAME":
pattern = {...pattern, alias: recordElementList[3] }
break;
case "TXT":
pattern = {...pattern, txt: recordElementList[3] }
break;
case "SRV":
pattern = {...pattern, target:recordElementList[6],
priority:recordElementList[3],
weight:recordElementList[4],
port:recordElementList[5] }
break;
default:
throw new Error("some record is invalid in record file")
}
recordObject[recordElementList[2]].push(pattern)
}
}
})
this.setParsedData(recordObject)
}
Parse(dataRaw=undefined) {
if(dataRaw) this.setRawData(dataRaw)
else this.setRawData()
this.removeComments()
this.flatten()
this.removeBlankLine()
this.splitRecords()
this.splitElementsOfRecords()
this.generateRecordObject()
return this.getParsedData()
}
Generate(recordObject) {
if(!recordObject || typeof recordObject !== "object") throw new Error("invalid Generate function input")
var pattern = this.getGeneratorPattern()
for (const key in recordObject) {
if(key === 'ttl') pattern = pattern.replace("{ttl}", `$TTL ${recordObject.ttl}`)
if(key === 'origin') pattern = pattern.replace("{origin}", `$ORIGIN ${recordObject.origin}`)
if(key === 'soa') {
var template = this.getRecordTemplate()[key]
for (const keyoption in recordObject[key].Options) {
template = template.replace(`{${keyoption}}`, recordObject[key].Options[keyoption])
}
pattern = pattern.replace(`{${key}}`, template)
}else{
var temp = ""
Array.prototype.forEach.call(recordObject[key], record => {
var template = this.getRecordTemplate()[key]
for (const keyoption in record.Options) {
template = template.replace(`{${keyoption}}`, record.Options[keyoption])
}
temp += template
})
pattern = pattern.replace(`{${key}}`, temp)
}
}
pattern = pattern.replace(/(\{.*\})/gi, '')
return pattern
}
}
module.exports = RecordManager
module.exports.RecordManager = RecordManager
module.exports.default = RecordManager