2017-09-16 00:12:09 +07:00
'use strict' ;
2016-08-22 18:31:50 -06:00
2020-07-09 12:52:49 -04:00
// If you edit this file, you must run `go generate` to embed this
// file in the source code.
2020-09-27 16:37:42 -04:00
2020-07-09 12:52:49 -04:00
// If you are heavily debugging this code, the "-dev" flag will
// read this file directly instead of using the output of
// `go generate`. You'll still need to run `go generate` before
// you commit the changes.
2016-08-22 18:31:50 -06:00
var conf = {
registrars : [ ] ,
2016-12-16 13:10:27 -07:00
dns _providers : [ ] ,
2017-09-16 00:12:09 +07:00
domains : [ ] ,
2017-11-14 21:14:45 -07:00
domain _names : [ ] ,
2016-08-22 18:31:50 -06:00
} ;
2016-12-16 13:10:27 -07:00
var defaultArgs = [ ] ;
2016-08-22 18:31:50 -06:00
2017-09-16 00:12:09 +07:00
function initialize ( ) {
2016-08-22 18:31:50 -06:00
conf = {
registrars : [ ] ,
2016-12-16 13:10:27 -07:00
dns _providers : [ ] ,
2017-09-16 00:12:09 +07:00
domains : [ ] ,
2016-08-22 18:31:50 -06:00
} ;
2016-12-16 13:10:27 -07:00
defaultArgs = [ ] ;
2016-08-22 18:31:50 -06:00
}
2020-08-04 14:43:02 +01:00
// Returns an array of domains which were registered so far during runtime
// Own function for compatibility reasons or if some day special processing would be required.
function getConfiguredDomains ( ) {
return conf . domain _names ;
}
2017-09-16 00:12:09 +07:00
function NewRegistrar ( name , type , meta ) {
2016-08-22 18:31:50 -06:00
if ( type ) {
2017-09-16 00:12:09 +07:00
type == 'MANUAL' ;
2016-08-22 18:31:50 -06:00
}
2017-09-16 00:12:09 +07:00
var reg = { name : name , type : type , meta : meta } ;
2016-08-22 18:31:50 -06:00
conf . registrars . push ( reg ) ;
return name ;
}
2016-12-16 13:10:27 -07:00
function NewDnsProvider ( name , type , meta ) {
2017-09-16 00:12:09 +07:00
if ( typeof meta === 'object' && 'ip_conversions' in meta ) {
meta . ip _conversions = format _tt ( meta . ip _conversions ) ;
2016-08-22 18:31:50 -06:00
}
2017-09-16 00:12:09 +07:00
var dsp = { name : name , type : type , meta : meta } ;
2016-12-16 13:10:27 -07:00
conf . dns _providers . push ( dsp ) ;
2016-08-22 18:31:50 -06:00
return name ;
}
2017-09-16 00:12:09 +07:00
function newDomain ( name , registrar ) {
return {
name : name ,
2020-10-07 14:27:33 -04:00
subdomain : '' ,
2017-09-16 00:12:09 +07:00
registrar : registrar ,
meta : { } ,
records : [ ] ,
dnsProviders : { } ,
defaultTTL : 0 ,
nameservers : [ ] ,
2020-08-19 03:14:34 +12:00
ignored _names : [ ] ,
ignored _targets : [ ] ,
2017-09-16 00:12:09 +07:00
} ;
2016-08-22 18:31:50 -06:00
}
function processDargs ( m , domain ) {
2017-09-16 00:12:09 +07:00
// for each modifier, if it is a...
// function: call it with domain
// array: process recursively
// object: merge it into metadata
if ( _ . isFunction ( m ) ) {
m ( domain ) ;
} else if ( _ . isArray ( m ) ) {
for ( var j in m ) {
processDargs ( m [ j ] , domain ) ;
2016-08-22 18:31:50 -06:00
}
2017-09-16 00:12:09 +07:00
} else if ( _ . isObject ( m ) ) {
_ . extend ( domain . meta , m ) ;
} else {
throw 'WARNING: domain modifier type unsupported: ' +
typeof m +
' Domain: ' +
domain . name ;
}
2016-08-22 18:31:50 -06:00
}
// D(name,registrar): Create a DNS Domain. Use the parameters as records and mods.
2017-09-16 00:12:09 +07:00
function D ( name , registrar ) {
var domain = newDomain ( name , registrar ) ;
for ( var i = 0 ; i < defaultArgs . length ; i ++ ) {
processDargs ( defaultArgs [ i ] , domain ) ;
}
for ( var i = 2 ; i < arguments . length ; i ++ ) {
2016-08-22 18:31:50 -06:00
var m = arguments [ i ] ;
2017-09-16 00:12:09 +07:00
processDargs ( m , domain ) ;
2016-08-22 18:31:50 -06:00
}
2017-12-06 15:56:57 -05:00
if ( conf . domain _names . indexOf ( name ) !== - 1 ) {
throw name + ' is declared more than once' ;
2017-11-14 21:14:45 -07:00
}
2017-09-16 00:12:09 +07:00
conf . domains . push ( domain ) ;
2017-11-14 21:14:45 -07:00
conf . domain _names . push ( name ) ;
2016-08-22 18:31:50 -06:00
}
2020-10-07 14:27:33 -04:00
// D_EXTEND(name): Update a DNS Domain already added with D(), or subdomain thereof
2020-08-04 14:43:02 +01:00
function D _EXTEND ( name ) {
var domain = _getDomainObject ( name ) ;
if ( domain == null ) {
throw name + ' was not declared yet and therefore cannot be updated. Use D() before.' ;
}
2020-10-07 14:27:33 -04:00
domain . obj . subdomain = name . substr ( 0 , name . length - domain . obj . name . length - 1 ) ;
2020-08-04 14:43:02 +01:00
for ( var i = 1 ; i < arguments . length ; i ++ ) {
var m = arguments [ i ] ;
processDargs ( m , domain . obj ) ;
}
conf . domains [ domain . id ] = domain . obj ; // let's overwrite the object.
}
2020-10-07 16:03:36 -04:00
// _getDomainObject(name): This implements the domain matching
// algorithm used by D_EXTEND(). Candidate matches are an exact match
// of the domain's name, or if name is a proper subdomain of the
2020-11-18 07:05:26 -05:00
// domain's name. The longest match is returned.
2020-08-04 14:43:02 +01:00
function _getDomainObject ( name ) {
2020-10-25 17:29:25 +00:00
var domain = null ;
var domainLen = 0 ;
for ( var i = 0 ; i < conf . domains . length ; i ++ ) {
var thisName = conf . domains [ i ] [ "name" ] ;
var desiredSuffix = "." + thisName ;
var foundSuffix = name . substr ( - desiredSuffix . length ) ;
// If this is an exact match or the suffix matches...
if ( name === thisName || foundSuffix === desiredSuffix ) {
// If this match is a longer match than our current best match...
if ( thisName . length > domainLen ) {
domainLen = thisName . length ;
domain = { id : i , obj : conf . domains [ i ] } ;
}
}
2020-08-04 14:43:02 +01:00
}
2020-10-25 17:29:25 +00:00
return domain ;
2020-08-04 14:43:02 +01:00
}
2016-12-16 13:10:27 -07:00
// DEFAULTS provides a set of default arguments to apply to all future domains.
// Each call to DEFAULTS will clear any previous values set.
2017-09-16 00:12:09 +07:00
function DEFAULTS ( ) {
2016-12-16 13:10:27 -07:00
defaultArgs = [ ] ;
2017-09-16 00:12:09 +07:00
for ( var i = 0 ; i < arguments . length ; i ++ ) {
2016-12-16 13:10:27 -07:00
defaultArgs . push ( arguments [ i ] ) ;
}
}
2016-08-22 18:31:50 -06:00
// TTL(v): Set the TTL for a DNS record.
function TTL ( v ) {
2017-09-16 00:12:09 +07:00
if ( _ . isString ( v ) ) {
2017-06-08 09:15:14 -04:00
v = stringToDuration ( v ) ;
}
2016-08-22 18:31:50 -06:00
return function ( r ) {
r . ttl = v ;
2017-09-16 00:12:09 +07:00
} ;
2016-08-22 18:31:50 -06:00
}
2017-09-16 00:12:09 +07:00
function stringToDuration ( v ) {
2017-06-08 09:15:14 -04:00
var matches = v . match ( /^(\d+)([smhdwny]?)$/ ) ;
2017-09-16 00:12:09 +07:00
if ( matches == null ) {
throw v + ' is not a valid duration string' ;
2017-06-08 09:15:14 -04:00
}
2017-09-16 00:12:09 +07:00
unit = 's' ;
if ( matches [ 2 ] ) {
unit = matches [ 2 ] ;
2017-06-08 09:15:14 -04:00
}
2017-09-16 00:12:09 +07:00
v = parseInt ( matches [ 1 ] ) ;
var u = { s : 1 , m : 60 , h : 3600 } ;
u [ 'd' ] = u . h * 24 ;
u [ 'w' ] = u . d * 7 ;
u [ 'n' ] = u . d * 30 ;
u [ 'y' ] = u . d * 365 ;
2017-06-08 09:15:14 -04:00
v *= u [ unit ] ;
2017-09-16 00:12:09 +07:00
return v ;
2017-06-08 09:15:14 -04:00
}
2016-08-22 18:31:50 -06:00
// DefaultTTL(v): Set the default TTL for the domain.
function DefaultTTL ( v ) {
2017-09-16 00:12:09 +07:00
if ( _ . isString ( v ) ) {
2017-06-08 09:15:14 -04:00
v = stringToDuration ( v ) ;
}
2016-08-22 18:31:50 -06:00
return function ( d ) {
d . defaultTTL = v ;
2017-09-16 00:12:09 +07:00
} ;
2016-08-22 18:31:50 -06:00
}
2017-09-16 00:12:09 +07:00
function makeCAAFlag ( value ) {
return function ( record ) {
2017-08-12 01:48:43 +07:00
record . caaflag |= value ;
} ;
}
2017-07-25 14:59:40 -04:00
// CAA_CRITICAL: Critical CAA flag
2018-02-09 20:03:40 +01:00
var CAA _CRITICAL = makeCAAFlag ( 1 << 7 ) ;
2016-12-16 13:10:27 -07:00
2017-09-16 00:12:09 +07:00
// DnsProvider("providerName", 0)
2016-12-16 13:10:27 -07:00
// nsCount of 0 means don't use or register any nameservers.
// nsCount not provider means use all.
2017-09-16 00:12:09 +07:00
function DnsProvider ( name , nsCount ) {
if ( typeof nsCount === 'undefined' ) {
2016-12-16 13:10:27 -07:00
nsCount = - 1 ;
}
return function ( d ) {
d . dnsProviders [ name ] = nsCount ;
2017-09-16 00:12:09 +07:00
} ;
2016-12-16 13:10:27 -07:00
}
2016-08-22 18:31:50 -06:00
// A(name,ip, recordModifiers...)
2017-08-12 01:48:43 +07:00
var A = recordBuilder ( 'A' ) ;
2016-08-22 18:31:50 -06:00
// AAAA(name,ip, recordModifiers...)
2017-08-12 01:48:43 +07:00
var AAAA = recordBuilder ( 'AAAA' ) ;
2016-08-22 18:31:50 -06:00
2017-04-19 13:13:28 -06:00
// ALIAS(name,target, recordModifiers...)
2017-08-12 01:48:43 +07:00
var ALIAS = recordBuilder ( 'ALIAS' ) ;
2017-04-19 13:13:28 -06:00
2020-03-02 20:25:42 +04:00
// AZURE_ALIAS(name, type, target, recordModifiers...)
var AZURE _ALIAS = recordBuilder ( 'AZURE_ALIAS' , {
args : [
[ 'name' , _ . isString ] ,
[ 'type' , validateAzureAliasType ] ,
[ 'target' , _ . isString ] ,
] ,
transform : function ( record , args , modifier ) {
record . name = args . name ;
record . target = args . target ;
if ( _ . isObject ( record . azure _alias ) ) {
record . azure _alias [ 'type' ] = args . type ;
} else {
record . azure _alias = { type : args . type } ;
}
} ,
} ) ;
function validateAzureAliasType ( value ) {
if ( ! _ . isString ( value ) ) {
return false ;
}
return [ 'A' , 'AAAA' , 'CNAME' ] . indexOf ( value ) !== - 1 ;
}
ROUTE53: Support Route53's ALIAS record type (#239) (#301)
* Stable comparison of metadata (#239)
Iterating over a map in Go never produces twice the same ordering.
Thus when comparing two metadata map with more than one key, the
`differ` is always finding differences.
To properly compare records metadata, we need to iterate the maps
in a deterministic way.
Signed-off-by: Brice Figureau <brice@daysofwonder.com>
* Support for Route53 ALIAS record type (#239)
Route53 ALIAS doesn't behave like a regular ALIAS, and is much more
limited as its target can only be some specific AWS resources or
another record in the same zone.
According to #239, this change adds a new directive R53_ALIAS which
implements this specific alias. This record type can only be used
with the Route53 provider.
This directive usage looks like this:
```js
D("example.com", REGISTRAR, DnsProvider("ROUTE53"),
R53_ALIAS("foo1", "A", "bar") // record in same zone
R53_ALIAS("foo2", "A",
"blahblah.elasticloadbalancing.us-west-1.amazonaws.com",
R53_ZONE('Z368ELLRRE2KJ0')) // ELB in us-west-1
```
Unfortunately, Route53 requires indicating the hosted zone id
where the target is defined (those are listed in AWS documentation,
see the R53_ALIAS documentation for links).
2018-01-16 11:53:12 +01:00
// R53_ALIAS(name, target, type, recordModifiers...)
var R53 _ALIAS = recordBuilder ( 'R53_ALIAS' , {
2020-02-22 12:07:10 -05:00
args : [
[ 'name' , _ . isString ] ,
[ 'type' , validateR53AliasType ] ,
[ 'target' , _ . isString ] ,
] ,
transform : function ( record , args , modifiers ) {
ROUTE53: Support Route53's ALIAS record type (#239) (#301)
* Stable comparison of metadata (#239)
Iterating over a map in Go never produces twice the same ordering.
Thus when comparing two metadata map with more than one key, the
`differ` is always finding differences.
To properly compare records metadata, we need to iterate the maps
in a deterministic way.
Signed-off-by: Brice Figureau <brice@daysofwonder.com>
* Support for Route53 ALIAS record type (#239)
Route53 ALIAS doesn't behave like a regular ALIAS, and is much more
limited as its target can only be some specific AWS resources or
another record in the same zone.
According to #239, this change adds a new directive R53_ALIAS which
implements this specific alias. This record type can only be used
with the Route53 provider.
This directive usage looks like this:
```js
D("example.com", REGISTRAR, DnsProvider("ROUTE53"),
R53_ALIAS("foo1", "A", "bar") // record in same zone
R53_ALIAS("foo2", "A",
"blahblah.elasticloadbalancing.us-west-1.amazonaws.com",
R53_ZONE('Z368ELLRRE2KJ0')) // ELB in us-west-1
```
Unfortunately, Route53 requires indicating the hosted zone id
where the target is defined (those are listed in AWS documentation,
see the R53_ALIAS documentation for links).
2018-01-16 11:53:12 +01:00
record . name = args . name ;
record . target = args . target ;
if ( _ . isObject ( record . r53 _alias ) ) {
record . r53 _alias [ 'type' ] = args . type ;
} else {
2020-02-22 12:07:10 -05:00
record . r53 _alias = { type : args . type } ;
ROUTE53: Support Route53's ALIAS record type (#239) (#301)
* Stable comparison of metadata (#239)
Iterating over a map in Go never produces twice the same ordering.
Thus when comparing two metadata map with more than one key, the
`differ` is always finding differences.
To properly compare records metadata, we need to iterate the maps
in a deterministic way.
Signed-off-by: Brice Figureau <brice@daysofwonder.com>
* Support for Route53 ALIAS record type (#239)
Route53 ALIAS doesn't behave like a regular ALIAS, and is much more
limited as its target can only be some specific AWS resources or
another record in the same zone.
According to #239, this change adds a new directive R53_ALIAS which
implements this specific alias. This record type can only be used
with the Route53 provider.
This directive usage looks like this:
```js
D("example.com", REGISTRAR, DnsProvider("ROUTE53"),
R53_ALIAS("foo1", "A", "bar") // record in same zone
R53_ALIAS("foo2", "A",
"blahblah.elasticloadbalancing.us-west-1.amazonaws.com",
R53_ZONE('Z368ELLRRE2KJ0')) // ELB in us-west-1
```
Unfortunately, Route53 requires indicating the hosted zone id
where the target is defined (those are listed in AWS documentation,
see the R53_ALIAS documentation for links).
2018-01-16 11:53:12 +01:00
}
} ,
} ) ;
// R53_ZONE(zone_id)
function R53 _ZONE ( zone _id ) {
2020-02-22 12:07:10 -05:00
return function ( r ) {
ROUTE53: Support Route53's ALIAS record type (#239) (#301)
* Stable comparison of metadata (#239)
Iterating over a map in Go never produces twice the same ordering.
Thus when comparing two metadata map with more than one key, the
`differ` is always finding differences.
To properly compare records metadata, we need to iterate the maps
in a deterministic way.
Signed-off-by: Brice Figureau <brice@daysofwonder.com>
* Support for Route53 ALIAS record type (#239)
Route53 ALIAS doesn't behave like a regular ALIAS, and is much more
limited as its target can only be some specific AWS resources or
another record in the same zone.
According to #239, this change adds a new directive R53_ALIAS which
implements this specific alias. This record type can only be used
with the Route53 provider.
This directive usage looks like this:
```js
D("example.com", REGISTRAR, DnsProvider("ROUTE53"),
R53_ALIAS("foo1", "A", "bar") // record in same zone
R53_ALIAS("foo2", "A",
"blahblah.elasticloadbalancing.us-west-1.amazonaws.com",
R53_ZONE('Z368ELLRRE2KJ0')) // ELB in us-west-1
```
Unfortunately, Route53 requires indicating the hosted zone id
where the target is defined (those are listed in AWS documentation,
see the R53_ALIAS documentation for links).
2018-01-16 11:53:12 +01:00
if ( _ . isObject ( r . r53 _alias ) ) {
r . r53 _alias [ 'zone_id' ] = zone _id ;
} else {
2020-02-22 12:07:10 -05:00
r . r53 _alias = { zone _id : zone _id } ;
ROUTE53: Support Route53's ALIAS record type (#239) (#301)
* Stable comparison of metadata (#239)
Iterating over a map in Go never produces twice the same ordering.
Thus when comparing two metadata map with more than one key, the
`differ` is always finding differences.
To properly compare records metadata, we need to iterate the maps
in a deterministic way.
Signed-off-by: Brice Figureau <brice@daysofwonder.com>
* Support for Route53 ALIAS record type (#239)
Route53 ALIAS doesn't behave like a regular ALIAS, and is much more
limited as its target can only be some specific AWS resources or
another record in the same zone.
According to #239, this change adds a new directive R53_ALIAS which
implements this specific alias. This record type can only be used
with the Route53 provider.
This directive usage looks like this:
```js
D("example.com", REGISTRAR, DnsProvider("ROUTE53"),
R53_ALIAS("foo1", "A", "bar") // record in same zone
R53_ALIAS("foo2", "A",
"blahblah.elasticloadbalancing.us-west-1.amazonaws.com",
R53_ZONE('Z368ELLRRE2KJ0')) // ELB in us-west-1
```
Unfortunately, Route53 requires indicating the hosted zone id
where the target is defined (those are listed in AWS documentation,
see the R53_ALIAS documentation for links).
2018-01-16 11:53:12 +01:00
}
} ;
}
function validateR53AliasType ( value ) {
if ( ! _ . isString ( value ) ) {
return false ;
}
2020-02-22 12:07:10 -05:00
return (
[
'A' ,
'AAAA' ,
'CNAME' ,
'CAA' ,
'MX' ,
'TXT' ,
'PTR' ,
'SPF' ,
'SRV' ,
'NAPTR' ,
2020-03-02 20:25:42 +04:00
] . indexOf ( value ) !== - 1
2020-02-22 12:07:10 -05:00
) ;
ROUTE53: Support Route53's ALIAS record type (#239) (#301)
* Stable comparison of metadata (#239)
Iterating over a map in Go never produces twice the same ordering.
Thus when comparing two metadata map with more than one key, the
`differ` is always finding differences.
To properly compare records metadata, we need to iterate the maps
in a deterministic way.
Signed-off-by: Brice Figureau <brice@daysofwonder.com>
* Support for Route53 ALIAS record type (#239)
Route53 ALIAS doesn't behave like a regular ALIAS, and is much more
limited as its target can only be some specific AWS resources or
another record in the same zone.
According to #239, this change adds a new directive R53_ALIAS which
implements this specific alias. This record type can only be used
with the Route53 provider.
This directive usage looks like this:
```js
D("example.com", REGISTRAR, DnsProvider("ROUTE53"),
R53_ALIAS("foo1", "A", "bar") // record in same zone
R53_ALIAS("foo2", "A",
"blahblah.elasticloadbalancing.us-west-1.amazonaws.com",
R53_ZONE('Z368ELLRRE2KJ0')) // ELB in us-west-1
```
Unfortunately, Route53 requires indicating the hosted zone id
where the target is defined (those are listed in AWS documentation,
see the R53_ALIAS documentation for links).
2018-01-16 11:53:12 +01:00
}
2017-07-25 14:59:40 -04:00
// CAA(name,tag,value, recordModifiers...)
2017-08-12 01:48:43 +07:00
var CAA = recordBuilder ( 'CAA' , {
2017-09-16 00:12:09 +07:00
// TODO(tlim): It should be an error if value is not 0 or 128.
2020-02-22 12:07:10 -05:00
args : [
[ 'name' , _ . isString ] ,
[ 'tag' , _ . isString ] ,
[ 'value' , _ . isString ] ,
] ,
2017-09-16 00:12:09 +07:00
transform : function ( record , args , modifiers ) {
2017-08-12 01:48:43 +07:00
record . name = args . name ;
record . caatag = args . tag ;
record . target = args . value ;
} ,
2017-09-16 00:12:09 +07:00
modifierNumber : function ( record , value ) {
2017-08-12 01:48:43 +07:00
record . caaflags |= value ;
} ,
} ) ;
2017-04-19 13:13:28 -06:00
2016-08-22 18:31:50 -06:00
// CNAME(name,target, recordModifiers...)
2017-08-12 01:48:43 +07:00
var CNAME = recordBuilder ( 'CNAME' ) ;
2016-08-22 18:31:50 -06:00
2020-05-30 10:40:21 -04:00
// DS(name, keytag, algorithm, digestype, digest)
var DS = recordBuilder ( "DS" , {
args : [
[ 'name' , _ . isString ] ,
[ 'keytag' , _ . isNumber ] ,
[ 'algorithm' , _ . isNumber ] ,
[ 'digesttype' , _ . isNumber ] ,
[ 'digest' , _ . isString ]
] ,
transform : function ( record , args , modifiers ) {
record . name = args . name ;
record . dskeytag = args . keytag ;
record . dsalgorithm = args . algorithm ;
record . dsdigesttype = args . digesttype ;
record . dsdigest = args . digest ;
record . target = args . target ;
} ,
} ) ;
2017-07-06 10:18:15 -04:00
// PTR(name,target, recordModifiers...)
2017-08-12 01:48:43 +07:00
var PTR = recordBuilder ( 'PTR' ) ;
2017-07-06 10:18:15 -04:00
2019-03-28 15:40:13 +01:00
// NAPTR(name,order,preference,flags,service,regexp,target, recordModifiers...)
var NAPTR = recordBuilder ( 'NAPTR' , {
args : [
[ 'name' , _ . isString ] ,
[ 'order' , _ . isNumber ] ,
[ 'preference' , _ . isNumber ] ,
[ 'flags' , _ . isString ] ,
[ 'service' , _ . isString ] ,
[ 'regexp' , _ . isString ] ,
[ 'target' , _ . isString ] ,
] ,
transform : function ( record , args , modifiers ) {
record . name = args . name ;
record . naptrorder = args . order ;
record . naptrpreference = args . preference ;
record . naptrflags = args . flags ;
record . naptrservice = args . service ;
record . naptrregexp = args . regexp ;
record . target = args . target ;
} ,
} ) ;
2017-07-19 15:53:40 -04:00
// SRV(name,priority,weight,port,target, recordModifiers...)
2017-08-12 01:48:43 +07:00
var SRV = recordBuilder ( 'SRV' , {
args : [
[ 'name' , _ . isString ] ,
[ 'priority' , _ . isNumber ] ,
[ 'weight' , _ . isNumber ] ,
[ 'port' , _ . isNumber ] ,
[ 'target' , _ . isString ] ,
] ,
2017-09-16 00:12:09 +07:00
transform : function ( record , args , modifiers ) {
2017-08-12 01:48:43 +07:00
record . name = args . name ;
record . srvpriority = args . priority ;
record . srvweight = args . weight ;
record . srvport = args . port ;
record . target = args . target ;
} ,
} ) ;
2017-07-19 15:53:40 -04:00
2019-01-28 23:26:20 +01:00
// SSHFP(name,algorithm,type,value, recordModifiers...)
var SSHFP = recordBuilder ( 'SSHFP' , {
args : [
[ 'name' , _ . isString ] ,
[ 'algorithm' , _ . isNumber ] ,
[ 'fingerprint' , _ . isNumber ] ,
[ 'value' , _ . isString ] ,
] ,
transform : function ( record , args , modifiers ) {
record . name = args . name ;
record . sshfpalgorithm = args . algorithm ;
record . sshfpfingerprint = args . fingerprint ;
record . target = args . value ;
} ,
} ) ;
2017-09-15 09:03:29 -04:00
// name, usage, selector, matchingtype, certificate
var TLSA = recordBuilder ( 'TLSA' , {
args : [
[ 'name' , _ . isString ] ,
[ 'usage' , _ . isNumber ] ,
[ 'selector' , _ . isNumber ] ,
[ 'matchingtype' , _ . isNumber ] ,
2018-01-09 12:53:16 -05:00
[ 'target' , _ . isString ] , // recordBuilder needs a "target" argument
2017-09-15 09:03:29 -04:00
] ,
2017-09-16 00:12:09 +07:00
transform : function ( record , args , modifiers ) {
2017-09-15 09:03:29 -04:00
record . name = args . name ;
record . tlsausage = args . usage ;
record . tlsaselector = args . selector ;
record . tlsamatchingtype = args . matchingtype ;
record . target = args . target ;
} ,
} ) ;
2018-01-04 19:19:35 -05:00
function isStringOrArray ( x ) {
2018-01-06 15:13:22 -05:00
return _ . isString ( x ) || _ . isArray ( x ) ;
2018-01-04 19:19:35 -05:00
}
2020-11-18 07:05:26 -05:00
// AUTOSPLIT is a modifier that instructs the Go-level code to
// split this TXT record's target into chunks of 255.
var AUTOSPLIT = { txtSplitAlgorithm : 'multistring' } ; // Create 255-byte chunks
//var TXTMULTISPACE = { txtSplitAlgorithm: 'space' }; // Split on space [not implemented]
2016-08-22 18:31:50 -06:00
// TXT(name,target, recordModifiers...)
2018-01-06 15:13:22 -05:00
var TXT = recordBuilder ( 'TXT' , {
2020-02-22 12:07:10 -05:00
args : [
[ 'name' , _ . isString ] ,
[ 'target' , isStringOrArray ] ,
] ,
2018-01-06 15:13:22 -05:00
transform : function ( record , args , modifiers ) {
record . name = args . name ;
// Store the strings twice:
// .target is the first string
// .txtstrings is the individual strings.
// NOTE: If there are more than 1 string, providers should only access
// .txtstrings, thus it doesn't matter what we store in .target.
// However, by storing the first string there, it improves backwards
// compatibility when the len(array) == 1 and (intentionally) breaks
// broken providers early in the integration tests.
if ( _ . isString ( args . target ) ) {
record . target = args . target ;
record . txtstrings = [ args . target ] ;
} else {
record . target = args . target [ 0 ] ;
record . txtstrings = args . target ;
}
} ,
2018-01-04 19:19:35 -05:00
} ) ;
2016-08-22 18:31:50 -06:00
// MX(name,priority,target, recordModifiers...)
2017-08-12 01:48:43 +07:00
var MX = recordBuilder ( 'MX' , {
args : [
[ 'name' , _ . isString ] ,
[ 'priority' , _ . isNumber ] ,
[ 'target' , _ . isString ] ,
] ,
2017-09-16 00:12:09 +07:00
transform : function ( record , args , modifiers ) {
2017-08-12 01:48:43 +07:00
record . name = args . name ;
record . mxpreference = args . priority ;
record . target = args . target ;
} ,
} ) ;
2016-08-22 18:31:50 -06:00
// NS(name,target, recordModifiers...)
2017-08-12 01:48:43 +07:00
var NS = recordBuilder ( 'NS' ) ;
2016-08-22 18:31:50 -06:00
// NAMESERVER(name,target)
2018-03-22 11:52:52 -04:00
function NAMESERVER ( name ) {
2020-02-22 12:07:10 -05:00
if ( arguments . length != 1 ) {
throw 'NAMESERVER only accepts one argument for name.' ;
2018-03-22 11:52:52 -04:00
}
2016-08-22 18:31:50 -06:00
return function ( d ) {
2018-03-22 11:52:52 -04:00
d . nameservers . push ( { name : name } ) ;
2017-09-16 00:12:09 +07:00
} ;
2016-08-22 18:31:50 -06:00
}
2018-09-04 07:57:11 -07:00
// NAMESERVER_TTL(v): Set the TTL for NAMESERVER records.
function NAMESERVER _TTL ( v ) {
if ( _ . isString ( v ) ) {
v = stringToDuration ( v ) ;
}
2020-02-22 12:07:10 -05:00
return { ns _ttl : v . toString ( ) } ;
2018-09-04 07:57:11 -07:00
}
2016-08-22 18:31:50 -06:00
function format _tt ( transform _table ) {
2017-09-16 00:12:09 +07:00
// Turn [[low: 1, high: 2, newBase: 3], [low: 4, high: 5, newIP: 6]]
// into "1 ~ 2 ~ 3 ~; 4 ~ 5 ~ ~ 6"
var lines = [ ] ;
for ( var i = 0 ; i < transform _table . length ; i ++ ) {
var ip = transform _table [ i ] ;
var newIP = ip . newIP ;
if ( newIP ) {
if ( _ . isArray ( newIP ) ) {
newIP = _ . map ( newIP , function ( i ) {
return num2dot ( i ) ;
} ) . join ( ',' ) ;
} else {
newIP = num2dot ( newIP ) ;
}
2016-08-22 18:31:50 -06:00
}
2017-09-16 00:12:09 +07:00
var newBase = ip . newBase ;
if ( newBase ) {
if ( _ . isArray ( newBase ) ) {
newBase = _ . map ( newBase , function ( i ) {
return num2dot ( i ) ;
} ) . join ( ',' ) ;
} else {
newBase = num2dot ( newBase ) ;
}
2016-09-27 11:35:28 -06:00
}
2017-09-16 00:12:09 +07:00
var row = [ num2dot ( ip . low ) , num2dot ( ip . high ) , newBase , newIP ] ;
lines . push ( row . join ( ' ~ ' ) ) ;
2016-09-27 11:35:28 -06:00
}
2017-09-16 00:12:09 +07:00
return lines . join ( ' ; ' ) ;
2016-08-22 18:31:50 -06:00
}
2018-01-15 21:39:29 +01:00
// IGNORE(name)
function IGNORE ( name ) {
2020-08-19 03:14:34 +12:00
// deprecated, use IGNORE_NAME
return IGNORE _NAME ( name ) ;
}
// IGNORE_NAME(name)
function IGNORE _NAME ( name ) {
2020-02-22 12:07:10 -05:00
return function ( d ) {
2020-08-19 03:14:34 +12:00
d . ignored _names . push ( name ) ;
2018-01-15 21:39:29 +01:00
} ;
}
2020-08-19 03:14:34 +12:00
// IGNORE_TARGET(target)
function IGNORE _TARGET ( target , rType ) {
return function ( d ) {
d . ignored _targets . push ( { pattern : target , type : rType } ) ;
} ;
}
2016-08-22 18:31:50 -06:00
// IMPORT_TRANSFORM(translation_table, domain)
2017-08-12 01:48:43 +07:00
var IMPORT _TRANSFORM = recordBuilder ( 'IMPORT_TRANSFORM' , {
2017-09-16 00:12:09 +07:00
args : [ [ 'translation_table' ] , [ 'domain' ] , [ 'ttl' , _ . isNumber ] ] ,
transform : function ( record , args , modifiers ) {
2017-08-12 01:48:43 +07:00
record . name = '@' ;
record . target = args . domain ;
record . meta [ 'transform_table' ] = format _tt ( args . translation _table ) ;
record . ttl = args . ttl ;
} ,
} ) ;
2016-08-22 18:31:50 -06:00
// PURGE()
function PURGE ( d ) {
2017-09-16 00:12:09 +07:00
d . KeepUnknown = false ;
2016-08-22 18:31:50 -06:00
}
// NO_PURGE()
function NO _PURGE ( d ) {
2017-09-16 00:12:09 +07:00
d . KeepUnknown = true ;
2016-08-22 18:31:50 -06:00
}
2020-09-27 16:37:42 -04:00
// AUTODNSSEC
// Permitted values are:
// "" Do not modify the setting (the default)
// "on" Enable AUTODNSSEC for this domain
// "off" Disable AUTODNSSEC for this domain
function AUTODNSSEC _ON ( d ) {
d . auto _dnssec = "on" ;
}
function AUTODNSSEC _OFF ( d ) {
d . auto _dnssec = "off" ;
}
2020-02-22 07:09:31 -05:00
function AUTODNSSEC ( d ) {
2020-09-27 16:37:42 -04:00
console . log (
"WARNING: AUTODNSSEC is deprecated. It is now a no-op. Please use AUTODNSSEC_ON or AUTODNSSEC_OFF. The default is to make no modifications. This message will disappear in a future release."
) ;
2020-02-22 07:09:31 -05:00
}
2017-08-12 01:48:43 +07:00
/ * *
* @ deprecated
* /
2017-09-16 00:12:09 +07:00
function getModifiers ( args , start ) {
2016-08-22 18:31:50 -06:00
var mods = [ ] ;
2017-09-16 00:12:09 +07:00
for ( var i = start ; i < args . length ; i ++ ) {
mods . push ( args [ i ] ) ;
2016-08-22 18:31:50 -06:00
}
return mods ;
}
2017-08-12 01:48:43 +07:00
/ * *
* Record type builder
* @ param { string } type Record type
* @ param { string } opts . args [ ] [ 0 ] Argument name
* @ param { function = } opts . args [ ] [ 1 ] Optional validator
* @ param { function = } opts . transform Function to apply arguments to record .
* Take ( record , args , modifier ) as arguments . Any modifiers will be
* applied before this function . It should mutate the given record .
* @ param { function = } opts . applyModifier Function to apply modifiers to the record
* /
2017-09-16 00:12:09 +07:00
function recordBuilder ( type , opts ) {
2017-08-12 01:48:43 +07:00
opts = _ . defaults ( { } , opts , {
2017-09-16 00:12:09 +07:00
args : [ [ 'name' , _ . isString ] , [ 'target' ] ] ,
2017-08-12 01:48:43 +07:00
transform : function ( record , args , modifiers ) {
// record will have modifiers already applied
// args will be an object for parameters defined
record . name = args . name ;
if ( _ . isNumber ( args . target ) ) {
record . target = num2dot ( args . target ) ;
} else {
record . target = args . target ;
}
} ,
applyModifier : function ( record , modifiers ) {
for ( var i = 0 ; i < modifiers . length ; i ++ ) {
var mod = modifiers [ i ] ;
if ( _ . isFunction ( mod ) ) {
mod ( record ) ;
} else if ( _ . isObject ( mod ) ) {
// convert transforms to strings
if ( mod . transform && _ . isArray ( mod . transform ) ) {
mod . transform = format _tt ( mod . transform ) ;
}
_ . extend ( record . meta , mod ) ;
} else {
2017-09-16 00:12:09 +07:00
throw 'ERROR: Unknown modifier type' ;
2017-08-12 01:48:43 +07:00
}
}
} ,
} ) ;
2017-09-16 00:12:09 +07:00
return function ( ) {
2017-08-12 01:48:43 +07:00
var parsedArgs = { } ;
var modifiers = [ ] ;
if ( arguments . length < opts . args . length ) {
2017-09-16 00:12:09 +07:00
var argumentsList = opts . args
. map ( function ( item ) {
return item [ 0 ] ;
} )
. join ( ', ' ) ;
throw type +
' record requires ' +
opts . args . length +
' arguments (' +
argumentsList +
'). Only ' +
arguments . length +
' were supplied' ;
2017-08-12 01:48:43 +07:00
return ;
}
// collect arguments
for ( var i = 0 ; i < opts . args . length ; i ++ ) {
var argDefinition = opts . args [ i ] ;
var value = arguments [ i ] ;
if ( argDefinition . length > 1 ) {
// run validator if supplied
2017-09-16 00:12:09 +07:00
if ( ! argDefinition [ 1 ] ( value ) ) {
throw type +
' record ' +
argDefinition [ 0 ] +
' argument validation failed' ;
2017-08-12 01:48:43 +07:00
}
}
parsedArgs [ argDefinition [ 0 ] ] = value ;
}
// collect modifiers
for ( var i = opts . args . length ; i < arguments . length ; i ++ ) {
modifiers . push ( arguments [ i ] ) ;
}
2017-09-16 00:12:09 +07:00
return function ( d ) {
2017-08-12 01:48:43 +07:00
var record = {
type : type ,
meta : { } ,
ttl : d . defaultTTL ,
} ;
opts . applyModifier ( record , modifiers ) ;
opts . transform ( record , parsedArgs , modifiers ) ;
2020-10-07 14:27:33 -04:00
// Handle D_EXTEND() with subdomains.
2020-12-03 08:33:37 -05:00
if ( d . subdomain &&
record . type != 'CF_REDIRECT' &&
record . type != 'CF_TEMP_REDIRECT' ) {
fqdn = [ d . subdomain , d . name ] . join ( "." )
2020-10-07 14:27:33 -04:00
record . subdomain = d . subdomain ;
if ( record . name == '@' ) {
2020-12-03 08:33:37 -05:00
record . subdomain = d . subdomain ;
2020-10-07 14:27:33 -04:00
record . name = d . subdomain ;
2020-12-03 08:33:37 -05:00
} else if ( fqdn != record . name && record . type != 'PTR' ) {
record . subdomain = d . subdomain ;
2020-10-07 14:27:33 -04:00
record . name += '.' + d . subdomain ;
}
}
2017-08-12 01:48:43 +07:00
d . records . push ( record ) ;
return record ;
} ;
} ;
}
/ * *
* @ deprecated
* /
2017-09-16 00:12:09 +07:00
function addRecord ( d , type , name , target , mods ) {
2016-08-22 18:31:50 -06:00
// if target is number, assume ip address. convert it.
if ( _ . isNumber ( target ) ) {
target = num2dot ( target ) ;
}
2017-09-16 00:12:09 +07:00
var rec = {
type : type ,
name : name ,
target : target ,
ttl : d . defaultTTL ,
priority : 0 ,
meta : { } ,
} ;
2016-08-22 18:31:50 -06:00
// for each modifier, decide based on type:
// - Function: call is with the record as the argument
// - Object: merge it into the metadata
// - Number: IF MX record assume it is priority
2017-07-19 15:53:40 -04:00
if ( mods ) {
2017-09-16 00:12:09 +07:00
for ( var i = 0 ; i < mods . length ; i ++ ) {
var m = mods [ i ] ;
2017-07-19 15:53:40 -04:00
if ( _ . isFunction ( m ) ) {
m ( rec ) ;
} else if ( _ . isObject ( m ) ) {
2018-01-09 12:53:16 -05:00
// convert transforms to strings
2017-09-16 00:12:09 +07:00
if ( m . transform && _ . isArray ( m . transform ) ) {
m . transform = format _tt ( m . transform ) ;
}
_ . extend ( rec . meta , m ) ;
_ . extend ( rec . meta , m ) ;
2017-07-19 15:53:40 -04:00
} else {
2017-09-16 00:12:09 +07:00
console . log (
'WARNING: Modifier type unsupported:' ,
typeof m ,
'(Skipping!)'
) ;
2017-07-19 15:53:40 -04:00
}
}
}
d . records . push ( rec ) ;
return rec ;
}
2018-01-09 12:53:16 -05:00
// ip conversion functions from http://stackoverflow.com/a/8105740/121660
2016-08-22 18:31:50 -06:00
// via http://javascript.about.com/library/blipconvert.htm
2017-09-16 00:12:09 +07:00
function IP ( dot ) {
2016-08-22 18:31:50 -06:00
var d = dot . split ( '.' ) ;
2017-09-16 00:12:09 +07:00
// prettier-ignore
return ( ( ( ( ( ( + d [ 0 ] ) * 256 ) + ( + d [ 1 ] ) ) * 256 ) + ( + d [ 2 ] ) ) * 256 ) + ( + d [ 3 ] ) ;
2016-08-22 18:31:50 -06:00
}
2017-09-16 00:12:09 +07:00
function num2dot ( num ) {
if ( num === undefined ) {
return '' ;
2016-08-22 18:31:50 -06:00
}
2017-09-16 00:12:09 +07:00
if ( _ . isString ( num ) ) {
return num ;
2016-08-22 18:31:50 -06:00
}
2017-09-16 00:12:09 +07:00
var d = num % 256 ;
for ( var i = 3 ; i > 0 ; i -- ) {
num = Math . floor ( num / 256 ) ;
2020-02-22 12:07:10 -05:00
d = ( num % 256 ) + '.' + d ;
2016-08-22 18:31:50 -06:00
}
return d ;
}
2017-05-11 01:02:57 -04:00
// Cloudflare aliases:
2017-05-15 16:28:26 -04:00
// Meta settings for individual records.
2017-09-16 00:12:09 +07:00
var CF _PROXY _OFF = { cloudflare _proxy : 'off' } ; // Proxy disabled.
var CF _PROXY _ON = { cloudflare _proxy : 'on' } ; // Proxy enabled.
var CF _PROXY _FULL = { cloudflare _proxy : 'full' } ; // Proxy+Railgun enabled.
2017-05-15 16:28:26 -04:00
// Per-domain meta settings:
// Proxy default off for entire domain (the default):
2017-09-16 00:12:09 +07:00
var CF _PROXY _DEFAULT _OFF = { cloudflare _proxy _default : 'off' } ;
2017-05-15 16:28:26 -04:00
// Proxy default on for entire domain:
2017-09-16 00:12:09 +07:00
var CF _PROXY _DEFAULT _ON = { cloudflare _proxy _default : 'on' } ;
2019-06-13 13:32:54 +02:00
// UniversalSSL off for entire domain:
var CF _UNIVERSALSSL _OFF = { cloudflare _universalssl : 'off' } ;
// UniversalSSL on for entire domain:
var CF _UNIVERSALSSL _ON = { cloudflare _universalssl : 'on' } ;
2017-05-25 20:38:48 -04:00
2017-05-19 14:15:57 -04:00
// CUSTOM, PROVIDER SPECIFIC RECORD TYPES
2017-08-12 01:48:43 +07:00
2019-05-23 06:29:21 -07:00
function _validateCloudflareRedirect ( value ) {
2017-09-16 00:12:09 +07:00
if ( ! _ . isString ( value ) ) {
2017-08-12 01:48:43 +07:00
return false ;
}
2017-09-16 00:12:09 +07:00
return value . indexOf ( ',' ) === - 1 ;
2017-08-12 01:48:43 +07:00
}
2017-09-16 00:12:09 +07:00
var CF _REDIRECT = recordBuilder ( 'CF_REDIRECT' , {
2017-08-12 01:48:43 +07:00
args : [
2019-05-23 06:29:21 -07:00
[ 'source' , _validateCloudflareRedirect ] ,
[ 'destination' , _validateCloudflareRedirect ] ,
2017-08-12 01:48:43 +07:00
] ,
2017-09-16 00:12:09 +07:00
transform : function ( record , args , modifiers ) {
record . name = '@' ;
record . target = args . source + ',' + args . destination ;
2017-08-12 01:48:43 +07:00
} ,
} ) ;
2017-09-16 00:12:09 +07:00
var CF _TEMP _REDIRECT = recordBuilder ( 'CF_TEMP_REDIRECT' , {
2017-08-12 01:48:43 +07:00
args : [
2019-05-23 06:29:21 -07:00
[ 'source' , _validateCloudflareRedirect ] ,
[ 'destination' , _validateCloudflareRedirect ] ,
2017-08-12 01:48:43 +07:00
] ,
2017-09-16 00:12:09 +07:00
transform : function ( record , args , modifiers ) {
record . name = '@' ;
record . target = args . source + ',' + args . destination ;
2017-08-12 01:48:43 +07:00
} ,
} ) ;
2017-10-23 12:54:31 -04:00
2017-12-06 15:56:57 -05:00
var URL = recordBuilder ( 'URL' ) ;
var URL301 = recordBuilder ( 'URL301' ) ;
var FRAME = recordBuilder ( 'FRAME' ) ;
2021-02-10 16:57:15 +00:00
var NS1 _URLFWD = recordBuilder ( 'NS1_URLFWD' ) ;
2017-12-06 15:50:21 -05:00
// SPF_BUILDER takes an object:
// parts: The parts of the SPF record (to be joined with ' ').
// label: The DNS label for the primary SPF record. (default: '@')
2017-12-06 15:56:57 -05:00
// raw: Where (which label) to store an unaltered version of the SPF settings.
2019-05-23 15:25:06 +02:00
// ttl: The time for TTL, integer or string. (default: not defined, using DefaultTTL)
2017-12-06 15:50:21 -05:00
// split: The template for additional records to be created (default: '_spf%d')
// flatten: A list of domains to be flattened.
2020-07-09 12:52:49 -04:00
// overhead1: Amout of "buffer room" to reserve on the first item in the spf chain.
2020-07-31 19:28:13 +02:00
// txtMaxSize: The maximum size for each TXT string. Values over 255 will result in multiple strings (default: '255')
2017-12-06 15:50:21 -05:00
function SPF _BUILDER ( value ) {
2017-12-06 15:56:57 -05:00
if ( ! value . parts || value . parts . length < 2 ) {
throw 'SPF_BUILDER requires at least 2 elements' ;
}
if ( ! value . label ) {
value . label = '@' ;
}
2020-07-31 16:40:22 +02:00
if ( ! value . raw && value . raw !== '' ) {
2017-12-06 15:56:57 -05:00
value . raw = '_rawspf' ;
}
r = [ ] ; // The list of records to return.
p = { } ; // The metaparameters to set on the main TXT record.
rawspf = value . parts . join ( ' ' ) ; // The unaltered SPF settings.
// If flattening is requested, generate a TXT record with the raw SPF settings.
if ( value . flatten && value . flatten . length > 0 ) {
p . flatten = value . flatten . join ( ',' ) ;
2020-07-31 16:40:22 +02:00
// Only add the raw spf record if it isn't an empty string
if ( value . raw !== '' ) {
2020-11-18 07:05:26 -05:00
rp = { } ;
rp . txtSplitAlgorithm = 'multistring' ; // Split the target if needed.
2020-07-31 16:40:22 +02:00
if ( value . ttl ) {
2020-11-18 07:05:26 -05:00
r . push ( TXT ( value . raw , rawspf , rp , TTL ( value . ttl ) ) ) ;
2020-07-31 16:40:22 +02:00
} else {
2020-11-18 07:05:26 -05:00
r . push ( TXT ( value . raw , rawspf , rp ) ) ;
2020-07-31 16:40:22 +02:00
}
2019-05-23 15:25:06 +02:00
}
2017-12-06 15:56:57 -05:00
}
// If overflow is specified, enable splitting.
if ( value . overflow ) {
p . split = value . overflow ;
}
2020-07-09 12:52:49 -04:00
if ( value . overhead1 ) {
p . overhead1 = value . overhead1 ;
}
2020-07-31 19:28:13 +02:00
if ( value . txtMaxSize ) {
p . txtMaxSize = value . txtMaxSize ;
}
2020-11-18 07:05:26 -05:00
p . txtSplitAlgorithm = 'multistring' ; // Split the target if needed.
2017-12-06 15:56:57 -05:00
// Generate a TXT record with the metaparameters.
2019-05-23 15:25:06 +02:00
if ( value . ttl ) {
r . push ( TXT ( value . label , rawspf , p , TTL ( value . ttl ) ) ) ;
} else {
r . push ( TXT ( value . label , rawspf , p ) ) ;
}
2017-12-06 15:56:57 -05:00
return r ;
2017-12-06 15:50:21 -05:00
}
2018-01-04 21:17:08 -05:00
2019-05-18 17:10:18 +02:00
// CAA_BUILDER takes an object:
// label: The DNS label for the CAA record. (default: '@')
// iodef: The contact mail address. (optional)
// iodef_critical: Boolean if sending report is required/critical. If not supported, certificate should be refused. (optional)
// issue: List of CAs which are allowed to issue certificates for the domain (creates one record for each).
// issuewild: Allowed CAs which can issue wildcard certificates for this domain. (creates one record for each)
function CAA _BUILDER ( value ) {
if ( ! value . label ) {
value . label = '@' ;
}
2020-02-22 12:07:10 -05:00
if ( value . issue && value . issue == 'none' ) value . issue = [ ';' ] ;
if ( value . issuewild && value . issuewild == 'none' ) value . issuewild = [ ';' ] ;
2019-05-18 17:10:18 +02:00
2020-02-22 12:07:10 -05:00
if (
( ! value . issue && ! value . issuewild ) ||
( value . issue &&
value . issue . length == 0 &&
2020-03-02 20:25:42 +04:00
value . issuewild &&
value . issuewild . length == 0 )
2020-02-22 12:07:10 -05:00
) {
2019-05-18 17:10:18 +02:00
throw 'CAA_BUILDER requires at least one entry at issue or issuewild' ;
}
r = [ ] ; // The list of records to return.
if ( value . iodef ) {
if ( value . iodef _critical ) {
2020-02-22 12:07:10 -05:00
r . push ( CAA ( value . label , 'iodef' , value . iodef , CAA _CRITICAL ) ) ;
2019-05-18 17:10:18 +02:00
} else {
2020-02-22 12:07:10 -05:00
r . push ( CAA ( value . label , 'iodef' , value . iodef ) ) ;
2019-05-18 17:10:18 +02:00
}
}
if ( value . issue )
for ( var i = 0 , len = value . issue . length ; i < len ; i ++ )
2020-02-22 12:07:10 -05:00
r . push ( CAA ( value . label , 'issue' , value . issue [ i ] ) ) ;
2019-05-18 17:10:18 +02:00
if ( value . issuewild )
for ( var i = 0 , len = value . issuewild . length ; i < len ; i ++ )
2020-02-22 12:07:10 -05:00
r . push ( CAA ( value . label , 'issuewild' , value . issuewild [ i ] ) ) ;
2019-05-18 17:10:18 +02:00
return r ;
}
2018-01-04 21:17:08 -05:00
// Split a DKIM string if it is >254 bytes.
function DKIM ( arr ) {
2018-01-06 15:13:22 -05:00
chunkSize = 255 ;
var R = [ ] ;
for ( var i = 0 , len = arr . length ; i < len ; i += chunkSize )
R . push ( arr . slice ( i , i + chunkSize ) ) ;
return R ;
2018-01-04 21:17:08 -05:00
}
2020-08-19 19:00:40 +01:00
// Function wrapper for glob() for recursively loading files.
// As the main function (in Go) is in our control anyway, all the values here are already sanity-checked.
// Note: glob() is only an internal undocumented helper function. So use it on your own risk.
function require _glob ( ) {
arguments [ 2 ] = "js" ; // force to only include .js files.
var files = glob . apply ( null , arguments ) ;
for ( i = 0 ; i < files . length ; i ++ ) {
require ( files [ i ] ) ;
}
return files
}
2020-10-27 15:43:00 +01:00
// Set default values for CLI variables
function CLI _DEFAULTS ( defaults ) {
for ( var key in defaults ) {
if ( typeof this [ key ] === "undefined" ) {
this [ key ] = defaults [ key ]
}
}
}
2021-01-06 23:45:32 +08:00
function FETCH ( ) {
return fetch . apply ( null , arguments ) . catch ( PANIC ) ;
}