isURL.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = isURL;
  6. var _assertString = require('./util/assertString');
  7. var _assertString2 = _interopRequireDefault(_assertString);
  8. var _isFQDN = require('./isFQDN');
  9. var _isFQDN2 = _interopRequireDefault(_isFQDN);
  10. var _isIP = require('./isIP');
  11. var _isIP2 = _interopRequireDefault(_isIP);
  12. var _merge = require('./util/merge');
  13. var _merge2 = _interopRequireDefault(_merge);
  14. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  15. var default_url_options = {
  16. protocols: ['http', 'https', 'ftp'],
  17. require_tld: true,
  18. require_protocol: false,
  19. require_host: true,
  20. require_valid_protocol: true,
  21. allow_underscores: false,
  22. allow_trailing_dot: false,
  23. allow_protocol_relative_urls: false
  24. };
  25. var wrapped_ipv6 = /^\[([^\]]+)\](?::([0-9]+))?$/;
  26. function isRegExp(obj) {
  27. return Object.prototype.toString.call(obj) === '[object RegExp]';
  28. }
  29. function checkHost(host, matches) {
  30. for (var i = 0; i < matches.length; i++) {
  31. var match = matches[i];
  32. if (host === match || isRegExp(match) && match.test(host)) {
  33. return true;
  34. }
  35. }
  36. return false;
  37. }
  38. function isURL(url, options) {
  39. (0, _assertString2.default)(url);
  40. if (!url || url.length >= 2083 || /\s/.test(url)) {
  41. return false;
  42. }
  43. if (url.indexOf('mailto:') === 0) {
  44. return false;
  45. }
  46. options = (0, _merge2.default)(options, default_url_options);
  47. var protocol = void 0,
  48. auth = void 0,
  49. host = void 0,
  50. hostname = void 0,
  51. port = void 0,
  52. port_str = void 0,
  53. split = void 0,
  54. ipv6 = void 0;
  55. split = url.split('#');
  56. url = split.shift();
  57. split = url.split('?');
  58. url = split.shift();
  59. split = url.split('://');
  60. if (split.length > 1) {
  61. protocol = split.shift();
  62. if (options.require_valid_protocol && options.protocols.indexOf(protocol) === -1) {
  63. return false;
  64. }
  65. } else if (options.require_protocol) {
  66. return false;
  67. } else if (options.allow_protocol_relative_urls && url.substr(0, 2) === '//') {
  68. split[0] = url.substr(2);
  69. }
  70. url = split.join('://');
  71. split = url.split('/');
  72. url = split.shift();
  73. if (url === '' && !options.require_host) {
  74. return true;
  75. }
  76. split = url.split('@');
  77. if (split.length > 1) {
  78. auth = split.shift();
  79. if (auth.indexOf(':') >= 0 && auth.split(':').length > 2) {
  80. return false;
  81. }
  82. }
  83. hostname = split.join('@');
  84. port_str = ipv6 = null;
  85. var ipv6_match = hostname.match(wrapped_ipv6);
  86. if (ipv6_match) {
  87. host = '';
  88. ipv6 = ipv6_match[1];
  89. port_str = ipv6_match[2] || null;
  90. } else {
  91. split = hostname.split(':');
  92. host = split.shift();
  93. if (split.length) {
  94. port_str = split.join(':');
  95. }
  96. }
  97. if (port_str !== null) {
  98. port = parseInt(port_str, 10);
  99. if (!/^[0-9]+$/.test(port_str) || port <= 0 || port > 65535) {
  100. return false;
  101. }
  102. }
  103. if (!(0, _isIP2.default)(host) && !(0, _isFQDN2.default)(host, options) && (!ipv6 || !(0, _isIP2.default)(ipv6, 6)) && host !== 'localhost') {
  104. return false;
  105. }
  106. host = host || ipv6;
  107. if (options.host_whitelist && !checkHost(host, options.host_whitelist)) {
  108. return false;
  109. }
  110. if (options.host_blacklist && checkHost(host, options.host_blacklist)) {
  111. return false;
  112. }
  113. return true;
  114. }
  115. module.exports = exports['default'];