/// <summary> /// Add <paramref name="tldRule"/> to <paramref name="structure"/>. /// </summary> /// <param name="structure">The structure to appened the rule.</param> /// <param name="tldRule">The rule to append.</param> public static void AddRule(this DomainDataStructure structure, [NotNull] TldRule tldRule) { List <string> parts = tldRule.Name.Split('.').Reverse().ToList(); for (int i = 0; i < parts.Count; i++) { string domainPart = parts[i]; if (parts.Count - 1 > i) { //Check if domain exists if (!structure.Nested.ContainsKey(domainPart)) { structure.Nested.Add(domainPart, new DomainDataStructure(domainPart)); } structure = structure.Nested[domainPart]; continue; } //Check if domain exists if (structure.Nested.ContainsKey(domainPart)) { structure.Nested[domainPart].TldRule = tldRule; continue; } structure.Nested.Add(domainPart, new DomainDataStructure(domainPart, tldRule)); } }
public DomainName(string domain, TldRule tldRule) { if (string.IsNullOrEmpty(domain)) { return; } if (tldRule == null) { return; } List <string> domainParts = domain.Split('.').Reverse().ToList(); List <string> ruleParts = tldRule.Name.Split('.').Skip(tldRule.Type == TldRuleType.WildcardException ? 1 : 0).Reverse().ToList(); string tld = string.Join(".", domainParts.Take(ruleParts.Count).Reverse()); string registrableDomain = string.Join(".", domainParts.Take(ruleParts.Count + 1).Reverse()); if (domain.Equals(tld)) { return; } TLDRule = tldRule; Hostname = domain; TLD = tld; RegistrableDomain = registrableDomain; Domain = domainParts.Skip(ruleParts.Count).FirstOrDefault(); string subDomain = string.Join(".", domainParts.Skip(ruleParts.Count + 1).Reverse()); SubDomain = string.IsNullOrEmpty(subDomain) ? null : subDomain; }
private DomainName GetDomainFromParts(string domain, [NotNull] List <string> parts) { if (parts == null || parts.Count == 0 || parts.Any(x => x.Equals(string.Empty))) { throw new ParseException("Invalid domain part detected"); } DomainDataStructure structure = _domainDataStructure; List <TldRule> matches = new List <TldRule>(); FindMatches(parts, structure, matches); //Sort so exceptions are first, then by biggest label count (with wildcards at bottom) IOrderedEnumerable <TldRule> sortedMatches = matches.OrderByDescending(x => x.Type == TldRuleType.WildcardException ? 1 : 0) .ThenByDescending(x => x.LabelCount) .ThenByDescending(x => x.Name); TldRule winningRule = sortedMatches.FirstOrDefault(); //Domain is TLD if (winningRule != null && parts.Count == winningRule.LabelCount) { parts.Reverse(); string tld = string.Join(".", parts); if (winningRule.Type == TldRuleType.Wildcard) { if (tld.EndsWith(winningRule.Name.Substring(1))) { throw new ParseException("Domain is a TLD according public suffix", winningRule); } } else { if (tld.Equals(winningRule.Name)) { throw new ParseException("Domain is a TLD according public suffix", winningRule); } } throw new ParseException($"Unknown domain {domain}"); } return(new DomainName(domain, winningRule)); }
public IEnumerable <TldRule> ParseRules([NotNull] IEnumerable <string> lines) { List <TldRule> items = new List <TldRule>(); TldRuleDivision division = TldRuleDivision.Unknown; foreach (string line in lines) { //Ignore empty lines if (string.IsNullOrEmpty(line)) { continue; } //Ignore comments (and set Division) if (line.StartsWith("//")) { //Detect Division if (line.StartsWith("// ===BEGIN ICANN DOMAINS===")) { division = TldRuleDivision.ICANN; } else if (line.StartsWith("// ===END ICANN DOMAINS===")) { division = TldRuleDivision.Unknown; } else if (line.StartsWith("// ===BEGIN PRIVATE DOMAINS===")) { division = TldRuleDivision.Private; } else if (line.StartsWith("// ===END PRIVATE DOMAINS===")) { division = TldRuleDivision.Unknown; } continue; } TldRule tldRule = new TldRule(line.Trim(), division); items.Add(tldRule); } return(items); }
/// <summary> /// Parse Exception /// </summary> /// <param name="errorMessage"></param> /// <param name="winningRule"></param> public ParseException(string errorMessage, TldRule winningRule = null) { ErrorMessage = errorMessage; WinningRule = winningRule; }
/// <summary> /// Creates a new <see cref="DomainDataStructure"/> for <paramref name="domain"/>. /// </summary> /// <param name="domain">The Domain.</param> /// <param name="tldRule">The type of TLD domain.</param> public DomainDataStructure(string domain, TldRule tldRule) { Domain = domain; TldRule = tldRule; Nested = new Dictionary <string, DomainDataStructure>(); }