36774e7978da219adb2bd4de0ff4c48779784816
[aai/esr-gui.git] /
1 (function() {
2   var expandIPv6, ipaddr, ipv4Part, ipv4Regexes, ipv6Part, ipv6Regexes, matchCIDR, root;
3
4   ipaddr = {};
5
6   root = this;
7
8   if ((typeof module !== "undefined" && module !== null) && module.exports) {
9     module.exports = ipaddr;
10   } else {
11     root['ipaddr'] = ipaddr;
12   }
13
14   matchCIDR = function(first, second, partSize, cidrBits) {
15     var part, shift;
16     if (first.length !== second.length) {
17       throw new Error("ipaddr: cannot match CIDR for objects with different lengths");
18     }
19     part = 0;
20     while (cidrBits > 0) {
21       shift = partSize - cidrBits;
22       if (shift < 0) {
23         shift = 0;
24       }
25       if (first[part] >> shift !== second[part] >> shift) {
26         return false;
27       }
28       cidrBits -= partSize;
29       part += 1;
30     }
31     return true;
32   };
33
34   ipaddr.subnetMatch = function(address, rangeList, defaultName) {
35     var rangeName, rangeSubnets, subnet, _i, _len;
36     if (defaultName == null) {
37       defaultName = 'unicast';
38     }
39     for (rangeName in rangeList) {
40       rangeSubnets = rangeList[rangeName];
41       if (rangeSubnets[0] && !(rangeSubnets[0] instanceof Array)) {
42         rangeSubnets = [rangeSubnets];
43       }
44       for (_i = 0, _len = rangeSubnets.length; _i < _len; _i++) {
45         subnet = rangeSubnets[_i];
46         if (address.match.apply(address, subnet)) {
47           return rangeName;
48         }
49       }
50     }
51     return defaultName;
52   };
53
54   ipaddr.IPv4 = (function() {
55     function IPv4(octets) {
56       var octet, _i, _len;
57       if (octets.length !== 4) {
58         throw new Error("ipaddr: ipv4 octet count should be 4");
59       }
60       for (_i = 0, _len = octets.length; _i < _len; _i++) {
61         octet = octets[_i];
62         if (!((0 <= octet && octet <= 255))) {
63           throw new Error("ipaddr: ipv4 octet should fit in 8 bits");
64         }
65       }
66       this.octets = octets;
67     }
68
69     IPv4.prototype.kind = function() {
70       return 'ipv4';
71     };
72
73     IPv4.prototype.toString = function() {
74       return this.octets.join(".");
75     };
76
77     IPv4.prototype.toByteArray = function() {
78       return this.octets.slice(0);
79     };
80
81     IPv4.prototype.match = function(other, cidrRange) {
82       var _ref;
83       if (cidrRange === void 0) {
84         _ref = other, other = _ref[0], cidrRange = _ref[1];
85       }
86       if (other.kind() !== 'ipv4') {
87         throw new Error("ipaddr: cannot match ipv4 address with non-ipv4 one");
88       }
89       return matchCIDR(this.octets, other.octets, 8, cidrRange);
90     };
91
92     IPv4.prototype.SpecialRanges = {
93       unspecified: [[new IPv4([0, 0, 0, 0]), 8]],
94       broadcast: [[new IPv4([255, 255, 255, 255]), 32]],
95       multicast: [[new IPv4([224, 0, 0, 0]), 4]],
96       linkLocal: [[new IPv4([169, 254, 0, 0]), 16]],
97       loopback: [[new IPv4([127, 0, 0, 0]), 8]],
98       "private": [[new IPv4([10, 0, 0, 0]), 8], [new IPv4([172, 16, 0, 0]), 12], [new IPv4([192, 168, 0, 0]), 16]],
99       reserved: [[new IPv4([192, 0, 0, 0]), 24], [new IPv4([192, 0, 2, 0]), 24], [new IPv4([192, 88, 99, 0]), 24], [new IPv4([198, 51, 100, 0]), 24], [new IPv4([203, 0, 113, 0]), 24], [new IPv4([240, 0, 0, 0]), 4]]
100     };
101
102     IPv4.prototype.range = function() {
103       return ipaddr.subnetMatch(this, this.SpecialRanges);
104     };
105
106     IPv4.prototype.toIPv4MappedAddress = function() {
107       return ipaddr.IPv6.parse("::ffff:" + (this.toString()));
108     };
109
110     IPv4.prototype.prefixLengthFromSubnetMask = function() {
111       var cidr, i, octet, stop, zeros, zerotable, _i;
112       zerotable = {
113         0: 8,
114         128: 7,
115         192: 6,
116         224: 5,
117         240: 4,
118         248: 3,
119         252: 2,
120         254: 1,
121         255: 0
122       };
123       cidr = 0;
124       stop = false;
125       for (i = _i = 3; _i >= 0; i = _i += -1) {
126         octet = this.octets[i];
127         if (octet in zerotable) {
128           zeros = zerotable[octet];
129           if (stop && zeros !== 0) {
130             return null;
131           }
132           if (zeros !== 8) {
133             stop = true;
134           }
135           cidr += zeros;
136         } else {
137           return null;
138         }
139       }
140       return 32 - cidr;
141     };
142
143     return IPv4;
144
145   })();
146
147   ipv4Part = "(0?\\d+|0x[a-f0-9]+)";
148
149   ipv4Regexes = {
150     fourOctet: new RegExp("^" + ipv4Part + "\\." + ipv4Part + "\\." + ipv4Part + "\\." + ipv4Part + "$", 'i'),
151     longValue: new RegExp("^" + ipv4Part + "$", 'i')
152   };
153
154   ipaddr.IPv4.parser = function(string) {
155     var match, parseIntAuto, part, shift, value;
156     parseIntAuto = function(string) {
157       if (string[0] === "0" && string[1] !== "x") {
158         return parseInt(string, 8);
159       } else {
160         return parseInt(string);
161       }
162     };
163     if (match = string.match(ipv4Regexes.fourOctet)) {
164       return (function() {
165         var _i, _len, _ref, _results;
166         _ref = match.slice(1, 6);
167         _results = [];
168         for (_i = 0, _len = _ref.length; _i < _len; _i++) {
169           part = _ref[_i];
170           _results.push(parseIntAuto(part));
171         }
172         return _results;
173       })();
174     } else if (match = string.match(ipv4Regexes.longValue)) {
175       value = parseIntAuto(match[1]);
176       if (value > 0xffffffff || value < 0) {
177         throw new Error("ipaddr: address outside defined range");
178       }
179       return ((function() {
180         var _i, _results;
181         _results = [];
182         for (shift = _i = 0; _i <= 24; shift = _i += 8) {
183           _results.push((value >> shift) & 0xff);
184         }
185         return _results;
186       })()).reverse();
187     } else {
188       return null;
189     }
190   };
191
192   ipaddr.IPv6 = (function() {
193     function IPv6(parts) {
194       var i, part, _i, _j, _len, _ref;
195       if (parts.length === 16) {
196         this.parts = [];
197         for (i = _i = 0; _i <= 14; i = _i += 2) {
198           this.parts.push((parts[i] << 8) | parts[i + 1]);
199         }
200       } else if (parts.length === 8) {
201         this.parts = parts;
202       } else {
203         throw new Error("ipaddr: ipv6 part count should be 8 or 16");
204       }
205       _ref = this.parts;
206       for (_j = 0, _len = _ref.length; _j < _len; _j++) {
207         part = _ref[_j];
208         if (!((0 <= part && part <= 0xffff))) {
209           throw new Error("ipaddr: ipv6 part should fit in 16 bits");
210         }
211       }
212     }
213
214     IPv6.prototype.kind = function() {
215       return 'ipv6';
216     };
217
218     IPv6.prototype.toString = function() {
219       var compactStringParts, part, pushPart, state, stringParts, _i, _len;
220       stringParts = (function() {
221         var _i, _len, _ref, _results;
222         _ref = this.parts;
223         _results = [];
224         for (_i = 0, _len = _ref.length; _i < _len; _i++) {
225           part = _ref[_i];
226           _results.push(part.toString(16));
227         }
228         return _results;
229       }).call(this);
230       compactStringParts = [];
231       pushPart = function(part) {
232         return compactStringParts.push(part);
233       };
234       state = 0;
235       for (_i = 0, _len = stringParts.length; _i < _len; _i++) {
236         part = stringParts[_i];
237         switch (state) {
238           case 0:
239             if (part === '0') {
240               pushPart('');
241             } else {
242               pushPart(part);
243             }
244             state = 1;
245             break;
246           case 1:
247             if (part === '0') {
248               state = 2;
249             } else {
250               pushPart(part);
251             }
252             break;
253           case 2:
254             if (part !== '0') {
255               pushPart('');
256               pushPart(part);
257               state = 3;
258             }
259             break;
260           case 3:
261             pushPart(part);
262         }
263       }
264       if (state === 2) {
265         pushPart('');
266         pushPart('');
267       }
268       return compactStringParts.join(":");
269     };
270
271     IPv6.prototype.toByteArray = function() {
272       var bytes, part, _i, _len, _ref;
273       bytes = [];
274       _ref = this.parts;
275       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
276         part = _ref[_i];
277         bytes.push(part >> 8);
278         bytes.push(part & 0xff);
279       }
280       return bytes;
281     };
282
283     IPv6.prototype.toNormalizedString = function() {
284       var part;
285       return ((function() {
286         var _i, _len, _ref, _results;
287         _ref = this.parts;
288         _results = [];
289         for (_i = 0, _len = _ref.length; _i < _len; _i++) {
290           part = _ref[_i];
291           _results.push(part.toString(16));
292         }
293         return _results;
294       }).call(this)).join(":");
295     };
296
297     IPv6.prototype.match = function(other, cidrRange) {
298       var _ref;
299       if (cidrRange === void 0) {
300         _ref = other, other = _ref[0], cidrRange = _ref[1];
301       }
302       if (other.kind() !== 'ipv6') {
303         throw new Error("ipaddr: cannot match ipv6 address with non-ipv6 one");
304       }
305       return matchCIDR(this.parts, other.parts, 16, cidrRange);
306     };
307
308     IPv6.prototype.SpecialRanges = {
309       unspecified: [new IPv6([0, 0, 0, 0, 0, 0, 0, 0]), 128],
310       linkLocal: [new IPv6([0xfe80, 0, 0, 0, 0, 0, 0, 0]), 10],
311       multicast: [new IPv6([0xff00, 0, 0, 0, 0, 0, 0, 0]), 8],
312       loopback: [new IPv6([0, 0, 0, 0, 0, 0, 0, 1]), 128],
313       uniqueLocal: [new IPv6([0xfc00, 0, 0, 0, 0, 0, 0, 0]), 7],
314       ipv4Mapped: [new IPv6([0, 0, 0, 0, 0, 0xffff, 0, 0]), 96],
315       rfc6145: [new IPv6([0, 0, 0, 0, 0xffff, 0, 0, 0]), 96],
316       rfc6052: [new IPv6([0x64, 0xff9b, 0, 0, 0, 0, 0, 0]), 96],
317       '6to4': [new IPv6([0x2002, 0, 0, 0, 0, 0, 0, 0]), 16],
318       teredo: [new IPv6([0x2001, 0, 0, 0, 0, 0, 0, 0]), 32],
319       reserved: [[new IPv6([0x2001, 0xdb8, 0, 0, 0, 0, 0, 0]), 32]]
320     };
321
322     IPv6.prototype.range = function() {
323       return ipaddr.subnetMatch(this, this.SpecialRanges);
324     };
325
326     IPv6.prototype.isIPv4MappedAddress = function() {
327       return this.range() === 'ipv4Mapped';
328     };
329
330     IPv6.prototype.toIPv4Address = function() {
331       var high, low, _ref;
332       if (!this.isIPv4MappedAddress()) {
333         throw new Error("ipaddr: trying to convert a generic ipv6 address to ipv4");
334       }
335       _ref = this.parts.slice(-2), high = _ref[0], low = _ref[1];
336       return new ipaddr.IPv4([high >> 8, high & 0xff, low >> 8, low & 0xff]);
337     };
338
339     return IPv6;
340
341   })();
342
343   ipv6Part = "(?:[0-9a-f]+::?)+";
344
345   ipv6Regexes = {
346     "native": new RegExp("^(::)?(" + ipv6Part + ")?([0-9a-f]+)?(::)?$", 'i'),
347     transitional: new RegExp(("^((?:" + ipv6Part + ")|(?:::)(?:" + ipv6Part + ")?)") + ("" + ipv4Part + "\\." + ipv4Part + "\\." + ipv4Part + "\\." + ipv4Part + "$"), 'i')
348   };
349
350   expandIPv6 = function(string, parts) {
351     var colonCount, lastColon, part, replacement, replacementCount;
352     if (string.indexOf('::') !== string.lastIndexOf('::')) {
353       return null;
354     }
355     colonCount = 0;
356     lastColon = -1;
357     while ((lastColon = string.indexOf(':', lastColon + 1)) >= 0) {
358       colonCount++;
359     }
360     if (string.substr(0, 2) === '::') {
361       colonCount--;
362     }
363     if (string.substr(-2, 2) === '::') {
364       colonCount--;
365     }
366     if (colonCount > parts) {
367       return null;
368     }
369     replacementCount = parts - colonCount;
370     replacement = ':';
371     while (replacementCount--) {
372       replacement += '0:';
373     }
374     string = string.replace('::', replacement);
375     if (string[0] === ':') {
376       string = string.slice(1);
377     }
378     if (string[string.length - 1] === ':') {
379       string = string.slice(0, -1);
380     }
381     return (function() {
382       var _i, _len, _ref, _results;
383       _ref = string.split(":");
384       _results = [];
385       for (_i = 0, _len = _ref.length; _i < _len; _i++) {
386         part = _ref[_i];
387         _results.push(parseInt(part, 16));
388       }
389       return _results;
390     })();
391   };
392
393   ipaddr.IPv6.parser = function(string) {
394     var match, octet, octets, parts, _i, _len;
395     if (string.match(ipv6Regexes['native'])) {
396       return expandIPv6(string, 8);
397     } else if (match = string.match(ipv6Regexes['transitional'])) {
398       parts = expandIPv6(match[1].slice(0, -1), 6);
399       if (parts) {
400         octets = [parseInt(match[2]), parseInt(match[3]), parseInt(match[4]), parseInt(match[5])];
401         for (_i = 0, _len = octets.length; _i < _len; _i++) {
402           octet = octets[_i];
403           if (!((0 <= octet && octet <= 255))) {
404             return null;
405           }
406         }
407         parts.push(octets[0] << 8 | octets[1]);
408         parts.push(octets[2] << 8 | octets[3]);
409         return parts;
410       }
411     }
412     return null;
413   };
414
415   ipaddr.IPv4.isIPv4 = ipaddr.IPv6.isIPv6 = function(string) {
416     return this.parser(string) !== null;
417   };
418
419   ipaddr.IPv4.isValid = function(string) {
420     var e;
421     try {
422       new this(this.parser(string));
423       return true;
424     } catch (_error) {
425       e = _error;
426       return false;
427     }
428   };
429
430   ipaddr.IPv6.isValid = function(string) {
431     var e;
432     if (typeof string === "string" && string.indexOf(":") === -1) {
433       return false;
434     }
435     try {
436       new this(this.parser(string));
437       return true;
438     } catch (_error) {
439       e = _error;
440       return false;
441     }
442   };
443
444   ipaddr.IPv4.parse = ipaddr.IPv6.parse = function(string) {
445     var parts;
446     parts = this.parser(string);
447     if (parts === null) {
448       throw new Error("ipaddr: string is not formatted like ip address");
449     }
450     return new this(parts);
451   };
452
453   ipaddr.IPv4.parseCIDR = function(string) {
454     var maskLength, match;
455     if (match = string.match(/^(.+)\/(\d+)$/)) {
456       maskLength = parseInt(match[2]);
457       if (maskLength >= 0 && maskLength <= 32) {
458         return [this.parse(match[1]), maskLength];
459       }
460     }
461     throw new Error("ipaddr: string is not formatted like an IPv4 CIDR range");
462   };
463
464   ipaddr.IPv6.parseCIDR = function(string) {
465     var maskLength, match;
466     if (match = string.match(/^(.+)\/(\d+)$/)) {
467       maskLength = parseInt(match[2]);
468       if (maskLength >= 0 && maskLength <= 128) {
469         return [this.parse(match[1]), maskLength];
470       }
471     }
472     throw new Error("ipaddr: string is not formatted like an IPv6 CIDR range");
473   };
474
475   ipaddr.isValid = function(string) {
476     return ipaddr.IPv6.isValid(string) || ipaddr.IPv4.isValid(string);
477   };
478
479   ipaddr.parse = function(string) {
480     if (ipaddr.IPv6.isValid(string)) {
481       return ipaddr.IPv6.parse(string);
482     } else if (ipaddr.IPv4.isValid(string)) {
483       return ipaddr.IPv4.parse(string);
484     } else {
485       throw new Error("ipaddr: the address has neither IPv6 nor IPv4 format");
486     }
487   };
488
489   ipaddr.parseCIDR = function(string) {
490     var e;
491     try {
492       return ipaddr.IPv6.parseCIDR(string);
493     } catch (_error) {
494       e = _error;
495       try {
496         return ipaddr.IPv4.parseCIDR(string);
497       } catch (_error) {
498         e = _error;
499         throw new Error("ipaddr: the address has neither IPv6 nor IPv4 CIDR format");
500       }
501     }
502   };
503
504   ipaddr.fromByteArray = function(bytes) {
505     var length;
506     length = bytes.length;
507     if (length === 4) {
508       return new ipaddr.IPv4(bytes);
509     } else if (length === 16) {
510       return new ipaddr.IPv6(bytes);
511     } else {
512       throw new Error("ipaddr: the binary input is neither an IPv6 nor IPv4 address");
513     }
514   };
515
516   ipaddr.process = function(string) {
517     var addr;
518     addr = this.parse(string);
519     if (addr.kind() === 'ipv6' && addr.isIPv4MappedAddress()) {
520       return addr.toIPv4Address();
521     } else {
522       return addr;
523     }
524   };
525
526 }).call(this);