class Hermes::Dictionary

A parser for header fields like DKIM-Signature

Example

ds = Dictionary.new v: 1, a: "rsa-sha256", c: "relaxed/relaxed", ...

ds = Dictionary.parse "v=1; a=rsa-sha256; c=relaxed/relaxed; ..."
ds[ "a"]  #=> "0123456"

Attributes

hash[R]
to_h[R]
to_hash[R]

Public Class Methods

new(hash = nil) click to toggle source

Create a Dictionary object from a value and a hash.

ds = Dictionary.new :v => 1, :a => "rsa-sha256",
                            :c => "relaxed/relaxed", ...
# File lib/hermes/contents.rb, line 107
def initialize hash = nil
  case hash
    when URLText::Dict then
      @hash = hash
    else
      @hash = URLText::Dict.new
      @hash.merge! hash if hash
  end
end

Public Instance Methods

[]( key) → str or nil click to toggle source

Find value of key.

# File lib/hermes/contents.rb, line 122
def [] key ; @hash[ key.to_sym] ; end
Also aliased as: field
encode() click to toggle source

Encode it for a mail header field.

# File lib/hermes/contents.rb, line 170
def encode
  f, *rest = encoded_parts
  if f then
    r = [ f]
    rest.each { |e|
      r.last << SEP
      r.push e
    }
  end
  r
end
field(key ;)
Alias for: []
keys() → ary click to toggle source

Returns a list of all contained keys

c = Contents.new "text/html; boundary=0123456"
c.keys                #=> [ :boundary]
# File lib/hermes/contents.rb, line 141
def keys ; @hash.keys ; end
method_missing(sym, *args) click to toggle source
Calls superclass method
# File lib/hermes/contents.rb, line 125
def method_missing sym, *args
  if sym =~ /[^a-z_]/ or args.any? then
    super
  else
    field sym
  end
end
parse(line) click to toggle source

Create a Dictionary object out of a string from a mail header field.

ds = Dictionary.parse "v=1; a=rsa-sha256; c=relaxed/relaxed; ..."
ds[ "a"]  #=> "0123456"
# File lib/hermes/contents.rb, line 46
def parse line
  rest = line.strip
  hash = parse_hash rest
  new hash
end
quote()
Alias for: to_s
to_s() click to toggle source

Show the line as readable text.

# File lib/hermes/contents.rb, line 150
def to_s
  quoted_parts.join "#{SEP} "
end
Also aliased as: quote
urltext() click to toggle source
# File lib/hermes/contents.rb, line 52
def urltext
  @urltext ||= URLText.new mask_space: true
end

Private Instance Methods

encoded_parts() click to toggle source
# File lib/hermes/contents.rb, line 183
def encoded_parts
  r = @hash.map { |k,v|
    case v
      when nil    then next
      when true   then v = k
      when false  then v = ""
      when String then nil
      else             v = v.to_s
    end
    if not v.ascii_only? or v =~ /[=;"]/ then
      enc = v.encoding
      if (l = ($env||ENV)[ "LANG"]) then
        l, = l.split /\W/, 2
        lang = l.gsub "_", "-"
      end
      v = [ enc, lang, (Dictionary.urltext.encode v)].join "'"
    end
    "#{k}=#{v}"
  }
  r.compact!
  r
end
parse_hash(rest) click to toggle source
# File lib/hermes/contents.rb, line 58
def parse_hash rest
  hash = Hash.new { |h,k| h[ k] = [] }
  asts = {}
  while rest.notempty? do
    key, rest = if rest =~ REA then
      ast = $1
      ord = $2.to_i if $2
      [ $`, $']
    else
      [ rest, ""]
    end
    key = key.to_sym
    asts[ key] = ast
    val, rest = if not ast and rest =~ /\A"(.*?)"(?:#{SEP}\s*|\z)/ then
      [ $1, $']
    else
      rest.split RES, 2
    end
    if ord then
      hash[ key][ ord] = val
    else
      hash[ key] = val
    end
  end
  r = URLText::Dict.new
  hash.keys.each { |k|
    v = hash[ k]
    Array === v and v = v.join
    if asts[ k] then
      enc, lang, val = v.split "'"
      val.force_encoding enc
      v = URLText.decode val
    end
    r[ k] = v
  }
  r
end
quoted_parts() click to toggle source
# File lib/hermes/contents.rb, line 156
def quoted_parts
  @hash.map { |k,v|
    case v
      when true                            then v = k
      when false                           then v = nil
      when TSPECIAL, /\s/, /[\0-\x1f\x7f]/ then v = v.inspect
    end
    "#{k}=#{v}"
  }
end