UNPKG

13.1 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6
7var _es6Promisify = require('es6-promisify');
8
9var _es6Promisify2 = _interopRequireDefault(_es6Promisify);
10
11var _Any = require('./Any');
12
13var _Any2 = _interopRequireDefault(_Any);
14
15var _Error = require('../Error');
16
17var _Error2 = _interopRequireDefault(_Error);
18
19var _Reference = require('../Reference');
20
21var _Reference2 = _interopRequireDefault(_Reference);
22
23function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
24
25const specialRanges = {
26 unspecified: ['0.0.0.0/8', '0::/128'],
27 broadcast: ['255.255.255.255/32'],
28 multicast: ['224.0.0.0/4', 'ff00::/8'],
29 linklocal: ['169.254.0.0/16', 'fe80::/10'],
30 loopback: ['127.0.0.0/8', '::1/128'],
31 private: ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'],
32
33 reserved: ['192.0.0.0/24', '192.88.99.0/24', '198.51.100.0/24', '203.0.113.0/24', '240.0.0.0/4', '2001:db8::/32'],
34 uniquelocal: ['fc00::/7'],
35 ipv4mapped: ['::ffff:0:0/96'],
36 rfc6145: ['::ffff:0:0:0/96'],
37 rfc6052: ['64:ff9b::/96'],
38 '6to4': ['2002::/16'],
39 teredo: ['2001::/32'],
40 special: [] };
41var _iteratorNormalCompletion = true;
42var _didIteratorError = false;
43var _iteratorError = undefined;
44
45try {
46 for (var _iterator = Object.keys(specialRanges)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
47 const key = _step.value;
48
49 if (key !== 'special') specialRanges.special.push(specialRanges[key]);
50 }
51} catch (err) {
52 _didIteratorError = true;
53 _iteratorError = err;
54} finally {
55 try {
56 if (!_iteratorNormalCompletion && _iterator.return) {
57 _iterator.return();
58 }
59 } finally {
60 if (_didIteratorError) {
61 throw _iteratorError;
62 }
63 }
64}
65
66class IPSchema extends _Any2.default {
67 constructor(base) {
68 super(base);
69 this._setting.format = 'short';
70
71 let raw = this._rules.descriptor.pop();
72 let allow = this._rules.descriptor.pop();
73 this._rules.descriptor.push(this._typeDescriptor, allow, this._versionDescriptor, this._formatDescriptor, raw);
74 raw = this._rules.validator.pop();
75 allow = this._rules.validator.pop();
76 this._rules.validator.push(this._typeValidator, allow, this._versionValidator, this._formatValidator, raw);
77 }
78
79 lookup(flag) {
80 return this._setFlag('lookup', flag);
81 }
82
83 _typeDescriptor() {
84 return 'An IP address as string or byte array is needed here.\n';
85 }
86
87 _typeValidator(data) {
88 const check = this._check;
89
90 return Promise.resolve().then(() => require('ipaddr.js')).then(ipaddr => {
91 if (Array.isArray(data.value) && (data.value.length === 4 || data.value.length === 16)) {
92 const ip = ipaddr.fromByteArray(data.value);
93 data.value = ip;
94 return Promise.resolve();
95 }
96 if (typeof data.value === 'string') {
97 let ip = null;
98 try {
99 ip = ipaddr.parse(data.value);
100 } catch (err) {
101 if (check.lookup) {
102 return Promise.resolve().then(() => require('dns')).then(dns => (0, _es6Promisify2.default)(dns.lookup)(data.value, { family: check.version }).then(resolved => {
103 data.value = ipaddr.parse(resolved);
104 return true;
105 }));
106 }
107 }
108 if (!ip) return Promise.reject(new Error('The given value could not be parsed as any valid IP address'));
109 data.value = ip;
110 return Promise.resolve();
111 }
112 return Promise.reject(new _Error2.default(this, data, `An ${typeof data.value} could not be transformed to an IP address`));
113 });
114 }
115
116 _allowValidator(data) {
117 const check = this._check;
118 this._checkArray('allow');
119 this._checkArray('deny');
120
121 const deny = [];
122 if (check.deny) {
123 var _iteratorNormalCompletion2 = true;
124 var _didIteratorError2 = false;
125 var _iteratorError2 = undefined;
126
127 try {
128 for (var _iterator2 = check.deny[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
129 const e = _step2.value;
130
131 if (specialRanges[e]) {
132 var _iteratorNormalCompletion3 = true;
133 var _didIteratorError3 = false;
134 var _iteratorError3 = undefined;
135
136 try {
137 for (var _iterator3 = specialRanges[e][Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
138 const n = _step3.value;
139 deny.push(`${n}#`);
140 }
141 } catch (err) {
142 _didIteratorError3 = true;
143 _iteratorError3 = err;
144 } finally {
145 try {
146 if (!_iteratorNormalCompletion3 && _iterator3.return) {
147 _iterator3.return();
148 }
149 } finally {
150 if (_didIteratorError3) {
151 throw _iteratorError3;
152 }
153 }
154 }
155 } else deny.push(e);
156 }
157 } catch (err) {
158 _didIteratorError2 = true;
159 _iteratorError2 = err;
160 } finally {
161 try {
162 if (!_iteratorNormalCompletion2 && _iterator2.return) {
163 _iterator2.return();
164 }
165 } finally {
166 if (_didIteratorError2) {
167 throw _iteratorError2;
168 }
169 }
170 }
171 }
172 const allow = [];
173 if (check.allow) {
174 var _iteratorNormalCompletion4 = true;
175 var _didIteratorError4 = false;
176 var _iteratorError4 = undefined;
177
178 try {
179 for (var _iterator4 = check.allow[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
180 const e = _step4.value;
181
182 if (specialRanges[e]) {
183 var _iteratorNormalCompletion5 = true;
184 var _didIteratorError5 = false;
185 var _iteratorError5 = undefined;
186
187 try {
188 for (var _iterator5 = specialRanges[e][Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
189 const n = _step5.value;
190 allow.push(`${n}#`);
191 }
192 } catch (err) {
193 _didIteratorError5 = true;
194 _iteratorError5 = err;
195 } finally {
196 try {
197 if (!_iteratorNormalCompletion5 && _iterator5.return) {
198 _iterator5.return();
199 }
200 } finally {
201 if (_didIteratorError5) {
202 throw _iteratorError5;
203 }
204 }
205 }
206 } else allow.push(e);
207 }
208 } catch (err) {
209 _didIteratorError4 = true;
210 _iteratorError4 = err;
211 } finally {
212 try {
213 if (!_iteratorNormalCompletion4 && _iterator4.return) {
214 _iterator4.return();
215 }
216 } finally {
217 if (_didIteratorError4) {
218 throw _iteratorError4;
219 }
220 }
221 }
222 }
223 if (allow && deny && allow.length && deny.length) {
224 check.deny = check.deny.filter(e => !check.allow.includes(e));
225 }
226
227 return Promise.resolve().then(() => require('ipaddr.js')).then(ipaddr => {
228 let denyBits = 0;
229 if (deny.length) {
230 var _iteratorNormalCompletion6 = true;
231 var _didIteratorError6 = false;
232 var _iteratorError6 = undefined;
233
234 try {
235 for (var _iterator6 = deny[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
236 const e = _step6.value;
237
238 const n = e.replace(/#$/, '');
239 let range;
240 if (n.match(/\//)) range = ipaddr.parseCIDR(n);else {
241 const ip = ipaddr.parse(n);
242 range = ip.kind === 4 ? [ip, 32] : [ip, 128];
243 }
244 if (data.value.match(range)) {
245 let bits = n.length < e.length ? 1 : range[1];
246 if (Number.isNaN(bits)) bits = 0;
247 if (bits > denyBits) denyBits = bits;
248 }
249 }
250 } catch (err) {
251 _didIteratorError6 = true;
252 _iteratorError6 = err;
253 } finally {
254 try {
255 if (!_iteratorNormalCompletion6 && _iterator6.return) {
256 _iterator6.return();
257 }
258 } finally {
259 if (_didIteratorError6) {
260 throw _iteratorError6;
261 }
262 }
263 }
264 }
265 let allowBits = 0;
266 if (allow.length) {
267 allowBits = -1;
268 var _iteratorNormalCompletion7 = true;
269 var _didIteratorError7 = false;
270 var _iteratorError7 = undefined;
271
272 try {
273 for (var _iterator7 = allow[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {
274 const e = _step7.value;
275
276 const n = e.replace(/#$/, '');
277 let range;
278 if (n.match(/\//)) range = ipaddr.parseCIDR(n);else {
279 const ip = ipaddr.parse(n);
280 range = ip.kind === 4 ? [ip, 32] : [ip, 128];
281 }
282 if (data.value.match(range)) {
283 let bits = n.length < e.length ? 1 : range[1];
284 if (Number.isNaN(bits)) bits = 0;
285 if (bits > allowBits) allowBits = bits;
286 }
287 }
288 } catch (err) {
289 _didIteratorError7 = true;
290 _iteratorError7 = err;
291 } finally {
292 try {
293 if (!_iteratorNormalCompletion7 && _iterator7.return) {
294 _iterator7.return();
295 }
296 } finally {
297 if (_didIteratorError7) {
298 throw _iteratorError7;
299 }
300 }
301 }
302 }
303
304 if (denyBits > allowBits) {
305 return Promise.reject(new _Error2.default(this, data, 'Element found in blacklist (denied item).'));
306 }
307 return Promise.resolve();
308 });
309 }
310
311 version(value) {
312 return this._setAny('version', value);
313 }
314 mapping(flag) {
315 return this._setFlag('mapping', flag);
316 }
317
318 _versionDescriptor() {
319 const set = this._setting;
320 let msg = '';
321 if (set.version) {
322 if (this._isReference('version')) {
323 msg += `Valid addresses has to be of IP version defined at ${set.version.description}. `;
324 } else msg += `Only IPv${set.version} addresses are valid. `;
325 }
326 if (set.mapping) {
327 if (this._isReference('mapping')) {
328 msg += `IPv4 adresses may be automatically converted if set under ${set.mapping.description}. `;
329 } else msg += 'IPv4 addresses may be automatically converted. ';
330 }
331 return msg.length ? `${msg.trim()}\n` : msg;
332 }
333
334 _versionValidator(data) {
335 const check = this._check;
336 try {
337 this._checkNumber('version');
338 this._checkBoolean('mapping');
339 if (check.version && ![4, 6].includes(check.version)) {
340 throw new Error(`Only IP version 4 or 6 are valid, ${check.version} is unknown`);
341 }
342 } catch (err) {
343 return Promise.reject(new _Error2.default(this, data, err.message));
344 }
345
346 if (check.version) {
347 if (check.version === 4) {
348 if (data.value.kind() === 'ipv6') {
349 if (check.mapping && data.value.isIPv4MappedAddress()) data.value = data.value.toIPv4Address();else {
350 return Promise.reject(new _Error2.default(this, data, `The given value is no valid IPv${check.version} address`));
351 }
352 }
353 } else if (data.value.kind() === 'ipv4') {
354 if (check.mapping) data.value = data.value.toIPv4MappedAddress();else {
355 return Promise.reject(new _Error2.default(this, data, `The given value is no valid IPv${check.version} address`));
356 }
357 }
358 }
359 return Promise.resolve();
360 }
361
362 format(value = 'short') {
363 return this._setAny('format', value);
364 }
365
366 _formatDescriptor() {
367 const set = this._setting;
368 let msg = '';
369 if (set.format) {
370 if (this._isReference('format')) {
371 msg += `The ip address will be formatted like defined under ${set.format.description}. `;
372 } else msg += `The ip address will be formatted in ${set.format} form. `;
373 }
374 return msg.length ? `${msg.trim()}\n` : msg;
375 }
376
377 _formatValidator(data) {
378 const check = this._check;
379 try {
380 this._checkString('format');
381 if (!['short', 'long', 'array'].includes(check.format)) {
382 throw new Error(`One of 'short', 'long' or 'array' is needed for format but ${check.format} \
383was given`);
384 }
385 } catch (err) {
386 return Promise.reject(new _Error2.default(this, data, err.message));
387 }
388
389 if (check.format === 'array') {
390 data.value = data.value.octets || data.value.parts;
391 } else if (data.value.kind() === 'ipv6' && check.format === 'long') {
392 data.value = data.value.toNormalizedString();
393 } else data.value = data.value.toString();
394 return Promise.resolve();
395 }
396}
397
398exports.default = IPSchema;
\No newline at end of file