/// <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)); } }
/// <summary> /// Add all the rules in <paramref name="tldRules"/> to <paramref name="structure"/>. /// </summary> /// <param name="structure">The structure to appened the rule.</param> /// <param name="tldRules">The rules to append.</param> public static void AddRules(this DomainDataStructure structure, [NotNull] IEnumerable <TldRule> tldRules) { foreach (TldRule tldRule in tldRules) { structure.AddRule(tldRule); } }
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)); }
private static void FindMatches([NotNull] IEnumerable <string> parts, [NotNull] DomainDataStructure structure, List <TldRule> matches) { if (structure.TldRule != null) { matches.Add(structure.TldRule); } string part = parts.FirstOrDefault(); if (string.IsNullOrEmpty(part)) { return; } if (structure.Nested.TryGetValue(part, out DomainDataStructure foundStructure)) { FindMatches(parts.Skip(1), foundStructure, matches); } if (structure.Nested.TryGetValue("*", out foundStructure)) { FindMatches(parts.Skip(1), foundStructure, matches); } }
/// <summary> /// Creates a DomainParser based on an already initialized tree. /// </summary> /// <param name="initializedDataStructure">An already initialized tree.</param> /// <param name="domainNormalizer">An <see cref="IDomainNormalizer"/>.</param> public DomainParser(DomainDataStructure initializedDataStructure, IDomainNormalizer domainNormalizer = null) : this(domainNormalizer) { _domainDataStructure = initializedDataStructure; }