validate-domainset.js 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. // Surge Domain Set can not include root domain from public suffix list.
  2. const tldts = require('tldts');
  3. const picocolors = require('picocolors');
  4. const fs = require('fs');
  5. const path = require('path');
  6. const listDir = require('@sukka/listdir');
  7. const SPECIAL_SUFFIXES = new Set([
  8. 'linodeobjects.com', // only *.linodeobjects.com are public suffix
  9. 'vultrobjects.com', // only *.vultrobjects.com are public suffix
  10. 'dweb.link' // only *.dweb.link are public suffix
  11. ]);
  12. const validateDomainSet = async (filePath) => {
  13. const domainSetContent = await fs.promises.readFile(
  14. path.resolve(__dirname, '../List/domainset', filePath),
  15. { encoding: 'utf-8' }
  16. );
  17. const domainSetLines = domainSetContent.split('\n');
  18. for (let i = 0, len = domainSetLines.length; i < len; i++) {
  19. const line = domainSetLines[i];
  20. // starts with #
  21. if (line.charCodeAt(0) === 35) {
  22. continue;
  23. }
  24. if (line.trim().length === 0) {
  25. continue;
  26. }
  27. const domain = line.charCodeAt(0) === 46 ? line.slice(1) : line;
  28. const parsed = tldts.parse(domain, { allowPrivateDomains: true, detectIp: false });
  29. if (
  30. (
  31. parsed.isPrivate
  32. || parsed.isIcann
  33. ) && domain === parsed.publicSuffix
  34. ) {
  35. console.error(`[${filePath}]`, picocolors.yellow(domain), picocolors.red('is in public suffix list!'));
  36. }
  37. }
  38. };
  39. const validateRuleset = async (filePath) => {
  40. const rulesetContent = await fs.promises.readFile(
  41. path.resolve(__dirname, '../List/non_ip', filePath),
  42. { encoding: 'utf-8' }
  43. );
  44. const rulesetLines = rulesetContent.split('\n');
  45. console.log(`[${filePath}]`);
  46. for (let i = 0, len = rulesetLines.length; i < len; i++) {
  47. const line = rulesetLines[i];
  48. // starts with #
  49. if (line.charCodeAt(0) === 35) {
  50. continue;
  51. }
  52. if (line.trim().length === 0) {
  53. continue;
  54. }
  55. if (!line.startsWith('DOMAIN-SUFFIX,')) {
  56. continue;
  57. }
  58. const domain = line.slice(14);
  59. const parsed = tldts.parse(domain, { allowPrivateDomains: true, detectIp: false });
  60. if (domain !== parsed.publicSuffix) {
  61. if (!SPECIAL_SUFFIXES.has(domain)) {
  62. console.warn(picocolors.yellow(domain), picocolors.green('is not in public suffix list!'));
  63. }
  64. }
  65. }
  66. }
  67. (async () => {
  68. const [domainsetFiles, rulesetFiles] = await Promise.all([
  69. listDir(path.resolve(__dirname, '../List/domainset')),
  70. listDir(path.resolve(__dirname, '../List/non_ip'))
  71. ]);
  72. await Promise.all(
  73. domainsetFiles.map(file => validateDomainSet(file))
  74. );
  75. // await Promise.all(
  76. // rulesetFiles.map(file => validateRuleset(file))
  77. // );
  78. })();