class PublicSuffix::List

A {PublicSuffix::List} is a collection of one or more {PublicSuffix::Rule}.

Given a {PublicSuffix::List}, you can add or remove {PublicSuffix::Rule}, iterate all items in the list or search for the first rule which matches a specific domain name.

# Create a new list
list =  PublicSuffix::List.new

# Push two rules to the list
list << PublicSuffix::Rule.factory("it")
list << PublicSuffix::Rule.factory("com")

# Get the size of the list
list.size
# => 2

# Search for the rule matching given domain
list.find("example.com")
# => #<PublicSuffix::Rule::Normal>
list.find("example.org")
# => nil

You can create as many {PublicSuffix::List} you want. The {PublicSuffix::List.default} rule list is used to tokenize and validate a domain.

Constants

DEFAULT_LIST_PATH

Attributes

rules[R]

Public Class Methods

default(**options) click to toggle source

Gets the default rule list.

Initializes a new {PublicSuffix::List} parsing the content of {PublicSuffix::List.default_list_content}, if required.

@return [PublicSuffix::List]

# File lib/public_suffix/list.rb, line 48
def self.default(**options)
  @default ||= parse(File.read(DEFAULT_LIST_PATH), options)
end
default=(value) click to toggle source

Sets the default rule list to value.

@param value [PublicSuffix::List] the new list @return [PublicSuffix::List]

# File lib/public_suffix/list.rb, line 56
def self.default=(value)
  @default = value
end
new() { |self| ... } click to toggle source

Initializes an empty {PublicSuffix::List}.

@yield [self] Yields on self. @yieldparam [PublicSuffix::List] self The newly created instance.

# File lib/public_suffix/list.rb, line 103
def initialize
  @rules = {}
  yield(self) if block_given?
end
parse(input, private_domains: true) click to toggle source

Parse given input treating the content as Public Suffix List.

See publicsuffix.org/format/ for more details about input format.

@param string [#each_line] the list to parse @param private_domains [Boolean] whether to ignore the private domains section @return [PublicSuffix::List]

# File lib/public_suffix/list.rb, line 67
def self.parse(input, private_domains: true)
  comment_token = "//".freeze
  private_token = "===BEGIN PRIVATE DOMAINS===".freeze
  section = nil # 1 == ICANN, 2 == PRIVATE

  new do |list|
    input.each_line do |line|
      line.strip!
      case # rubocop:disable Style/EmptyCaseCondition

      # skip blank lines
      when line.empty?
        next

      # include private domains or stop scanner
      when line.include?(private_token)
        break if !private_domains
        section = 2

      # skip comments
      when line.start_with?(comment_token)
        next

      else
        list.add(Rule.factory(line, private: section == 2))

      end
    end
  end
end

Public Instance Methods

<<(rule)
Alias for: add
==(other) click to toggle source

Checks whether two lists are equal.

List one is equal to two, if two is an instance of {PublicSuffix::List} and each PublicSuffix::Rule::* in list one is available in list two, in the same order.

@param other [PublicSuffix::List] the List to compare @return [Boolean]

# File lib/public_suffix/list.rb, line 117
def ==(other)
  return false unless other.is_a?(List)
  equal?(other) || @rules == other.rules
end
Also aliased as: eql?
add(rule) click to toggle source

Adds the given object to the list and optionally refreshes the rule index.

@param rule [PublicSuffix::Rule::*] the rule to add to the list @return [self]

# File lib/public_suffix/list.rb, line 137
def add(rule)
  @rules[rule.value] = rule_to_entry(rule)
  self
end
Also aliased as: <<
clear() click to toggle source

Removes all rules.

@return [self]

# File lib/public_suffix/list.rb, line 160
def clear
  @rules.clear
  self
end
default_rule() click to toggle source

Gets the default rule.

@see PublicSuffix::Rule.default_rule

@return [PublicSuffix::Rule::*]

# File lib/public_suffix/list.rb, line 222
def default_rule
  PublicSuffix::Rule.default
end
each(&block) click to toggle source

Iterates each rule in the list.

# File lib/public_suffix/list.rb, line 124
def each(&block)
  Enumerator.new do |y|
    @rules.each do |key, node|
      y << entry_to_rule(node, key)
    end
  end.each(&block)
end
empty?() click to toggle source

Checks whether the list is empty.

@return [Boolean]

# File lib/public_suffix/list.rb, line 153
def empty?
  @rules.empty?
end
eql?(other)
Alias for: ==
find(name, default: default_rule, **options) click to toggle source

Finds and returns the rule corresponding to the longest public suffix for the hostname.

@param name [#to_s] the hostname @param default [PublicSuffix::Rule::*] the default rule to return in case no rule matches @return [PublicSuffix::Rule::*]

# File lib/public_suffix/list.rb, line 170
def find(name, default: default_rule, **options)
  rule = select(name, **options).inject do |l, r|
    return r if r.class == Rule::Exception
    l.length > r.length ? l : r
  end
  rule || default
end
size() click to toggle source

Gets the number of rules in the list.

@return [Integer]

# File lib/public_suffix/list.rb, line 146
def size
  @rules.size
end

Private Instance Methods

entry_to_rule(entry, value) click to toggle source
# File lib/public_suffix/list.rb, line 234
def entry_to_rule(entry, value)
  entry.type.new(value: value, length: entry.length, private: entry.private)
end
rule_to_entry(rule) click to toggle source
# File lib/public_suffix/list.rb, line 238
def rule_to_entry(rule)
  Rule::Entry.new(rule.class, rule.length, rule.private)
end
select(name, ignore_private: false) click to toggle source

Selects all the rules matching given hostame.

If `ignore_private` is set to true, the algorithm will skip the rules that are flagged as private domain. Note that the rules will still be part of the loop. If you frequently need to access lists ignoring the private domains, you should create a list that doesn't include these domains setting the `private_domains: false` option when calling {.parse}.

Note that this method is currently private, as you should not rely on it. Instead, the public interface is {#find}. The current internal algorithm allows to return all matching rules, but different data structures may not be able to do it, and instead would return only the match. For this reason, you should rely on {#find}.

@param name [#to_s] the hostname @param ignore_private [Boolean] @return [Array<PublicSuffix::Rule::*>]

# File lib/public_suffix/list.rb, line 194
def select(name, ignore_private: false)
  name = name.to_s

  parts = name.split(DOT).reverse!
  index = 0
  query = parts[index]
  rules = []

  loop do
    match = @rules[query]
    if !match.nil? && (ignore_private == false || match.private == false)
      rules << entry_to_rule(match, query)
    end

    index += 1
    break if index >= parts.size
    query = parts[index] + DOT + query
  end

  rules
end