Commit Diff


commit - d3b38006cdb9ff7869f844c6b98f7c6073573df6
commit + 09207408944007a2a81689e5867f31d10cdd3a1f
blob - d91574e8e0019a70ac88025c8d8eef9578882639
blob + 6245796cd9c80ce1087f093ac83a7edf902fc8c1
--- src/build.zig
+++ src/build.zig
@@ -32,7 +32,7 @@ pub fn build(b: *std.Build) void {
     const optimize = b.standardOptimizeOption(.{});
 
     const fence_mod = b.createModule(.{
-        .root_source_file = b.path("fence/src/root.zig"),
+        .root_source_file = b.path("fence/root.zig"),
         .target = target,
     });
     const fence = b.addLibrary(.{
@@ -41,7 +41,7 @@ pub fn build(b: *std.Build) void {
     });
     // https://github.com/ziglang/zig/issues/6817
     fence.bundle_compiler_rt = true;
-    const header_file = b.addInstallHeaderFile(b.path("fence/src/fence.h"), "fence.h");
+    const header_file = b.addInstallHeaderFile(b.path("fence/fence.h"), "fence.h");
     b.getInstallStep().dependOn(&header_file.step);
 
     const extlibs = [_][]const u8{
blob - 90683e5ab7dcdb5e61181c4bed770396903c0058 (mode 644)
blob + /dev/null
--- src/fence/src/fence.h
+++ /dev/null
@@ -1,3 +0,0 @@
-char fence_is_top_level_domain(char *domain);
-int quote_depth(char *line);
-size_t fence_copy_after_line(char *dst, char *src, char *line);
blob - 3db3c90ce76ac72f363922645c8e805460932a7c (mode 644)
blob + /dev/null
--- src/fence/src/root.zig
+++ /dev/null
@@ -1,102 +0,0 @@
-const std = @import("std");
-const tlds = @import("tlds.zig");
-const testing = std.testing;
-
-export fn fence_is_top_level_domain(dom: [*:0]const u8) bool {
-    return isTopLevelDomain(std.mem.span(dom));
-}
-
-fn isTopLevelDomain(dom: []const u8) bool {
-    for (tlds.tab) |tld| {
-        if (std.mem.eql(u8, dom, tld)) return true;
-    }
-    return false;
-}
-
-fn isRfc822Char(c: u8) bool {
-    if (!std.ascii.isAscii(c)) return false;
-    switch (c) {
-        0...32, 127 => return false,
-        '(', ')', ',', ';', '<', '>', '"' => return false,
-    }
-    return true;
-}
-
-fn quoteDepth(line: []const u8) u8 {
-    const ln = std.mem.trim(u8, line, &std.ascii.whitespace);
-    const first = std.mem.indexOfScalar(u8, ln, '>') orelse return 0;
-    if (first != 0) return 0;
-
-    var depth: u8 = 0;
-    const last = std.mem.lastIndexOfScalar(u8, ln, '>') orelse return 1;
-    for (line[first .. last + 1]) |c| {
-        if (c == '>') {
-            if (depth == 0xff) return depth;
-            depth += 1;
-            continue;
-        }
-        if (std.ascii.isWhitespace(c)) continue;
-        break;
-    }
-    return depth;
-}
-
-export fn quote_depth(line: [*:0]const u8) c_int {
-    const n = quoteDepth(std.mem.span(line));
-    return @as(c_int, n);
-}
-
-fn copyAfterLine(dst: std.fs.File, src: std.fs.File, key: []const u8) !usize {
-    var buf: [8192]u8 = undefined;
-    var rd = std.io.bufferedReader(src.reader());
-    var r = rd.reader();
-    var wr = std.io.bufferedWriter(dst.writer());
-    var w = wr.writer();
-    var found = false;
-    var n: usize = 0;
-    while (try r.readUntilDelimiterOrEof(buf[0..], '\n')) |line| {
-        if (std.mem.startsWith(u8, line, key)) {
-            found = true;
-            continue;
-        }
-        if (!found) continue;
-        try w.print("{s}\n", .{line});
-        n += (line.len + 1); // + 1 for newline
-    }
-    try wr.flush();
-    return n;
-}
-
-export fn fence_copy_after_line(dst: [*:0]const u8, src: [*:0]const u8, line: [*:0]const u8) usize {
-    const fdst = std.fs.cwd().createFile(std.mem.span(dst), .{}) catch return 0;
-    defer fdst.close();
-    const fsrc = std.fs.cwd().openFile(std.mem.span(src), .{}) catch return 0;
-    defer fsrc.close();
-    return copyAfterLine(fdst, fsrc, std.mem.span(line)) catch 0;
-}
-
-test "quote depth" {
-    const tests = [_]struct { []const u8, u8 }{
-        .{ ">>> hello", 3 },
-        .{ ">    >> hello", 3 },
-        .{ "     > hello >", 1 },
-        .{ "hello>>", 0 },
-        .{ ">> hello >>", 2 },
-        .{ ">  \t> hello", 2 },
-        .{ ">", 1 },
-        .{ "xxx > hello >>", 0 },
-    };
-    for (tests) |t| {
-        const got = quoteDepth(t[0]);
-        errdefer std.debug.print("quote depth for \"{s}\"\n", .{t[0]});
-        try testing.expectEqual(t[1], got);
-    }
-}
-
-test "check domains" {
-    try testing.expect(isTopLevelDomain("com"));
-    try testing.expect(isTopLevelDomain("69yamum") == false);
-
-    const str = [_:0]u8{ 'c', 'o', 'm', 0 };
-    try testing.expect(fence_is_top_level_domain(str[0..]));
-}
blob - 0fb29f6d90ff4d12beca7d1d83efc7e31eb99adf (mode 644)
blob + /dev/null
--- src/fence/src/tlds.zig
+++ /dev/null
@@ -1,1443 +0,0 @@
-// curl https://data.iana.org/TLD/tlds-alpha-by-domain.txt | grep -v '^#' | tr A-Z a-z > tlds.zig
-pub const tab = [_][]const u8{
-    "aaa",
-    "aarp",
-    "abb",
-    "abbott",
-    "abbvie",
-    "abc",
-    "able",
-    "abogado",
-    "abudhabi",
-    "ac",
-    "academy",
-    "accenture",
-    "accountant",
-    "accountants",
-    "aco",
-    "actor",
-    "ad",
-    "ads",
-    "adult",
-    "ae",
-    "aeg",
-    "aero",
-    "aetna",
-    "af",
-    "afl",
-    "africa",
-    "ag",
-    "agakhan",
-    "agency",
-    "ai",
-    "aig",
-    "airbus",
-    "airforce",
-    "airtel",
-    "akdn",
-    "al",
-    "alibaba",
-    "alipay",
-    "allfinanz",
-    "allstate",
-    "ally",
-    "alsace",
-    "alstom",
-    "am",
-    "amazon",
-    "americanexpress",
-    "americanfamily",
-    "amex",
-    "amfam",
-    "amica",
-    "amsterdam",
-    "analytics",
-    "android",
-    "anquan",
-    "anz",
-    "ao",
-    "aol",
-    "apartments",
-    "app",
-    "apple",
-    "aq",
-    "aquarelle",
-    "ar",
-    "arab",
-    "aramco",
-    "archi",
-    "army",
-    "arpa",
-    "art",
-    "arte",
-    "as",
-    "asda",
-    "asia",
-    "associates",
-    "at",
-    "athleta",
-    "attorney",
-    "au",
-    "auction",
-    "audi",
-    "audible",
-    "audio",
-    "auspost",
-    "author",
-    "auto",
-    "autos",
-    "aw",
-    "aws",
-    "ax",
-    "axa",
-    "az",
-    "azure",
-    "ba",
-    "baby",
-    "baidu",
-    "banamex",
-    "band",
-    "bank",
-    "bar",
-    "barcelona",
-    "barclaycard",
-    "barclays",
-    "barefoot",
-    "bargains",
-    "baseball",
-    "basketball",
-    "bauhaus",
-    "bayern",
-    "bb",
-    "bbc",
-    "bbt",
-    "bbva",
-    "bcg",
-    "bcn",
-    "bd",
-    "be",
-    "beats",
-    "beauty",
-    "beer",
-    "berlin",
-    "best",
-    "bestbuy",
-    "bet",
-    "bf",
-    "bg",
-    "bh",
-    "bharti",
-    "bi",
-    "bible",
-    "bid",
-    "bike",
-    "bing",
-    "bingo",
-    "bio",
-    "biz",
-    "bj",
-    "black",
-    "blackfriday",
-    "blockbuster",
-    "blog",
-    "bloomberg",
-    "blue",
-    "bm",
-    "bms",
-    "bmw",
-    "bn",
-    "bnpparibas",
-    "bo",
-    "boats",
-    "boehringer",
-    "bofa",
-    "bom",
-    "bond",
-    "boo",
-    "book",
-    "booking",
-    "bosch",
-    "bostik",
-    "boston",
-    "bot",
-    "boutique",
-    "box",
-    "br",
-    "bradesco",
-    "bridgestone",
-    "broadway",
-    "broker",
-    "brother",
-    "brussels",
-    "bs",
-    "bt",
-    "build",
-    "builders",
-    "business",
-    "buy",
-    "buzz",
-    "bv",
-    "bw",
-    "by",
-    "bz",
-    "bzh",
-    "ca",
-    "cab",
-    "cafe",
-    "cal",
-    "call",
-    "calvinklein",
-    "cam",
-    "camera",
-    "camp",
-    "canon",
-    "capetown",
-    "capital",
-    "capitalone",
-    "car",
-    "caravan",
-    "cards",
-    "care",
-    "career",
-    "careers",
-    "cars",
-    "casa",
-    "case",
-    "cash",
-    "casino",
-    "cat",
-    "catering",
-    "catholic",
-    "cba",
-    "cbn",
-    "cbre",
-    "cc",
-    "cd",
-    "center",
-    "ceo",
-    "cern",
-    "cf",
-    "cfa",
-    "cfd",
-    "cg",
-    "ch",
-    "chanel",
-    "channel",
-    "charity",
-    "chase",
-    "chat",
-    "cheap",
-    "chintai",
-    "christmas",
-    "chrome",
-    "church",
-    "ci",
-    "cipriani",
-    "circle",
-    "cisco",
-    "citadel",
-    "citi",
-    "citic",
-    "city",
-    "ck",
-    "cl",
-    "claims",
-    "cleaning",
-    "click",
-    "clinic",
-    "clinique",
-    "clothing",
-    "cloud",
-    "club",
-    "clubmed",
-    "cm",
-    "cn",
-    "co",
-    "coach",
-    "codes",
-    "coffee",
-    "college",
-    "cologne",
-    "com",
-    "commbank",
-    "community",
-    "company",
-    "compare",
-    "computer",
-    "comsec",
-    "condos",
-    "construction",
-    "consulting",
-    "contact",
-    "contractors",
-    "cooking",
-    "cool",
-    "coop",
-    "corsica",
-    "country",
-    "coupon",
-    "coupons",
-    "courses",
-    "cpa",
-    "cr",
-    "credit",
-    "creditcard",
-    "creditunion",
-    "cricket",
-    "crown",
-    "crs",
-    "cruise",
-    "cruises",
-    "cu",
-    "cuisinella",
-    "cv",
-    "cw",
-    "cx",
-    "cy",
-    "cymru",
-    "cyou",
-    "cz",
-    "dad",
-    "dance",
-    "data",
-    "date",
-    "dating",
-    "datsun",
-    "day",
-    "dclk",
-    "dds",
-    "de",
-    "deal",
-    "dealer",
-    "deals",
-    "degree",
-    "delivery",
-    "dell",
-    "deloitte",
-    "delta",
-    "democrat",
-    "dental",
-    "dentist",
-    "desi",
-    "design",
-    "dev",
-    "dhl",
-    "diamonds",
-    "diet",
-    "digital",
-    "direct",
-    "directory",
-    "discount",
-    "discover",
-    "dish",
-    "diy",
-    "dj",
-    "dk",
-    "dm",
-    "dnp",
-    "do",
-    "docs",
-    "doctor",
-    "dog",
-    "domains",
-    "dot",
-    "download",
-    "drive",
-    "dtv",
-    "dubai",
-    "dunlop",
-    "dupont",
-    "durban",
-    "dvag",
-    "dvr",
-    "dz",
-    "earth",
-    "eat",
-    "ec",
-    "eco",
-    "edeka",
-    "edu",
-    "education",
-    "ee",
-    "eg",
-    "email",
-    "emerck",
-    "energy",
-    "engineer",
-    "engineering",
-    "enterprises",
-    "epson",
-    "equipment",
-    "er",
-    "ericsson",
-    "erni",
-    "es",
-    "esq",
-    "estate",
-    "et",
-    "eu",
-    "eurovision",
-    "eus",
-    "events",
-    "exchange",
-    "expert",
-    "exposed",
-    "express",
-    "extraspace",
-    "fage",
-    "fail",
-    "fairwinds",
-    "faith",
-    "family",
-    "fan",
-    "fans",
-    "farm",
-    "farmers",
-    "fashion",
-    "fast",
-    "fedex",
-    "feedback",
-    "ferrari",
-    "ferrero",
-    "fi",
-    "fidelity",
-    "fido",
-    "film",
-    "final",
-    "finance",
-    "financial",
-    "fire",
-    "firestone",
-    "firmdale",
-    "fish",
-    "fishing",
-    "fit",
-    "fitness",
-    "fj",
-    "fk",
-    "flickr",
-    "flights",
-    "flir",
-    "florist",
-    "flowers",
-    "fly",
-    "fm",
-    "fo",
-    "foo",
-    "food",
-    "football",
-    "ford",
-    "forex",
-    "forsale",
-    "forum",
-    "foundation",
-    "fox",
-    "fr",
-    "free",
-    "fresenius",
-    "frl",
-    "frogans",
-    "frontier",
-    "ftr",
-    "fujitsu",
-    "fun",
-    "fund",
-    "furniture",
-    "futbol",
-    "fyi",
-    "ga",
-    "gal",
-    "gallery",
-    "gallo",
-    "gallup",
-    "game",
-    "games",
-    "gap",
-    "garden",
-    "gay",
-    "gb",
-    "gbiz",
-    "gd",
-    "gdn",
-    "ge",
-    "gea",
-    "gent",
-    "genting",
-    "george",
-    "gf",
-    "gg",
-    "ggee",
-    "gh",
-    "gi",
-    "gift",
-    "gifts",
-    "gives",
-    "giving",
-    "gl",
-    "glass",
-    "gle",
-    "global",
-    "globo",
-    "gm",
-    "gmail",
-    "gmbh",
-    "gmo",
-    "gmx",
-    "gn",
-    "godaddy",
-    "gold",
-    "goldpoint",
-    "golf",
-    "goo",
-    "goodyear",
-    "goog",
-    "google",
-    "gop",
-    "got",
-    "gov",
-    "gp",
-    "gq",
-    "gr",
-    "grainger",
-    "graphics",
-    "gratis",
-    "green",
-    "gripe",
-    "grocery",
-    "group",
-    "gs",
-    "gt",
-    "gu",
-    "gucci",
-    "guge",
-    "guide",
-    "guitars",
-    "guru",
-    "gw",
-    "gy",
-    "hair",
-    "hamburg",
-    "hangout",
-    "haus",
-    "hbo",
-    "hdfc",
-    "hdfcbank",
-    "health",
-    "healthcare",
-    "help",
-    "helsinki",
-    "here",
-    "hermes",
-    "hiphop",
-    "hisamitsu",
-    "hitachi",
-    "hiv",
-    "hk",
-    "hkt",
-    "hm",
-    "hn",
-    "hockey",
-    "holdings",
-    "holiday",
-    "homedepot",
-    "homegoods",
-    "homes",
-    "homesense",
-    "honda",
-    "horse",
-    "hospital",
-    "host",
-    "hosting",
-    "hot",
-    "hotels",
-    "hotmail",
-    "house",
-    "how",
-    "hr",
-    "hsbc",
-    "ht",
-    "hu",
-    "hughes",
-    "hyatt",
-    "hyundai",
-    "ibm",
-    "icbc",
-    "ice",
-    "icu",
-    "id",
-    "ie",
-    "ieee",
-    "ifm",
-    "ikano",
-    "il",
-    "im",
-    "imamat",
-    "imdb",
-    "immo",
-    "immobilien",
-    "in",
-    "inc",
-    "industries",
-    "infiniti",
-    "info",
-    "ing",
-    "ink",
-    "institute",
-    "insurance",
-    "insure",
-    "int",
-    "international",
-    "intuit",
-    "investments",
-    "io",
-    "ipiranga",
-    "iq",
-    "ir",
-    "irish",
-    "is",
-    "ismaili",
-    "ist",
-    "istanbul",
-    "it",
-    "itau",
-    "itv",
-    "jaguar",
-    "java",
-    "jcb",
-    "je",
-    "jeep",
-    "jetzt",
-    "jewelry",
-    "jio",
-    "jll",
-    "jm",
-    "jmp",
-    "jnj",
-    "jo",
-    "jobs",
-    "joburg",
-    "jot",
-    "joy",
-    "jp",
-    "jpmorgan",
-    "jprs",
-    "juegos",
-    "juniper",
-    "kaufen",
-    "kddi",
-    "ke",
-    "kerryhotels",
-    "kerryproperties",
-    "kfh",
-    "kg",
-    "kh",
-    "ki",
-    "kia",
-    "kids",
-    "kim",
-    "kindle",
-    "kitchen",
-    "kiwi",
-    "km",
-    "kn",
-    "koeln",
-    "komatsu",
-    "kosher",
-    "kp",
-    "kpmg",
-    "kpn",
-    "kr",
-    "krd",
-    "kred",
-    "kuokgroup",
-    "kw",
-    "ky",
-    "kyoto",
-    "kz",
-    "la",
-    "lacaixa",
-    "lamborghini",
-    "lamer",
-    "land",
-    "landrover",
-    "lanxess",
-    "lasalle",
-    "lat",
-    "latino",
-    "latrobe",
-    "law",
-    "lawyer",
-    "lb",
-    "lc",
-    "lds",
-    "lease",
-    "leclerc",
-    "lefrak",
-    "legal",
-    "lego",
-    "lexus",
-    "lgbt",
-    "li",
-    "lidl",
-    "life",
-    "lifeinsurance",
-    "lifestyle",
-    "lighting",
-    "like",
-    "lilly",
-    "limited",
-    "limo",
-    "lincoln",
-    "link",
-    "live",
-    "living",
-    "lk",
-    "llc",
-    "llp",
-    "loan",
-    "loans",
-    "locker",
-    "locus",
-    "lol",
-    "london",
-    "lotte",
-    "lotto",
-    "love",
-    "lpl",
-    "lplfinancial",
-    "lr",
-    "ls",
-    "lt",
-    "ltd",
-    "ltda",
-    "lu",
-    "lundbeck",
-    "luxe",
-    "luxury",
-    "lv",
-    "ly",
-    "ma",
-    "madrid",
-    "maif",
-    "maison",
-    "makeup",
-    "man",
-    "management",
-    "mango",
-    "map",
-    "market",
-    "marketing",
-    "markets",
-    "marriott",
-    "marshalls",
-    "mattel",
-    "mba",
-    "mc",
-    "mckinsey",
-    "md",
-    "me",
-    "med",
-    "media",
-    "meet",
-    "melbourne",
-    "meme",
-    "memorial",
-    "men",
-    "menu",
-    "merckmsd",
-    "mg",
-    "mh",
-    "miami",
-    "microsoft",
-    "mil",
-    "mini",
-    "mint",
-    "mit",
-    "mitsubishi",
-    "mk",
-    "ml",
-    "mlb",
-    "mls",
-    "mm",
-    "mma",
-    "mn",
-    "mo",
-    "mobi",
-    "mobile",
-    "moda",
-    "moe",
-    "moi",
-    "mom",
-    "monash",
-    "money",
-    "monster",
-    "mormon",
-    "mortgage",
-    "moscow",
-    "moto",
-    "motorcycles",
-    "mov",
-    "movie",
-    "mp",
-    "mq",
-    "mr",
-    "ms",
-    "msd",
-    "mt",
-    "mtn",
-    "mtr",
-    "mu",
-    "museum",
-    "music",
-    "mv",
-    "mw",
-    "mx",
-    "my",
-    "mz",
-    "na",
-    "nab",
-    "nagoya",
-    "name",
-    "navy",
-    "nba",
-    "nc",
-    "ne",
-    "nec",
-    "net",
-    "netbank",
-    "netflix",
-    "network",
-    "neustar",
-    "new",
-    "news",
-    "next",
-    "nextdirect",
-    "nexus",
-    "nf",
-    "nfl",
-    "ng",
-    "ngo",
-    "nhk",
-    "ni",
-    "nico",
-    "nike",
-    "nikon",
-    "ninja",
-    "nissan",
-    "nissay",
-    "nl",
-    "no",
-    "nokia",
-    "norton",
-    "now",
-    "nowruz",
-    "nowtv",
-    "np",
-    "nr",
-    "nra",
-    "nrw",
-    "ntt",
-    "nu",
-    "nyc",
-    "nz",
-    "obi",
-    "observer",
-    "office",
-    "okinawa",
-    "olayan",
-    "olayangroup",
-    "ollo",
-    "om",
-    "omega",
-    "one",
-    "ong",
-    "onl",
-    "online",
-    "ooo",
-    "open",
-    "oracle",
-    "orange",
-    "org",
-    "organic",
-    "origins",
-    "osaka",
-    "otsuka",
-    "ott",
-    "ovh",
-    "pa",
-    "page",
-    "panasonic",
-    "paris",
-    "pars",
-    "partners",
-    "parts",
-    "party",
-    "pay",
-    "pccw",
-    "pe",
-    "pet",
-    "pf",
-    "pfizer",
-    "pg",
-    "ph",
-    "pharmacy",
-    "phd",
-    "philips",
-    "phone",
-    "photo",
-    "photography",
-    "photos",
-    "physio",
-    "pics",
-    "pictet",
-    "pictures",
-    "pid",
-    "pin",
-    "ping",
-    "pink",
-    "pioneer",
-    "pizza",
-    "pk",
-    "pl",
-    "place",
-    "play",
-    "playstation",
-    "plumbing",
-    "plus",
-    "pm",
-    "pn",
-    "pnc",
-    "pohl",
-    "poker",
-    "politie",
-    "porn",
-    "post",
-    "pr",
-    "praxi",
-    "press",
-    "prime",
-    "pro",
-    "prod",
-    "productions",
-    "prof",
-    "progressive",
-    "promo",
-    "properties",
-    "property",
-    "protection",
-    "pru",
-    "prudential",
-    "ps",
-    "pt",
-    "pub",
-    "pw",
-    "pwc",
-    "py",
-    "qa",
-    "qpon",
-    "quebec",
-    "quest",
-    "racing",
-    "radio",
-    "re",
-    "read",
-    "realestate",
-    "realtor",
-    "realty",
-    "recipes",
-    "red",
-    "redstone",
-    "redumbrella",
-    "rehab",
-    "reise",
-    "reisen",
-    "reit",
-    "reliance",
-    "ren",
-    "rent",
-    "rentals",
-    "repair",
-    "report",
-    "republican",
-    "rest",
-    "restaurant",
-    "review",
-    "reviews",
-    "rexroth",
-    "rich",
-    "richardli",
-    "ricoh",
-    "ril",
-    "rio",
-    "rip",
-    "ro",
-    "rocks",
-    "rodeo",
-    "rogers",
-    "room",
-    "rs",
-    "rsvp",
-    "ru",
-    "rugby",
-    "ruhr",
-    "run",
-    "rw",
-    "rwe",
-    "ryukyu",
-    "sa",
-    "saarland",
-    "safe",
-    "safety",
-    "sakura",
-    "sale",
-    "salon",
-    "samsclub",
-    "samsung",
-    "sandvik",
-    "sandvikcoromant",
-    "sanofi",
-    "sap",
-    "sarl",
-    "sas",
-    "save",
-    "saxo",
-    "sb",
-    "sbi",
-    "sbs",
-    "sc",
-    "scb",
-    "schaeffler",
-    "schmidt",
-    "scholarships",
-    "school",
-    "schule",
-    "schwarz",
-    "science",
-    "scot",
-    "sd",
-    "se",
-    "search",
-    "seat",
-    "secure",
-    "security",
-    "seek",
-    "select",
-    "sener",
-    "services",
-    "seven",
-    "sew",
-    "sex",
-    "sexy",
-    "sfr",
-    "sg",
-    "sh",
-    "shangrila",
-    "sharp",
-    "shell",
-    "shia",
-    "shiksha",
-    "shoes",
-    "shop",
-    "shopping",
-    "shouji",
-    "show",
-    "si",
-    "silk",
-    "sina",
-    "singles",
-    "site",
-    "sj",
-    "sk",
-    "ski",
-    "skin",
-    "sky",
-    "skype",
-    "sl",
-    "sling",
-    "sm",
-    "smart",
-    "smile",
-    "sn",
-    "sncf",
-    "so",
-    "soccer",
-    "social",
-    "softbank",
-    "software",
-    "sohu",
-    "solar",
-    "solutions",
-    "song",
-    "sony",
-    "soy",
-    "spa",
-    "space",
-    "sport",
-    "spot",
-    "sr",
-    "srl",
-    "ss",
-    "st",
-    "stada",
-    "staples",
-    "star",
-    "statebank",
-    "statefarm",
-    "stc",
-    "stcgroup",
-    "stockholm",
-    "storage",
-    "store",
-    "stream",
-    "studio",
-    "study",
-    "style",
-    "su",
-    "sucks",
-    "supplies",
-    "supply",
-    "support",
-    "surf",
-    "surgery",
-    "suzuki",
-    "sv",
-    "swatch",
-    "swiss",
-    "sx",
-    "sy",
-    "sydney",
-    "systems",
-    "sz",
-    "tab",
-    "taipei",
-    "talk",
-    "taobao",
-    "target",
-    "tatamotors",
-    "tatar",
-    "tattoo",
-    "tax",
-    "taxi",
-    "tc",
-    "tci",
-    "td",
-    "tdk",
-    "team",
-    "tech",
-    "technology",
-    "tel",
-    "temasek",
-    "tennis",
-    "teva",
-    "tf",
-    "tg",
-    "th",
-    "thd",
-    "theater",
-    "theatre",
-    "tiaa",
-    "tickets",
-    "tienda",
-    "tips",
-    "tires",
-    "tirol",
-    "tj",
-    "tjmaxx",
-    "tjx",
-    "tk",
-    "tkmaxx",
-    "tl",
-    "tm",
-    "tmall",
-    "tn",
-    "to",
-    "today",
-    "tokyo",
-    "tools",
-    "top",
-    "toray",
-    "toshiba",
-    "total",
-    "tours",
-    "town",
-    "toyota",
-    "toys",
-    "tr",
-    "trade",
-    "trading",
-    "training",
-    "travel",
-    "travelers",
-    "travelersinsurance",
-    "trust",
-    "trv",
-    "tt",
-    "tube",
-    "tui",
-    "tunes",
-    "tushu",
-    "tv",
-    "tvs",
-    "tw",
-    "tz",
-    "ua",
-    "ubank",
-    "ubs",
-    "ug",
-    "uk",
-    "unicom",
-    "university",
-    "uno",
-    "uol",
-    "ups",
-    "us",
-    "uy",
-    "uz",
-    "va",
-    "vacations",
-    "vana",
-    "vanguard",
-    "vc",
-    "ve",
-    "vegas",
-    "ventures",
-    "verisign",
-    "versicherung",
-    "vet",
-    "vg",
-    "vi",
-    "viajes",
-    "video",
-    "vig",
-    "viking",
-    "villas",
-    "vin",
-    "vip",
-    "virgin",
-    "visa",
-    "vision",
-    "viva",
-    "vivo",
-    "vlaanderen",
-    "vn",
-    "vodka",
-    "volvo",
-    "vote",
-    "voting",
-    "voto",
-    "voyage",
-    "vu",
-    "wales",
-    "walmart",
-    "walter",
-    "wang",
-    "wanggou",
-    "watch",
-    "watches",
-    "weather",
-    "weatherchannel",
-    "webcam",
-    "weber",
-    "website",
-    "wed",
-    "wedding",
-    "weibo",
-    "weir",
-    "wf",
-    "whoswho",
-    "wien",
-    "wiki",
-    "williamhill",
-    "win",
-    "windows",
-    "wine",
-    "winners",
-    "wme",
-    "wolterskluwer",
-    "woodside",
-    "work",
-    "works",
-    "world",
-    "wow",
-    "ws",
-    "wtc",
-    "wtf",
-    "xbox",
-    "xerox",
-    "xihuan",
-    "xin",
-    "xn--11b4c3d",
-    "xn--1ck2e1b",
-    "xn--1qqw23a",
-    "xn--2scrj9c",
-    "xn--30rr7y",
-    "xn--3bst00m",
-    "xn--3ds443g",
-    "xn--3e0b707e",
-    "xn--3hcrj9c",
-    "xn--3pxu8k",
-    "xn--42c2d9a",
-    "xn--45br5cyl",
-    "xn--45brj9c",
-    "xn--45q11c",
-    "xn--4dbrk0ce",
-    "xn--4gbrim",
-    "xn--54b7fta0cc",
-    "xn--55qw42g",
-    "xn--55qx5d",
-    "xn--5su34j936bgsg",
-    "xn--5tzm5g",
-    "xn--6frz82g",
-    "xn--6qq986b3xl",
-    "xn--80adxhks",
-    "xn--80ao21a",
-    "xn--80aqecdr1a",
-    "xn--80asehdb",
-    "xn--80aswg",
-    "xn--8y0a063a",
-    "xn--90a3ac",
-    "xn--90ae",
-    "xn--90ais",
-    "xn--9dbq2a",
-    "xn--9et52u",
-    "xn--9krt00a",
-    "xn--b4w605ferd",
-    "xn--bck1b9a5dre4c",
-    "xn--c1avg",
-    "xn--c2br7g",
-    "xn--cck2b3b",
-    "xn--cckwcxetd",
-    "xn--cg4bki",
-    "xn--clchc0ea0b2g2a9gcd",
-    "xn--czr694b",
-    "xn--czrs0t",
-    "xn--czru2d",
-    "xn--d1acj3b",
-    "xn--d1alf",
-    "xn--e1a4c",
-    "xn--eckvdtc9d",
-    "xn--efvy88h",
-    "xn--fct429k",
-    "xn--fhbei",
-    "xn--fiq228c5hs",
-    "xn--fiq64b",
-    "xn--fiqs8s",
-    "xn--fiqz9s",
-    "xn--fjq720a",
-    "xn--flw351e",
-    "xn--fpcrj9c3d",
-    "xn--fzc2c9e2c",
-    "xn--fzys8d69uvgm",
-    "xn--g2xx48c",
-    "xn--gckr3f0f",
-    "xn--gecrj9c",
-    "xn--gk3at1e",
-    "xn--h2breg3eve",
-    "xn--h2brj9c",
-    "xn--h2brj9c8c",
-    "xn--hxt814e",
-    "xn--i1b6b1a6a2e",
-    "xn--imr513n",
-    "xn--io0a7i",
-    "xn--j1aef",
-    "xn--j1amh",
-    "xn--j6w193g",
-    "xn--jlq480n2rg",
-    "xn--jvr189m",
-    "xn--kcrx77d1x4a",
-    "xn--kprw13d",
-    "xn--kpry57d",
-    "xn--kput3i",
-    "xn--l1acc",
-    "xn--lgbbat1ad8j",
-    "xn--mgb9awbf",
-    "xn--mgba3a3ejt",
-    "xn--mgba3a4f16a",
-    "xn--mgba7c0bbn0a",
-    "xn--mgbaam7a8h",
-    "xn--mgbab2bd",
-    "xn--mgbah1a3hjkrd",
-    "xn--mgbai9azgqp6j",
-    "xn--mgbayh7gpa",
-    "xn--mgbbh1a",
-    "xn--mgbbh1a71e",
-    "xn--mgbc0a9azcg",
-    "xn--mgbca7dzdo",
-    "xn--mgbcpq6gpa1a",
-    "xn--mgberp4a5d4ar",
-    "xn--mgbgu82a",
-    "xn--mgbi4ecexp",
-    "xn--mgbpl2fh",
-    "xn--mgbt3dhd",
-    "xn--mgbtx2b",
-    "xn--mgbx4cd0ab",
-    "xn--mix891f",
-    "xn--mk1bu44c",
-    "xn--mxtq1m",
-    "xn--ngbc5azd",
-    "xn--ngbe9e0a",
-    "xn--ngbrx",
-    "xn--node",
-    "xn--nqv7f",
-    "xn--nqv7fs00ema",
-    "xn--nyqy26a",
-    "xn--o3cw4h",
-    "xn--ogbpf8fl",
-    "xn--otu796d",
-    "xn--p1acf",
-    "xn--p1ai",
-    "xn--pgbs0dh",
-    "xn--pssy2u",
-    "xn--q7ce6a",
-    "xn--q9jyb4c",
-    "xn--qcka1pmc",
-    "xn--qxa6a",
-    "xn--qxam",
-    "xn--rhqv96g",
-    "xn--rovu88b",
-    "xn--rvc1e0am3e",
-    "xn--s9brj9c",
-    "xn--ses554g",
-    "xn--t60b56a",
-    "xn--tckwe",
-    "xn--tiq49xqyj",
-    "xn--unup4y",
-    "xn--vermgensberater-ctb",
-    "xn--vermgensberatung-pwb",
-    "xn--vhquv",
-    "xn--vuq861b",
-    "xn--w4r85el8fhu5dnra",
-    "xn--w4rs40l",
-    "xn--wgbh1c",
-    "xn--wgbl6a",
-    "xn--xhq521b",
-    "xn--xkc2al3hye2a",
-    "xn--xkc2dl3a5ee0h",
-    "xn--y9a3aq",
-    "xn--yfro4i67o",
-    "xn--ygbi2ammx",
-    "xn--zfr164b",
-    "xxx",
-    "xyz",
-    "yachts",
-    "yahoo",
-    "yamaxun",
-    "yandex",
-    "ye",
-    "yodobashi",
-    "yoga",
-    "yokohama",
-    "you",
-    "youtube",
-    "yt",
-    "yun",
-    "za",
-    "zappos",
-    "zara",
-    "zero",
-    "zip",
-    "zm",
-    "zone",
-    "zuerich",
-    "zw",
-};
blob - /dev/null
blob + 90683e5ab7dcdb5e61181c4bed770396903c0058 (mode 644)
--- /dev/null
+++ src/fence/fence.h
@@ -0,0 +1,3 @@
+char fence_is_top_level_domain(char *domain);
+int quote_depth(char *line);
+size_t fence_copy_after_line(char *dst, char *src, char *line);
blob - /dev/null
blob + 3db3c90ce76ac72f363922645c8e805460932a7c (mode 644)
--- /dev/null
+++ src/fence/root.zig
@@ -0,0 +1,102 @@
+const std = @import("std");
+const tlds = @import("tlds.zig");
+const testing = std.testing;
+
+export fn fence_is_top_level_domain(dom: [*:0]const u8) bool {
+    return isTopLevelDomain(std.mem.span(dom));
+}
+
+fn isTopLevelDomain(dom: []const u8) bool {
+    for (tlds.tab) |tld| {
+        if (std.mem.eql(u8, dom, tld)) return true;
+    }
+    return false;
+}
+
+fn isRfc822Char(c: u8) bool {
+    if (!std.ascii.isAscii(c)) return false;
+    switch (c) {
+        0...32, 127 => return false,
+        '(', ')', ',', ';', '<', '>', '"' => return false,
+    }
+    return true;
+}
+
+fn quoteDepth(line: []const u8) u8 {
+    const ln = std.mem.trim(u8, line, &std.ascii.whitespace);
+    const first = std.mem.indexOfScalar(u8, ln, '>') orelse return 0;
+    if (first != 0) return 0;
+
+    var depth: u8 = 0;
+    const last = std.mem.lastIndexOfScalar(u8, ln, '>') orelse return 1;
+    for (line[first .. last + 1]) |c| {
+        if (c == '>') {
+            if (depth == 0xff) return depth;
+            depth += 1;
+            continue;
+        }
+        if (std.ascii.isWhitespace(c)) continue;
+        break;
+    }
+    return depth;
+}
+
+export fn quote_depth(line: [*:0]const u8) c_int {
+    const n = quoteDepth(std.mem.span(line));
+    return @as(c_int, n);
+}
+
+fn copyAfterLine(dst: std.fs.File, src: std.fs.File, key: []const u8) !usize {
+    var buf: [8192]u8 = undefined;
+    var rd = std.io.bufferedReader(src.reader());
+    var r = rd.reader();
+    var wr = std.io.bufferedWriter(dst.writer());
+    var w = wr.writer();
+    var found = false;
+    var n: usize = 0;
+    while (try r.readUntilDelimiterOrEof(buf[0..], '\n')) |line| {
+        if (std.mem.startsWith(u8, line, key)) {
+            found = true;
+            continue;
+        }
+        if (!found) continue;
+        try w.print("{s}\n", .{line});
+        n += (line.len + 1); // + 1 for newline
+    }
+    try wr.flush();
+    return n;
+}
+
+export fn fence_copy_after_line(dst: [*:0]const u8, src: [*:0]const u8, line: [*:0]const u8) usize {
+    const fdst = std.fs.cwd().createFile(std.mem.span(dst), .{}) catch return 0;
+    defer fdst.close();
+    const fsrc = std.fs.cwd().openFile(std.mem.span(src), .{}) catch return 0;
+    defer fsrc.close();
+    return copyAfterLine(fdst, fsrc, std.mem.span(line)) catch 0;
+}
+
+test "quote depth" {
+    const tests = [_]struct { []const u8, u8 }{
+        .{ ">>> hello", 3 },
+        .{ ">    >> hello", 3 },
+        .{ "     > hello >", 1 },
+        .{ "hello>>", 0 },
+        .{ ">> hello >>", 2 },
+        .{ ">  \t> hello", 2 },
+        .{ ">", 1 },
+        .{ "xxx > hello >>", 0 },
+    };
+    for (tests) |t| {
+        const got = quoteDepth(t[0]);
+        errdefer std.debug.print("quote depth for \"{s}\"\n", .{t[0]});
+        try testing.expectEqual(t[1], got);
+    }
+}
+
+test "check domains" {
+    try testing.expect(isTopLevelDomain("com"));
+    try testing.expect(isTopLevelDomain("69yamum") == false);
+
+    const str = [_:0]u8{ 'c', 'o', 'm', 0 };
+    try testing.expect(fence_is_top_level_domain(str[0..]));
+}
blob - /dev/null
blob + 0fb29f6d90ff4d12beca7d1d83efc7e31eb99adf (mode 644)
--- /dev/null
+++ src/fence/tlds.zig
@@ -0,0 +1,1443 @@
+// curl https://data.iana.org/TLD/tlds-alpha-by-domain.txt | grep -v '^#' | tr A-Z a-z > tlds.zig
+pub const tab = [_][]const u8{
+    "aaa",
+    "aarp",
+    "abb",
+    "abbott",
+    "abbvie",
+    "abc",
+    "able",
+    "abogado",
+    "abudhabi",
+    "ac",
+    "academy",
+    "accenture",
+    "accountant",
+    "accountants",
+    "aco",
+    "actor",
+    "ad",
+    "ads",
+    "adult",
+    "ae",
+    "aeg",
+    "aero",
+    "aetna",
+    "af",
+    "afl",
+    "africa",
+    "ag",
+    "agakhan",
+    "agency",
+    "ai",
+    "aig",
+    "airbus",
+    "airforce",
+    "airtel",
+    "akdn",
+    "al",
+    "alibaba",
+    "alipay",
+    "allfinanz",
+    "allstate",
+    "ally",
+    "alsace",
+    "alstom",
+    "am",
+    "amazon",
+    "americanexpress",
+    "americanfamily",
+    "amex",
+    "amfam",
+    "amica",
+    "amsterdam",
+    "analytics",
+    "android",
+    "anquan",
+    "anz",
+    "ao",
+    "aol",
+    "apartments",
+    "app",
+    "apple",
+    "aq",
+    "aquarelle",
+    "ar",
+    "arab",
+    "aramco",
+    "archi",
+    "army",
+    "arpa",
+    "art",
+    "arte",
+    "as",
+    "asda",
+    "asia",
+    "associates",
+    "at",
+    "athleta",
+    "attorney",
+    "au",
+    "auction",
+    "audi",
+    "audible",
+    "audio",
+    "auspost",
+    "author",
+    "auto",
+    "autos",
+    "aw",
+    "aws",
+    "ax",
+    "axa",
+    "az",
+    "azure",
+    "ba",
+    "baby",
+    "baidu",
+    "banamex",
+    "band",
+    "bank",
+    "bar",
+    "barcelona",
+    "barclaycard",
+    "barclays",
+    "barefoot",
+    "bargains",
+    "baseball",
+    "basketball",
+    "bauhaus",
+    "bayern",
+    "bb",
+    "bbc",
+    "bbt",
+    "bbva",
+    "bcg",
+    "bcn",
+    "bd",
+    "be",
+    "beats",
+    "beauty",
+    "beer",
+    "berlin",
+    "best",
+    "bestbuy",
+    "bet",
+    "bf",
+    "bg",
+    "bh",
+    "bharti",
+    "bi",
+    "bible",
+    "bid",
+    "bike",
+    "bing",
+    "bingo",
+    "bio",
+    "biz",
+    "bj",
+    "black",
+    "blackfriday",
+    "blockbuster",
+    "blog",
+    "bloomberg",
+    "blue",
+    "bm",
+    "bms",
+    "bmw",
+    "bn",
+    "bnpparibas",
+    "bo",
+    "boats",
+    "boehringer",
+    "bofa",
+    "bom",
+    "bond",
+    "boo",
+    "book",
+    "booking",
+    "bosch",
+    "bostik",
+    "boston",
+    "bot",
+    "boutique",
+    "box",
+    "br",
+    "bradesco",
+    "bridgestone",
+    "broadway",
+    "broker",
+    "brother",
+    "brussels",
+    "bs",
+    "bt",
+    "build",
+    "builders",
+    "business",
+    "buy",
+    "buzz",
+    "bv",
+    "bw",
+    "by",
+    "bz",
+    "bzh",
+    "ca",
+    "cab",
+    "cafe",
+    "cal",
+    "call",
+    "calvinklein",
+    "cam",
+    "camera",
+    "camp",
+    "canon",
+    "capetown",
+    "capital",
+    "capitalone",
+    "car",
+    "caravan",
+    "cards",
+    "care",
+    "career",
+    "careers",
+    "cars",
+    "casa",
+    "case",
+    "cash",
+    "casino",
+    "cat",
+    "catering",
+    "catholic",
+    "cba",
+    "cbn",
+    "cbre",
+    "cc",
+    "cd",
+    "center",
+    "ceo",
+    "cern",
+    "cf",
+    "cfa",
+    "cfd",
+    "cg",
+    "ch",
+    "chanel",
+    "channel",
+    "charity",
+    "chase",
+    "chat",
+    "cheap",
+    "chintai",
+    "christmas",
+    "chrome",
+    "church",
+    "ci",
+    "cipriani",
+    "circle",
+    "cisco",
+    "citadel",
+    "citi",
+    "citic",
+    "city",
+    "ck",
+    "cl",
+    "claims",
+    "cleaning",
+    "click",
+    "clinic",
+    "clinique",
+    "clothing",
+    "cloud",
+    "club",
+    "clubmed",
+    "cm",
+    "cn",
+    "co",
+    "coach",
+    "codes",
+    "coffee",
+    "college",
+    "cologne",
+    "com",
+    "commbank",
+    "community",
+    "company",
+    "compare",
+    "computer",
+    "comsec",
+    "condos",
+    "construction",
+    "consulting",
+    "contact",
+    "contractors",
+    "cooking",
+    "cool",
+    "coop",
+    "corsica",
+    "country",
+    "coupon",
+    "coupons",
+    "courses",
+    "cpa",
+    "cr",
+    "credit",
+    "creditcard",
+    "creditunion",
+    "cricket",
+    "crown",
+    "crs",
+    "cruise",
+    "cruises",
+    "cu",
+    "cuisinella",
+    "cv",
+    "cw",
+    "cx",
+    "cy",
+    "cymru",
+    "cyou",
+    "cz",
+    "dad",
+    "dance",
+    "data",
+    "date",
+    "dating",
+    "datsun",
+    "day",
+    "dclk",
+    "dds",
+    "de",
+    "deal",
+    "dealer",
+    "deals",
+    "degree",
+    "delivery",
+    "dell",
+    "deloitte",
+    "delta",
+    "democrat",
+    "dental",
+    "dentist",
+    "desi",
+    "design",
+    "dev",
+    "dhl",
+    "diamonds",
+    "diet",
+    "digital",
+    "direct",
+    "directory",
+    "discount",
+    "discover",
+    "dish",
+    "diy",
+    "dj",
+    "dk",
+    "dm",
+    "dnp",
+    "do",
+    "docs",
+    "doctor",
+    "dog",
+    "domains",
+    "dot",
+    "download",
+    "drive",
+    "dtv",
+    "dubai",
+    "dunlop",
+    "dupont",
+    "durban",
+    "dvag",
+    "dvr",
+    "dz",
+    "earth",
+    "eat",
+    "ec",
+    "eco",
+    "edeka",
+    "edu",
+    "education",
+    "ee",
+    "eg",
+    "email",
+    "emerck",
+    "energy",
+    "engineer",
+    "engineering",
+    "enterprises",
+    "epson",
+    "equipment",
+    "er",
+    "ericsson",
+    "erni",
+    "es",
+    "esq",
+    "estate",
+    "et",
+    "eu",
+    "eurovision",
+    "eus",
+    "events",
+    "exchange",
+    "expert",
+    "exposed",
+    "express",
+    "extraspace",
+    "fage",
+    "fail",
+    "fairwinds",
+    "faith",
+    "family",
+    "fan",
+    "fans",
+    "farm",
+    "farmers",
+    "fashion",
+    "fast",
+    "fedex",
+    "feedback",
+    "ferrari",
+    "ferrero",
+    "fi",
+    "fidelity",
+    "fido",
+    "film",
+    "final",
+    "finance",
+    "financial",
+    "fire",
+    "firestone",
+    "firmdale",
+    "fish",
+    "fishing",
+    "fit",
+    "fitness",
+    "fj",
+    "fk",
+    "flickr",
+    "flights",
+    "flir",
+    "florist",
+    "flowers",
+    "fly",
+    "fm",
+    "fo",
+    "foo",
+    "food",
+    "football",
+    "ford",
+    "forex",
+    "forsale",
+    "forum",
+    "foundation",
+    "fox",
+    "fr",
+    "free",
+    "fresenius",
+    "frl",
+    "frogans",
+    "frontier",
+    "ftr",
+    "fujitsu",
+    "fun",
+    "fund",
+    "furniture",
+    "futbol",
+    "fyi",
+    "ga",
+    "gal",
+    "gallery",
+    "gallo",
+    "gallup",
+    "game",
+    "games",
+    "gap",
+    "garden",
+    "gay",
+    "gb",
+    "gbiz",
+    "gd",
+    "gdn",
+    "ge",
+    "gea",
+    "gent",
+    "genting",
+    "george",
+    "gf",
+    "gg",
+    "ggee",
+    "gh",
+    "gi",
+    "gift",
+    "gifts",
+    "gives",
+    "giving",
+    "gl",
+    "glass",
+    "gle",
+    "global",
+    "globo",
+    "gm",
+    "gmail",
+    "gmbh",
+    "gmo",
+    "gmx",
+    "gn",
+    "godaddy",
+    "gold",
+    "goldpoint",
+    "golf",
+    "goo",
+    "goodyear",
+    "goog",
+    "google",
+    "gop",
+    "got",
+    "gov",
+    "gp",
+    "gq",
+    "gr",
+    "grainger",
+    "graphics",
+    "gratis",
+    "green",
+    "gripe",
+    "grocery",
+    "group",
+    "gs",
+    "gt",
+    "gu",
+    "gucci",
+    "guge",
+    "guide",
+    "guitars",
+    "guru",
+    "gw",
+    "gy",
+    "hair",
+    "hamburg",
+    "hangout",
+    "haus",
+    "hbo",
+    "hdfc",
+    "hdfcbank",
+    "health",
+    "healthcare",
+    "help",
+    "helsinki",
+    "here",
+    "hermes",
+    "hiphop",
+    "hisamitsu",
+    "hitachi",
+    "hiv",
+    "hk",
+    "hkt",
+    "hm",
+    "hn",
+    "hockey",
+    "holdings",
+    "holiday",
+    "homedepot",
+    "homegoods",
+    "homes",
+    "homesense",
+    "honda",
+    "horse",
+    "hospital",
+    "host",
+    "hosting",
+    "hot",
+    "hotels",
+    "hotmail",
+    "house",
+    "how",
+    "hr",
+    "hsbc",
+    "ht",
+    "hu",
+    "hughes",
+    "hyatt",
+    "hyundai",
+    "ibm",
+    "icbc",
+    "ice",
+    "icu",
+    "id",
+    "ie",
+    "ieee",
+    "ifm",
+    "ikano",
+    "il",
+    "im",
+    "imamat",
+    "imdb",
+    "immo",
+    "immobilien",
+    "in",
+    "inc",
+    "industries",
+    "infiniti",
+    "info",
+    "ing",
+    "ink",
+    "institute",
+    "insurance",
+    "insure",
+    "int",
+    "international",
+    "intuit",
+    "investments",
+    "io",
+    "ipiranga",
+    "iq",
+    "ir",
+    "irish",
+    "is",
+    "ismaili",
+    "ist",
+    "istanbul",
+    "it",
+    "itau",
+    "itv",
+    "jaguar",
+    "java",
+    "jcb",
+    "je",
+    "jeep",
+    "jetzt",
+    "jewelry",
+    "jio",
+    "jll",
+    "jm",
+    "jmp",
+    "jnj",
+    "jo",
+    "jobs",
+    "joburg",
+    "jot",
+    "joy",
+    "jp",
+    "jpmorgan",
+    "jprs",
+    "juegos",
+    "juniper",
+    "kaufen",
+    "kddi",
+    "ke",
+    "kerryhotels",
+    "kerryproperties",
+    "kfh",
+    "kg",
+    "kh",
+    "ki",
+    "kia",
+    "kids",
+    "kim",
+    "kindle",
+    "kitchen",
+    "kiwi",
+    "km",
+    "kn",
+    "koeln",
+    "komatsu",
+    "kosher",
+    "kp",
+    "kpmg",
+    "kpn",
+    "kr",
+    "krd",
+    "kred",
+    "kuokgroup",
+    "kw",
+    "ky",
+    "kyoto",
+    "kz",
+    "la",
+    "lacaixa",
+    "lamborghini",
+    "lamer",
+    "land",
+    "landrover",
+    "lanxess",
+    "lasalle",
+    "lat",
+    "latino",
+    "latrobe",
+    "law",
+    "lawyer",
+    "lb",
+    "lc",
+    "lds",
+    "lease",
+    "leclerc",
+    "lefrak",
+    "legal",
+    "lego",
+    "lexus",
+    "lgbt",
+    "li",
+    "lidl",
+    "life",
+    "lifeinsurance",
+    "lifestyle",
+    "lighting",
+    "like",
+    "lilly",
+    "limited",
+    "limo",
+    "lincoln",
+    "link",
+    "live",
+    "living",
+    "lk",
+    "llc",
+    "llp",
+    "loan",
+    "loans",
+    "locker",
+    "locus",
+    "lol",
+    "london",
+    "lotte",
+    "lotto",
+    "love",
+    "lpl",
+    "lplfinancial",
+    "lr",
+    "ls",
+    "lt",
+    "ltd",
+    "ltda",
+    "lu",
+    "lundbeck",
+    "luxe",
+    "luxury",
+    "lv",
+    "ly",
+    "ma",
+    "madrid",
+    "maif",
+    "maison",
+    "makeup",
+    "man",
+    "management",
+    "mango",
+    "map",
+    "market",
+    "marketing",
+    "markets",
+    "marriott",
+    "marshalls",
+    "mattel",
+    "mba",
+    "mc",
+    "mckinsey",
+    "md",
+    "me",
+    "med",
+    "media",
+    "meet",
+    "melbourne",
+    "meme",
+    "memorial",
+    "men",
+    "menu",
+    "merckmsd",
+    "mg",
+    "mh",
+    "miami",
+    "microsoft",
+    "mil",
+    "mini",
+    "mint",
+    "mit",
+    "mitsubishi",
+    "mk",
+    "ml",
+    "mlb",
+    "mls",
+    "mm",
+    "mma",
+    "mn",
+    "mo",
+    "mobi",
+    "mobile",
+    "moda",
+    "moe",
+    "moi",
+    "mom",
+    "monash",
+    "money",
+    "monster",
+    "mormon",
+    "mortgage",
+    "moscow",
+    "moto",
+    "motorcycles",
+    "mov",
+    "movie",
+    "mp",
+    "mq",
+    "mr",
+    "ms",
+    "msd",
+    "mt",
+    "mtn",
+    "mtr",
+    "mu",
+    "museum",
+    "music",
+    "mv",
+    "mw",
+    "mx",
+    "my",
+    "mz",
+    "na",
+    "nab",
+    "nagoya",
+    "name",
+    "navy",
+    "nba",
+    "nc",
+    "ne",
+    "nec",
+    "net",
+    "netbank",
+    "netflix",
+    "network",
+    "neustar",
+    "new",
+    "news",
+    "next",
+    "nextdirect",
+    "nexus",
+    "nf",
+    "nfl",
+    "ng",
+    "ngo",
+    "nhk",
+    "ni",
+    "nico",
+    "nike",
+    "nikon",
+    "ninja",
+    "nissan",
+    "nissay",
+    "nl",
+    "no",
+    "nokia",
+    "norton",
+    "now",
+    "nowruz",
+    "nowtv",
+    "np",
+    "nr",
+    "nra",
+    "nrw",
+    "ntt",
+    "nu",
+    "nyc",
+    "nz",
+    "obi",
+    "observer",
+    "office",
+    "okinawa",
+    "olayan",
+    "olayangroup",
+    "ollo",
+    "om",
+    "omega",
+    "one",
+    "ong",
+    "onl",
+    "online",
+    "ooo",
+    "open",
+    "oracle",
+    "orange",
+    "org",
+    "organic",
+    "origins",
+    "osaka",
+    "otsuka",
+    "ott",
+    "ovh",
+    "pa",
+    "page",
+    "panasonic",
+    "paris",
+    "pars",
+    "partners",
+    "parts",
+    "party",
+    "pay",
+    "pccw",
+    "pe",
+    "pet",
+    "pf",
+    "pfizer",
+    "pg",
+    "ph",
+    "pharmacy",
+    "phd",
+    "philips",
+    "phone",
+    "photo",
+    "photography",
+    "photos",
+    "physio",
+    "pics",
+    "pictet",
+    "pictures",
+    "pid",
+    "pin",
+    "ping",
+    "pink",
+    "pioneer",
+    "pizza",
+    "pk",
+    "pl",
+    "place",
+    "play",
+    "playstation",
+    "plumbing",
+    "plus",
+    "pm",
+    "pn",
+    "pnc",
+    "pohl",
+    "poker",
+    "politie",
+    "porn",
+    "post",
+    "pr",
+    "praxi",
+    "press",
+    "prime",
+    "pro",
+    "prod",
+    "productions",
+    "prof",
+    "progressive",
+    "promo",
+    "properties",
+    "property",
+    "protection",
+    "pru",
+    "prudential",
+    "ps",
+    "pt",
+    "pub",
+    "pw",
+    "pwc",
+    "py",
+    "qa",
+    "qpon",
+    "quebec",
+    "quest",
+    "racing",
+    "radio",
+    "re",
+    "read",
+    "realestate",
+    "realtor",
+    "realty",
+    "recipes",
+    "red",
+    "redstone",
+    "redumbrella",
+    "rehab",
+    "reise",
+    "reisen",
+    "reit",
+    "reliance",
+    "ren",
+    "rent",
+    "rentals",
+    "repair",
+    "report",
+    "republican",
+    "rest",
+    "restaurant",
+    "review",
+    "reviews",
+    "rexroth",
+    "rich",
+    "richardli",
+    "ricoh",
+    "ril",
+    "rio",
+    "rip",
+    "ro",
+    "rocks",
+    "rodeo",
+    "rogers",
+    "room",
+    "rs",
+    "rsvp",
+    "ru",
+    "rugby",
+    "ruhr",
+    "run",
+    "rw",
+    "rwe",
+    "ryukyu",
+    "sa",
+    "saarland",
+    "safe",
+    "safety",
+    "sakura",
+    "sale",
+    "salon",
+    "samsclub",
+    "samsung",
+    "sandvik",
+    "sandvikcoromant",
+    "sanofi",
+    "sap",
+    "sarl",
+    "sas",
+    "save",
+    "saxo",
+    "sb",
+    "sbi",
+    "sbs",
+    "sc",
+    "scb",
+    "schaeffler",
+    "schmidt",
+    "scholarships",
+    "school",
+    "schule",
+    "schwarz",
+    "science",
+    "scot",
+    "sd",
+    "se",
+    "search",
+    "seat",
+    "secure",
+    "security",
+    "seek",
+    "select",
+    "sener",
+    "services",
+    "seven",
+    "sew",
+    "sex",
+    "sexy",
+    "sfr",
+    "sg",
+    "sh",
+    "shangrila",
+    "sharp",
+    "shell",
+    "shia",
+    "shiksha",
+    "shoes",
+    "shop",
+    "shopping",
+    "shouji",
+    "show",
+    "si",
+    "silk",
+    "sina",
+    "singles",
+    "site",
+    "sj",
+    "sk",
+    "ski",
+    "skin",
+    "sky",
+    "skype",
+    "sl",
+    "sling",
+    "sm",
+    "smart",
+    "smile",
+    "sn",
+    "sncf",
+    "so",
+    "soccer",
+    "social",
+    "softbank",
+    "software",
+    "sohu",
+    "solar",
+    "solutions",
+    "song",
+    "sony",
+    "soy",
+    "spa",
+    "space",
+    "sport",
+    "spot",
+    "sr",
+    "srl",
+    "ss",
+    "st",
+    "stada",
+    "staples",
+    "star",
+    "statebank",
+    "statefarm",
+    "stc",
+    "stcgroup",
+    "stockholm",
+    "storage",
+    "store",
+    "stream",
+    "studio",
+    "study",
+    "style",
+    "su",
+    "sucks",
+    "supplies",
+    "supply",
+    "support",
+    "surf",
+    "surgery",
+    "suzuki",
+    "sv",
+    "swatch",
+    "swiss",
+    "sx",
+    "sy",
+    "sydney",
+    "systems",
+    "sz",
+    "tab",
+    "taipei",
+    "talk",
+    "taobao",
+    "target",
+    "tatamotors",
+    "tatar",
+    "tattoo",
+    "tax",
+    "taxi",
+    "tc",
+    "tci",
+    "td",
+    "tdk",
+    "team",
+    "tech",
+    "technology",
+    "tel",
+    "temasek",
+    "tennis",
+    "teva",
+    "tf",
+    "tg",
+    "th",
+    "thd",
+    "theater",
+    "theatre",
+    "tiaa",
+    "tickets",
+    "tienda",
+    "tips",
+    "tires",
+    "tirol",
+    "tj",
+    "tjmaxx",
+    "tjx",
+    "tk",
+    "tkmaxx",
+    "tl",
+    "tm",
+    "tmall",
+    "tn",
+    "to",
+    "today",
+    "tokyo",
+    "tools",
+    "top",
+    "toray",
+    "toshiba",
+    "total",
+    "tours",
+    "town",
+    "toyota",
+    "toys",
+    "tr",
+    "trade",
+    "trading",
+    "training",
+    "travel",
+    "travelers",
+    "travelersinsurance",
+    "trust",
+    "trv",
+    "tt",
+    "tube",
+    "tui",
+    "tunes",
+    "tushu",
+    "tv",
+    "tvs",
+    "tw",
+    "tz",
+    "ua",
+    "ubank",
+    "ubs",
+    "ug",
+    "uk",
+    "unicom",
+    "university",
+    "uno",
+    "uol",
+    "ups",
+    "us",
+    "uy",
+    "uz",
+    "va",
+    "vacations",
+    "vana",
+    "vanguard",
+    "vc",
+    "ve",
+    "vegas",
+    "ventures",
+    "verisign",
+    "versicherung",
+    "vet",
+    "vg",
+    "vi",
+    "viajes",
+    "video",
+    "vig",
+    "viking",
+    "villas",
+    "vin",
+    "vip",
+    "virgin",
+    "visa",
+    "vision",
+    "viva",
+    "vivo",
+    "vlaanderen",
+    "vn",
+    "vodka",
+    "volvo",
+    "vote",
+    "voting",
+    "voto",
+    "voyage",
+    "vu",
+    "wales",
+    "walmart",
+    "walter",
+    "wang",
+    "wanggou",
+    "watch",
+    "watches",
+    "weather",
+    "weatherchannel",
+    "webcam",
+    "weber",
+    "website",
+    "wed",
+    "wedding",
+    "weibo",
+    "weir",
+    "wf",
+    "whoswho",
+    "wien",
+    "wiki",
+    "williamhill",
+    "win",
+    "windows",
+    "wine",
+    "winners",
+    "wme",
+    "wolterskluwer",
+    "woodside",
+    "work",
+    "works",
+    "world",
+    "wow",
+    "ws",
+    "wtc",
+    "wtf",
+    "xbox",
+    "xerox",
+    "xihuan",
+    "xin",
+    "xn--11b4c3d",
+    "xn--1ck2e1b",
+    "xn--1qqw23a",
+    "xn--2scrj9c",
+    "xn--30rr7y",
+    "xn--3bst00m",
+    "xn--3ds443g",
+    "xn--3e0b707e",
+    "xn--3hcrj9c",
+    "xn--3pxu8k",
+    "xn--42c2d9a",
+    "xn--45br5cyl",
+    "xn--45brj9c",
+    "xn--45q11c",
+    "xn--4dbrk0ce",
+    "xn--4gbrim",
+    "xn--54b7fta0cc",
+    "xn--55qw42g",
+    "xn--55qx5d",
+    "xn--5su34j936bgsg",
+    "xn--5tzm5g",
+    "xn--6frz82g",
+    "xn--6qq986b3xl",
+    "xn--80adxhks",
+    "xn--80ao21a",
+    "xn--80aqecdr1a",
+    "xn--80asehdb",
+    "xn--80aswg",
+    "xn--8y0a063a",
+    "xn--90a3ac",
+    "xn--90ae",
+    "xn--90ais",
+    "xn--9dbq2a",
+    "xn--9et52u",
+    "xn--9krt00a",
+    "xn--b4w605ferd",
+    "xn--bck1b9a5dre4c",
+    "xn--c1avg",
+    "xn--c2br7g",
+    "xn--cck2b3b",
+    "xn--cckwcxetd",
+    "xn--cg4bki",
+    "xn--clchc0ea0b2g2a9gcd",
+    "xn--czr694b",
+    "xn--czrs0t",
+    "xn--czru2d",
+    "xn--d1acj3b",
+    "xn--d1alf",
+    "xn--e1a4c",
+    "xn--eckvdtc9d",
+    "xn--efvy88h",
+    "xn--fct429k",
+    "xn--fhbei",
+    "xn--fiq228c5hs",
+    "xn--fiq64b",
+    "xn--fiqs8s",
+    "xn--fiqz9s",
+    "xn--fjq720a",
+    "xn--flw351e",
+    "xn--fpcrj9c3d",
+    "xn--fzc2c9e2c",
+    "xn--fzys8d69uvgm",
+    "xn--g2xx48c",
+    "xn--gckr3f0f",
+    "xn--gecrj9c",
+    "xn--gk3at1e",
+    "xn--h2breg3eve",
+    "xn--h2brj9c",
+    "xn--h2brj9c8c",
+    "xn--hxt814e",
+    "xn--i1b6b1a6a2e",
+    "xn--imr513n",
+    "xn--io0a7i",
+    "xn--j1aef",
+    "xn--j1amh",
+    "xn--j6w193g",
+    "xn--jlq480n2rg",
+    "xn--jvr189m",
+    "xn--kcrx77d1x4a",
+    "xn--kprw13d",
+    "xn--kpry57d",
+    "xn--kput3i",
+    "xn--l1acc",
+    "xn--lgbbat1ad8j",
+    "xn--mgb9awbf",
+    "xn--mgba3a3ejt",
+    "xn--mgba3a4f16a",
+    "xn--mgba7c0bbn0a",
+    "xn--mgbaam7a8h",
+    "xn--mgbab2bd",
+    "xn--mgbah1a3hjkrd",
+    "xn--mgbai9azgqp6j",
+    "xn--mgbayh7gpa",
+    "xn--mgbbh1a",
+    "xn--mgbbh1a71e",
+    "xn--mgbc0a9azcg",
+    "xn--mgbca7dzdo",
+    "xn--mgbcpq6gpa1a",
+    "xn--mgberp4a5d4ar",
+    "xn--mgbgu82a",
+    "xn--mgbi4ecexp",
+    "xn--mgbpl2fh",
+    "xn--mgbt3dhd",
+    "xn--mgbtx2b",
+    "xn--mgbx4cd0ab",
+    "xn--mix891f",
+    "xn--mk1bu44c",
+    "xn--mxtq1m",
+    "xn--ngbc5azd",
+    "xn--ngbe9e0a",
+    "xn--ngbrx",
+    "xn--node",
+    "xn--nqv7f",
+    "xn--nqv7fs00ema",
+    "xn--nyqy26a",
+    "xn--o3cw4h",
+    "xn--ogbpf8fl",
+    "xn--otu796d",
+    "xn--p1acf",
+    "xn--p1ai",
+    "xn--pgbs0dh",
+    "xn--pssy2u",
+    "xn--q7ce6a",
+    "xn--q9jyb4c",
+    "xn--qcka1pmc",
+    "xn--qxa6a",
+    "xn--qxam",
+    "xn--rhqv96g",
+    "xn--rovu88b",
+    "xn--rvc1e0am3e",
+    "xn--s9brj9c",
+    "xn--ses554g",
+    "xn--t60b56a",
+    "xn--tckwe",
+    "xn--tiq49xqyj",
+    "xn--unup4y",
+    "xn--vermgensberater-ctb",
+    "xn--vermgensberatung-pwb",
+    "xn--vhquv",
+    "xn--vuq861b",
+    "xn--w4r85el8fhu5dnra",
+    "xn--w4rs40l",
+    "xn--wgbh1c",
+    "xn--wgbl6a",
+    "xn--xhq521b",
+    "xn--xkc2al3hye2a",
+    "xn--xkc2dl3a5ee0h",
+    "xn--y9a3aq",
+    "xn--yfro4i67o",
+    "xn--ygbi2ammx",
+    "xn--zfr164b",
+    "xxx",
+    "xyz",
+    "yachts",
+    "yahoo",
+    "yamaxun",
+    "yandex",
+    "ye",
+    "yodobashi",
+    "yoga",
+    "yokohama",
+    "you",
+    "youtube",
+    "yt",
+    "yun",
+    "za",
+    "zappos",
+    "zara",
+    "zero",
+    "zip",
+    "zm",
+    "zone",
+    "zuerich",
+    "zw",
+};