UNPKG

mediawiki-title

Version:

Title normalization library for mediawiki

67 lines (60 loc) 3.66 kB
'use strict'; function substrCount(string, substr) { return string.split(substr).length - 1; } function strRepeat(string, number) { return new Array(number + 1).join(string); } /* eslint-disable-next-line max-len */ const IP_STRING_REGEX = /^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])$|^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?(?:\/(12[0-8]|1[01][0-9]|[1-9]?\d))?$/; /* eslint-disable-next-line max-len */ const IP_V4_STRING_REGEX = /^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])(?:\/(3[0-2]|[12]?\d))?$/; module.exports = function sanitizeIP(ip) { ip = ip.trim(); // If not an IP, just return trimmed value, since sanitizeIP() is called // in a number of contexts where usernames are supplied as input. if (!IP_STRING_REGEX.test(ip)) { return ip; } if (IP_V4_STRING_REGEX.test(ip)) { return ip.split('.') .map((block) => { const simplified = block.replace(/^0+/, ''); if (!simplified.length) { return '0'; } return simplified; }).join('.'); } ip = ip.toUpperCase(); // Expand zero abbreviations const abbrevPos = ip.indexOf('::'); if (abbrevPos !== -1) { // We know this is valid IPv6. Find the last index of the // address before any CIDR number (e.g. "a:b:c::/24"). const CIDRStart = ip.indexOf('/'); const addressEnd = CIDRStart !== -1 ? CIDRStart - 1 : ip.length - 1; let repeat; let extra; let pad; if (abbrevPos === 0) { // If the '::' is at the beginning... repeat = '0:'; extra = ip === '::' ? '0' : ''; // for the address '::' pad = 9; // 7+2 (due to '::') // If the '::' is at the end... } else if (abbrevPos === addressEnd - 1) { repeat = ':0'; extra = ''; pad = 9; // 7+2 (due to '::') // If the '::' is in the middle... } else { repeat = ':0'; extra = ':'; pad = 8; // 6+2 (due to '::') } ip = ip.replace(/::/g, strRepeat(repeat, pad - substrCount(ip, ':')) + extra); } // Remove leading zeros from each bloc as needed return ip.replace(/(^|:)0+([0-9A-Fa-f]{1,4})/g, '$1$2'); };