class MailParser::RFC2822::Scanner

Constants

ATEXT_RE
CTEXT_RE
DTEXT_RE
QTEXT_RE
TEXT_RE
UTEXT_RE

Attributes

comments[R]

Public Class Methods

new(header_type, str) click to toggle source
# File lib/mailparser/rfc2822/scanner.rb, line 15
def initialize(header_type, str)
  @header_type = header_type
  @comments = []
  @token = []
  @token_idx = {}
  @ss = StringScanner.new(str)
end

Public Instance Methods

cfws(ss) click to toggle source

scan from after “(” to end of comment part @return [String] comment

# File lib/mailparser/rfc2822/scanner.rb, line 73
def cfws(ss)
  comments = []
  while true
    c = cfws_sub(ss)
    ss.skip(/\s+/)
    comments << "(#{c})"
    break unless @ss.scan(/\(/)
  end
  @comments.concat comments
  return comments.join
end
cfws_sub(ss) click to toggle source

process comment part @return [String] comment part

# File lib/mailparser/rfc2822/scanner.rb, line 87
def cfws_sub(ss)
  ret = ""
  until ss.eos? do
    if ss.scan(/(\s*(\\[#{TEXT_RE}]|[#{CTEXT_RE}]))*\s*/o) then
      ret << ss.matched
    end
    if ss.scan(/\)/) then         # return when ")"
      return ret
    elsif ss.scan(/\(/) then      # recursive when "("
      c = cfws_sub(ss)
      break if c.nil?
      ret << "(" << c << ")"
    else
      raise MailParser::ParseError, ss.rest
    end
  end
  # error when ")" don't exist
  raise MailParser::ParseError, ss.rest
end
get_comment(s, e) click to toggle source

@param [Integer] s start index @param [Integer] e end index

# File lib/mailparser/rfc2822/scanner.rb, line 109
def get_comment(s, e)
  a = @token[s..e].select{|i| i =~ /^\s*\(/}.map{|i| i.strip}
  return a
end
get_comment_by_id(s_id, e_id) click to toggle source

@param [Integer] s_id start object id @param [Integer] e_id end object id

# File lib/mailparser/rfc2822/scanner.rb, line 116
def get_comment_by_id(s_id, e_id)
  s = s_id ? @token_idx[s_id] : 0
  e = e_id ? @token_idx[e_id] : -1
  return get_comment(s, e)
end
rest() click to toggle source
# File lib/mailparser/rfc2822/scanner.rb, line 67
def rest()
  @ss.rest
end
scan() { |:NO_FOLD_QUOTE, s| ... } click to toggle source
# File lib/mailparser/rfc2822/scanner.rb, line 25
def scan()
  until @ss.eos?
    case
    when s = @ss.scan(/\s*\(/)
      @token << cfws(@ss)
      @token_idx[@token.last.object_id] = @token.size-1
    when s = @ss.scan(/\s+/)
      @token << s
      @token_idx[s.object_id] = @token.size-1
    when s = @ss.scan(/\"(\\[#{TEXT_RE}]|[#{QTEXT_RE}])*\"/o)
      @token << s
      @token_idx[s.object_id] = @token.size-1
      yield [:NO_FOLD_QUOTE, s]
    when s = @ss.scan(/\"(\s*(\\[#{TEXT_RE}]|[#{QTEXT_RE}]))*\s*\"/o)
      @token << s
      @token_idx[s.object_id] = @token.size-1
      yield [:QUOTED_STRING, s]
    when s = @ss.scan(/\[(\\[#{TEXT_RE}]|[#{DTEXT_RE}])*\]/o)
      @token << s
      @token_idx[s.object_id] = @token.size-1
      yield [:NO_FOLD_LITERAL, s]
    when s = @ss.scan(/\[(\s*(\\[#{TEXT_RE}]|[#{DTEXT_RE}]))*\s*\]/o)
      @token << s
      @token_idx[s.object_id] = @token.size-1
      yield [:DOMAIN_LITERAL, s]
    when s = @ss.scan(/[#{ATEXT_RE}]+/o)
      @token << s
      @token_idx[s.object_id] = @token.size-1
      if s =~ /\A\d+\z/ then
        yield [:DIGIT, s]
      else
        yield [:ATOM, s]
      end
    when s = @ss.scan(/./)
      @token << s
      @token_idx[s.object_id] = @token.size-1
      yield [s, s]
    end
  end
  yield nil
end