diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj
index 287c159c..468e4fe1 100644
--- a/src/common/common.vcxproj
+++ b/src/common/common.vcxproj
@@ -29,6 +29,7 @@
+
@@ -109,6 +110,7 @@
Header Files
+
+ Header Files
+
Header Files
diff --git a/src/common/gen-public-suffix.py b/src/common/gen-public-suffix.py
new file mode 100644
index 00000000..4ccdd289
--- /dev/null
+++ b/src/common/gen-public-suffix.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python3
+import sys
+import urllib.request
+from pathlib import Path
+
+URL = "https://raw.githubusercontent.com/publicsuffix/list/main/public_suffix_list.dat"
+
+
+def parse_rules(text: str):
+ rules = []
+ for raw in text.splitlines():
+ line = raw.strip()
+ if not line or line.startswith("//"):
+ continue
+ if " " in line or "\t" in line:
+ line = line.split()[0]
+ rules.append(line.lower())
+ return sorted(set(rules))
+
+
+def emit_header(path: str, rules):
+ with open(path, "w", encoding="utf-8", newline="\n") as out:
+ out.write("#pragma once\n")
+ out.write("static const char * const public_suffix_rules[] = {\n")
+ for rule in rules:
+ escaped = rule.replace("\\", "\\\\").replace('"', '\\"')
+ out.write(f'\t"{escaped}",\n')
+ out.write("};\n")
+ out.write(
+ "static const unsigned int public_suffix_rules_len = sizeof(public_suffix_rules) / sizeof(public_suffix_rules[0]);\n"
+ )
+
+
+def main():
+ if len(sys.argv) != 2:
+ raise SystemExit("usage: gen-public-suffix.py