Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions src/core/ProxyRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ import { Utils } from "../lib/Utils";
import { SettingsOperation } from "./SettingsOperation";
import { api } from "../lib/environment";

function regexHostMatches(rule: CompiledProxyRule, host: string): boolean {
if (rule.regex.test(host))
return true;

let normalizedHost = Utils.normalizeIpForMatching(host);
return normalizedHost != null && normalizedHost !== host && rule.regex.test(normalizedHost);
}

export class ProxyRules {

public static compileRules(profile: SmartProfileBase, proxyRules: ProxyRule[]): {
Expand Down Expand Up @@ -370,7 +378,7 @@ export class ProxyRules {
}
}

if (rule.regex.test(domainHostLowerCase))
if (regexHostMatches(rule, domainHostLowerCase))
return rule;
break;

Expand Down Expand Up @@ -448,7 +456,7 @@ export class ProxyRules {

case CompiledProxyRuleType.RegexHost:

if (rule.regex.test(domainHostLowerCase))
if (regexHostMatches(rule, domainHostLowerCase))
return rule;
break;

Expand Down
169 changes: 47 additions & 122 deletions src/lib/RuleImporterSwitchy.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
* @source https://github.com/FelisCatus/SwitchyOmega
* @license GPL3
*/
const { Utils } = require('./Utils');

const strStartsWith = function (str, prefix) {
return str.substr(0, prefix.length) === prefix;
};
Expand Down Expand Up @@ -839,146 +841,69 @@ const Conditions = {
'IpCondition': {
abbrs: ['Ip'],
analyze: function (condition) {
let addr, cache, ip, mask;
let cache, ip, regex;
cache = {
addr: null,
normalized: null
regex: null
};
ip = condition.ip;
if (ip.charCodeAt(0) === '['.charCodeAt(0)) {
ip = ip.substr(1, ip.length - 2);
ip = (condition.ip || '').trim();
if (ip.charCodeAt(0) === '['.charCodeAt(0) && ip.charCodeAt(ip.length - 1) === ']'.charCodeAt(0)) {
ip = ip.substring(1, ip.length - 1).trim();
}
addr = ip + '/' + condition.prefixLength;
cache.addr = this.parseIp(addr);
if (cache.addr == null) {
throw new Error("Invalid IP address " + addr);
regex = Utils.ipCidrNotationToRegExp(ip, String(condition.prefixLength));
if (regex == null) {
throw new Error("Invalid IP address " + ip + '/' + condition.prefixLength);
}
cache.normalized = this.normalizeIp(cache.addr);
mask = cache.addr.v4 ? new IP.v4.Address('255.255.255.255/' + cache.addr.subnetMask) : new IP.v6.Address(this.ipv6Max + '/' + cache.addr.subnetMask);
cache.mask = this.normalizeIp(mask.startAddress());
cache.regex = regex;
return cache;
},
match: function (condition, request, cache) {
let addr;
addr = this.parseIp(request.host);
if (addr == null) {
let normalizedHost;
normalizedHost = Utils.normalizeIpForMatching(request.host);
if (normalizedHost == null) {
return false;
}
cache = cache.analyzed;
if (addr.v4 !== cache.addr.v4) {
return false;
}
return addr.isInSubnet(cache.addr);
return cache.regex.test(normalizedHost);
},
compile: function (condition, cache) {
let hostIsInNet, hostIsInNetEx, hostLooksLikeIp;
cache = cache.analyzed;
hostLooksLikeIp = cache.addr.v4 ? new U2.AST_Binary({
left: new U2.AST_Sub({
expression: new U2.AST_SymbolRef({
name: 'host'
}),
property: new U2.AST_Binary({
left: new U2.AST_Dot({
expression: new U2.AST_SymbolRef({
name: 'host'
}),
property: 'length'
}),
operator: '-',
right: new U2.AST_Number({
value: 1
})
})
}),
operator: '>=',
right: new U2.AST_Number({
value: 0
})
}) : new U2.AST_Binary({
left: new U2.AST_Call({
expression: new U2.AST_Dot({
expression: new U2.AST_SymbolRef({
name: 'host'
}),
property: 'indexOf'
}),
args: [
new U2.AST_String({
value: ':'
})
]
}),
operator: '>=',
right: new U2.AST_Number({
value: 0
})
});
if (cache.addr.subnetMask === 0) {
return hostLooksLikeIp;
}
hostIsInNet = new U2.AST_Call({
expression: new U2.AST_SymbolRef({
name: 'isInNet'
}),
args: [
new U2.AST_SymbolRef({
name: 'host'
}), new U2.AST_String({
value: cache.normalized
}), new U2.AST_String({
value: cache.mask
})
]
});
if (!cache.addr.v4) {
hostIsInNetEx = new U2.AST_Call({
expression: new U2.AST_SymbolRef({
name: 'isInNetEx'
}),
args: [
new U2.AST_SymbolRef({
name: 'host'
}), new U2.AST_String({
value: cache.normalized + cache.addr.subnet
})
]
});
hostIsInNet = new U2.AST_Conditional({
condition: new U2.AST_Binary({
left: new U2.AST_UnaryPrefix({
operator: 'typeof',
expression: new U2.AST_SymbolRef({
name: 'isInNetEx'
})
}),
operator: '===',
right: new U2.AST_String({
value: 'function'
})
}),
consequent: hostIsInNetEx,
alternative: hostIsInNet
});
}
return new U2.AST_Binary({
left: hostLooksLikeIp,
operator: '&&',
right: hostIsInNet
});
return this.regTest('host', cache.regex);
},
str: function (condition) {
return condition.ip + '/' + condition.prefixLength;
},
fromStr: function (str, condition) {
let addr;
addr = this.parseIp(str);
if (addr != null) {
condition.ip = addr.addressMinusSuffix;
condition.prefixLength = addr.subnetMask;
let ip, slashIndex;
str = str.trim();
if (str.charCodeAt(0) === '['.charCodeAt(0) && str.charCodeAt(str.length - 1) === ']'.charCodeAt(0)) {
str = str.substring(1, str.length - 1).trim();
}
slashIndex = str.lastIndexOf('/');
if (slashIndex > 0 && slashIndex < str.length - 1) {
ip = str.substring(0, slashIndex).trim();
condition.ip = ip;
condition.prefixLength = parseInt(str.substring(slashIndex + 1).trim(), 10);
} else if (slashIndex < 0) {
// Bare IP with no prefix — default to /32 for IPv4, /128 for IPv6.
// This restores the old parseIp behaviour for bare-IP entries and avoids
// silently producing a /0 match-all.
if (str.indexOf(':') >= 0) {
// IPv6 address — analyze() will validate via ipCidrNotationToRegExp.
condition.ip = str;
condition.prefixLength = 128;
} else if (str.indexOf('.') >= 0) {
// Looks like an IPv4 address.
condition.ip = str;
condition.prefixLength = 32;
} else {
return null;
}
} else {
condition.ip = '0.0.0.0';
condition.prefixLength = 0;
// Trailing slash or leading slash — treat as invalid.
return null;
}
if (isNaN(condition.prefixLength)) {
return null;
}
Comment thread
salarcode marked this conversation as resolved.
return condition;
}
Expand Down Expand Up @@ -1876,4 +1801,4 @@ if (typeof (exports) == 'undefined')
exports.RuleImporterSwitchy = {
switchy: Switchy,
compiler: SwitchyCompiler,
}
}
22 changes: 9 additions & 13 deletions src/lib/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -602,25 +602,21 @@ export class Utils {
public static normalizeIpForMatching(host: string): string | null {
if (!host) return null;
let h = host.trim();

// remove surrounding brackets if any
h = h.replace(/^\[|\]$/g, '');
const bracketedHost = h.match(/^\[([^\]]+)\](?::\d+)?$/);
if (bracketedHost) {
h = bracketedHost[1];
}
else {
// remove surrounding brackets if any
h = h.replace(/^\[|\]$/g, '');
}

// If there's an IPv4 tail (possibly with a port), extract it: ::ffff:192.0.2.1 or 192.0.2.1:8080
const ipv4Tail = h.match(/(\d+\.\d+\.\d+\.\d+)(?::\d+)?$/);
if (ipv4Tail) {
return ipv4Tail[1];
}

// Remove trailing :port for IPv6 hosts that lost brackets earlier (e.g. ::1:8080)
if (/:\d+$/.test(h)) {
// Only strip if it looks like a port (all digits) and the rest contains ':' (likely IPv6)
const withoutPort = h.replace(/:\d+$/, '');
if (withoutPort.indexOf(':') >= 0) {
h = withoutPort;
}
}

// If it looks like IPv6, try to expand
if (h.indexOf(':') >= 0) {
const groups = Utils.expandIPv6ToGroups(h);
Expand Down Expand Up @@ -709,4 +705,4 @@ export class Utils {

private static readonly IgnoreDomainExtensions: string[] = [
"000.nl", "999.nl", "aa.no", "ab.ca", "ab.se", "abo.pa", "ac.ae", "ac.at", "ac.be", "ac.be", "ac.cn", "ac.com", "ac.cr", "ac.cy", "ac.fj", "ac.fk", "ac.gn", "ac.id", "ac.il", "ac.im.in", "ac.in", "ac.ir", "ac.jp", "ac.mw", "ac.nz", "ac.pa", "ac.ru", "ac.rw", "ac.se", "ac.th", "ac.tj", "ac.tz", "ac.ug", "ac.uk", "ac.vn", "ac.yu", "ac.zm", "ac.zw", "act.au", "ad.jp", "adm.br", "adult.ht", "adv.br", "aero.mv", "agr.br", "ah.cn", "ah.no", "ak.us", "al.us", "alt.za", "am.br", "ar.us", "army.mil", "arq.br", "art.br", "art.do", "art.dz", "art.ht", "art.pl", "asn.au", "asn.au", "asn.lv", "asso.dz", "asso.fr", "asso.ht", "asso.mc", "ato.br", "av.tr", "az.us", "bbs.tr", "bc.ca", "bd.se", "bel.tr", "bio.br", "biz.az", "biz.cy", "biz.et", "biz.fj", "biz.mv", "biz.nr", "biz.om", "biz.pk", "biz.pl", "biz.pr", "biz.tj", "biz.tr", "biz.tt", "biz.vn", "bj.cn", "bl.uk", "bmd.br", "bu.no", "c.se", "ca.us", "cim.br", "city.za", "ck.ua", "club.tw", "cn.ua", "cng.br", "cnt.br", "co.ag", "co.ao", "co.at", "co.bw", "co.cc.cd", "co.ck", "co.cr", "co.fk", "co.gg", "co.hu", "co.id", "co.il", "co.im", "co.in", "co.ir", "co.je", "co.jp", "co.kr", "co.ls", "co.ma", "co.mu", "co.mw", "co.nz", "co.om", "co.rw", "co.th", "co.tj", "co.tt", "co.ug", "co.uk", "co.us", "co.ve", "co.yu", "co.za", "co.zm", "co.zw", "com.ac", "com.af", "com.ag", "com.ai", "com.al", "com.an", "com.ar", "com.au", "com.aw", "com.ax", "com.az", "com.bb", "com.bd", "com.bm", "com.bn", "com.bo", "com.br", "com.bs", "com.bt", "com.cd", "com.ch", "com.cn", "com.co", "com.cu", "com.cy", "com.dm", "com.do", "com.dz", "com.ec", "com.ee", "com.eg", "com.es", "com.et", "com.fj", "com.fr", "com.ge", "com.gh", "com.gi", "com.gn", "com.gp", "com.gr", "com.hk", "com.hn", "com.hr", "com.ht", "com.jm", "com.jo", "com.kh", "com.kw", "com.ky", "com.kz", "com.lb", "com.lc", "com.li", "com.lk", "com.lr", "com.lv", "com.ly", "com.mg", "com.mk", "com.mo", "com.mt", "com.mu", "com.mv", "com.mw", "com.mx", "com.my", "com.ng", "com.ni", "com.np", "com.nr", "com.om", "com.pa", "com.pe", "com.pf", "com.pg", "com.ph", "com.pk", "com.pl", "com.pr", "com.ps", "com.pt", "com.py", "com.ro", "com.ru", "com.rw", "com.sa", "com.sb", "com.sc", "com.sd", "com.sg", "com.sv", "com.sy", "com.tj", "com.tn", "com.tr", "com.tt", "com.tw", "com.ua", "com.uy", "com.ve", "com.vi", "com.vn", "com.ye", "conf.au", "conf.lv", "coop.br", "coop.ht", "coop.mv", "coop.mw", "cpa.pro", "cq.cn", "cri.nz", "csiro.au", "ct.us", "cv.ua", "d.se", "dc.us", "de.us", "dn.ua", "dni.us", "dp.ua", "dpn.br", "dr.tr", "e.se", "ebiz.tw", "ecn.br", "ed.ao", "ed.cr", "ed.jp", "edu.ac", "edu.af", "edu.al", "edu.an", "edu.au", "edu.az", "edu.bb", "edu.bd", "edu.bm", "edu.bn", "edu.bo", "edu.br", "edu.bt", "edu.cn", "edu.co", "edu.cu", "edu.dm", "edu.do", "edu.dz", "edu.ec", "edu.eg", "edu.es", "edu.et", "edu.ge", "edu.gh", "edu.gi", "edu.gp", "edu.gr", "edu.hk", "edu.hn", "edu.ht", "edu.in", "edu.jm", "edu.jo", "edu.kh", "edu.kw", "edu.ky", "edu.kz", "edu.lb", "edu.lc", "edu.lk", "edu.lr", "edu.lv", "edu.ly", "edu.mg", "edu.mo", "edu.mt", "edu.mv", "edu.mw", "edu.mx", "edu.my", "edu.ng", "edu.ni", "edu.np", "edu.nr", "edu.om", "edu.pa", "edu.pe", "edu.pf", "edu.pk", "edu.pl", "edu.pr", "edu.ps", "edu.pt", "edu.py", "edu.rw", "edu.sa", "edu.sb", "edu.sc", "edu.sd", "edu.sg", "edu.sv", "edu.tj", "edu.tr", "edu.tt", "edu.tw", "edu.ua", "edu.vi", "edu.vn", "edu.za", "eng.br", "ens.tn", "esp.br", "etc.br", "eti.br", "eun.eg", "f.se", "fam.pk", "far.br", "fed.us", "fh.se", "fhs.no", "fhsk.se", "fhv.se", "fi.cr", "fie.ee", "fin.ec", "fin.tn", "firm.ht", "firm.in", "fj.cn", "fl.us", "fm.br", "fm.no", "fnd.br", "fot.br", "from.hr", "fst.br", "g.se", "g12.br", "ga.us", "game.tw", "gd.cn", "geek.nz", "gen.in", "gen.nz", "gen.tr", "ggf.br", "go.cr", "go.id", "go.jp", "go.th", "go.tj", "go.tz", "go.ug", "gob.bo", "gob.do", "gob.es", "gob.hn", "gob.mx", "gob.ni", "gob.pa", "gob.pe", "gob.pk", "gob.sv", "gok.pk", "gon.pk", "gop.pk", "gos.pk", "gouv.fr", "gouv.ht", "gouv.rw", "gov.ac", "gov.ae", "gov.af", "gov.al", "gov.ar", "gov.au", "gov.az", "gov.bb", "gov.bd", "gov.bf", "gov.bm", "gov.bo", "gov.br", "gov.bt", "gov.by", "gov.ch", "gov.cn", "gov.co", "gov.cu", "gov.cx", "gov.dm", "gov.do", "gov.dz", "gov.ec", "gov.eg", "gov.et", "gov.fj", "gov.fk", "gov.ge", "gov.gh", "gov.gi", "gov.gn", "gov.gr", "gov.hk", "gov.ie", "gov.il", "gov.im", "gov.in", "gov.ir", "gov.it", "gov.jm", "gov.jo", "gov.kh", "gov.kw", "gov.ky", "gov.kz", "gov.lb", "gov.lc", "gov.li", "gov.lk", "gov.lr", "gov.lt", "gov.lu", "gov.lv", "gov.ly", "gov.ma", "gov.mg", "gov.mo", "gov.mt", "gov.mv", "gov.mw", "gov.my", "gov.ng", "gov.np", "gov.nr", "gov.om", "gov.ph", "gov.pk", "gov.pl", "gov.pr", "gov.ps", "gov.pt", "gov.py", "gov.rw", "gov.sa", "gov.sb", "gov.sc", "gov.sd", "gov.sg", "gov.sy", "gov.tj", "gov.tn", "gov.to", "gov.tp", "gov.tr", "gov.tt.tv", "gov.tv", "gov.tw", "gov.ua", "gov.uk", "gov.vi", "gov.vn", "gov.za", "gov.zm", "gov.zw", "govt.nz", "gr.jp", "gs.cn", "gub.uy", "gv.ao", "gv.at", "gx.cn", "gz.cn", "h.se", "ha.cn", "hb.cn", "he.cn", "hi.cn", "hi.us", "hl.cn", "hl.no", "hm.no", "hn.cn", "i.se", "ia.us", "id.au", "id.lv", "id.ly", "id.us", "idf.il", "idn.sg", "idv.hk", "idv.tw", "if.ua", "il.us", "imb.br", "in.th", "in.us", "ind.br", "ind.in", "ind.tn", "inf.br", "inf.cu", "info.au", "info.az", "info.cy", "info.ec", "info.et", "info.fj", "info.ht", "info.hu", "info.mv", "info.nr", "info.pl", "info.pr", "info.ro", "info.sd", "info.tn", "info.tr", "info.tt", "info.ve", "info.vn", "ing.pa", "inima.al", "int.ar", "int.az", "int.bo", "int.lk", "int.mv", "int.mw", "int.pt", "int.ru", "int.rw", "int.tj", "int.vn", "intl.tn", "ip6.ar", "ip6.pa", "iris.ar", "iris.pa", "isa.us", "isla.pr", "it.ao", "iwi.nz", "iz.hr", "jet.uk", "jl.cn", "jor.br", "js.cn", "jx.cn", "k.se", "k12.il", "k12.tr", "kh.ua", "kiev.ua", "km.ua", "kr.ua", "ks.ua", "ks.us", "kv.ua", "ky.us", "la.us", "law.pro", "law.za", "lel.br", "lg.jp", "lg.ua", "ln.cn", "ltd.co.im", "ltd.cy", "ltd.gi", "ltd.lk", "ltd.uk", "lviv.ua", "m.se", "ma.us", "mat.br", "mb.ca", "md.us", "me.uk", "me.us", "med.br", "med.ec", "med.ht", "med.ly", "med.om", "med.pa", "med.pro", "med.sa", "med.sd", "mi.th", "mi.us", "mil.ac", "mil.ae", "mil.ar", "mil.az", "mil.bd", "mil.bo", "mil.br", "mil.by", "mil.co", "mil.do", "mil.ec", "mil.eg", "mil.fj", "mil.ge", "mil.gh", "mil.hn", "mil.in", "mil.jo", "mil.kh", "mil.kw", "mil.kz", "mil.lt", "mil.lu", "mil.lv", "mil.mg", "mil.mv", "mil.my", "mil.no", "mil.np", "mil.nz", "mil.om", "mil.pe", "mil.pl", "mil.rw", "mil.se", "mil.tj", "mil.tr", "mil.tw", "mil.uk", "mil.uy", "mil.za", "mk.ua", "mn.us", "mo.us", "mod.gi", "mod.uk", "mr.no", "ms.us", "msk.ru", "mt.us", "muni.il", "mus.br", "n.se", "name.ae", "name.af", "name.az", "name.cy", "name.et", "name.fj", "name.hr", "name.mv", "name.my", "name.pr", "name.ro", "name.tj", "name.tr", "name.tt", "name.vn", "nat.tn", "navy.mil", "nb.ca", "nc.us", "nd.us", "ne.jp", "ne.tz", "ne.ug", "ne.us", "nel.uk", "net.ac", "net.ae", "net.af", "net.ag", "net.ai", "net.al", "net.an", "net.ar", "net.au", "net.az", "net.bb", "net.bd", "net.bm", "net.bn", "net.bo", "net.br", "net.bs", "net.bt", "net.cd", "net.ch", "net.cn", "net.co", "net.cu", "net.cy", "net.dm", "net.do", "net.dz", "net.ec", "net.eg", "net.et", "net.fj", "net.fk", "net.ge", "net.gg", "net.gn", "net.gp", "net.gr", "net.hk", "net.hn", "net.ht", "net.il", "net.im", "net.in", "net.ir", "net.je", "net.jm", "net.jo", "net.kh", "net.kw", "net.ky", "net.kz", "net.lb", "net.li", "net.lk", "net.lr", "net.lu", "net.lv", "net.ly", "net.ma", "net.mo", "net.mt", "net.mv", "net.mw", "net.mx", "net.my", "net.ng", "net.ni", "net.np", "net.nr", "net.nz", "net.om", "net.pa", "net.pe", "net.pg", "net.pk", "net.pl", "net.pr", "net.ps", "net.pt", "net.py", "net.ru", "net.rw", "net.sa", "net.sb", "net.sc", "net.sd", "net.sg", "net.sy", "net.th", "net.tj", "net.tn", "net.tr", "net.tt", "net.tw", "net.ua", "net.uk", "net.uy", "net.ve", "net.vn", "net.ye", "net.za", "nf.ca", "ngo.lk", "ngo.pl", "ngo.za", "nh.us", "nhs.uk", "nic.im", "nic.in", "nic.uk", "nj.us", "nl.ca", "nl.no", "nls.uk", "nm.cn", "nm.us", "nom.adae", "nom.ag", "nom.ai", "nom.br", "nom.co", "nom.es", "nom.fk", "nom.fr", "nom.mg", "nom.ni", "nom.pa", "nom.pe", "nom.ro", "nom.za", "nome.pt", "not.br", "ns.ca", "nsn.us", "nsw.au", "nt.au", "nt.ca", "nt.no", "nt.ro", "ntr.br", "nu.ca", "nv.us", "nx.cn", "ny.us", "o.se", "od.ua", "odo.br", "of.no", "off.ai", "og.ao", "oh.us", "ok.us", "ol.no", "on.ca", "or.at", "or.cr", "or.id", "or.jp", "or.kr", "or.th", "or.tz", "or.ug", "or.us", "org.ac", "org.ae", "org.ag", "org.ai", "org.al", "org.an", "org.au", "org.az", "org.bb", "org.bd", "org.bm", "org.bn", "org.bo", "org.br", "org.bs", "org.bt", "org.bw", "org.cd", "org.ch", "org.cn", "org.co", "org.cu", "org.cy", "org.dm", "org.do", "org.dz", "org.ec", "org.ee", "org.eg", "org.es", "org.et", "org.fj", "org.fk", "org.ge", "org.gg", "org.gh", "org.gi", "org.gn", "org.gp", "org.gr", "org.hk", "org.hn", "org.ht", "org.hu", "org.il", "org.im", "org.in", "org.ir", "org.je", "org.jm", "org.jo", "org.kh", "org.kw", "org.ky", "org.kz", "org.lb", "org.lc", "org.li", "org.lk", "org.lr", "org.ls", "org.lu", "org.lv", "org.ly", "org.ma", "org.mg", "org.mk", "org.mo", "org.mt", "org.mv", "org.mw", "org.mx", "org.my", "org.ng", "org.ni", "org.np", "org.nr", "org.nz", "org.om", "org.pa", "org.pe", "org.pf", "org.pk", "org.pl", "org.pr", "org.ps", "org.pt", "org.py", "org.ro", "org.ru", "org.sa", "org.sc", "org.sd", "org.se", "org.sg", "org.sv", "org.tj", "org.tn", "org.tr", "org.tt", "org.tw", "org.ua", "org.uk", "org.uy", "org.ve", "org.vi", "org.vn", "org.yu", "org.za", "org.zm", "org.zw", "oz.au", "pa.us", "pb.ao", "pe.ca", "per.kh", "per.sg", "perso.ht", "pl.ua", "plc.co.im", "plc.ly", "plc.uk", "plo.ps", "pol.dz", "pol.ht", "pol.tr", "pp.az", "pp.ru", "pp.se", "ppg.br", "prd.fr", "prd.mg", "pri.ee", "priv.at", "priv.hu", "pro.ae", "pro.br", "pro.cy", "pro.ec", "pro.fj", "pro.ht", "pro.mv", "pro.om", "pro.pr", "pro.tt", "pro.vn", "psc.br", "psi.br", "pub.sa", "publ.pt", "pvt.ge", "qc.ca", "qh.cn", "qld.au", "qsl.br", "rec.br", "rec.ro", "red.sv", "rel.ht", "res.in", "ri.us", "rl.no", "rv.ua", "s.se", "sa.au", "sa.cr", "sc.cn", "sc.ug", "sc.us", "sch.ae", "sch.ir", "sch.lk", "sch.ly", "sch.om", "sch.sa", "sch.uk", "sch.zm", "sci.eg", "sd.cn", "sd.us", "sec.ps", "sf.no", "sh.cn", "shop.ht", "sk.ca", "sld.do", "sld.pa", "slg.br", "sn.cn", "soc.lk", "soros.al", "sport.hu", "srv.br", "sshn.se", "st.no", "sumy.ua", "sx.cn", "t.se", "tas.au", "te.ua", "tel.tr", "tirana.al", "tj.cn", "tm.cy", "tm.fr", "tm.hu", "tm.mc", "tm.mg", "tm.no", "tm.ro", "tm.se", "tm.za", "tmp.br", "tn.us", "tr.no", "trd.br", "tur.br", "tv.bo", "tv.br", "tv.sd", "tx.us", "u.se", "uniti.al", "upt.al", "uri.ar", "uri.pa", "us.com", "ut.us", "va.no", "va.us", "vet.br", "vf.no", "vgs.no", "vic.au", "vn.ua", "vt.us", "w.se", "wa.au", "wa.us", "waw.pl", "web.do", "web.lk", "web.pk", "web.tj", "web.tr", "web.ve", "wi.us", "wv.us", "www.ro", "x.se", "xj.cn", "xz.cn", "y.se", "yk.ca", "yn.cn", "z.se", "zj.cn", "zlg.br", "zp.ua", "zt.ua"]
}
}
Loading