Class: MailParser::RFC2822::Scanner

Inherits:
Object
  • Object
show all
Defined in:
lib/mailparser/rfc2822/scanner.rb

Constant Summary collapse

TEXT_RE =
'\x00-\x7f'
QTEXT_RE =
'\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f'
ATEXT_RE =
'A-Za-z0-9\!\#\$\%\&\'\*\+\\-\/\=\?\^\_\`\{\|\}\~'
CTEXT_RE =
'\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x27\x2a-\x5b\x5d-\x7f'
UTEXT_RE =
'\x00-\x7f'
DTEXT_RE =
'\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x5e-\x7e'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(header_type, str) ⇒ Scanner

Returns a new instance of Scanner.



15
16
17
18
19
20
21
# 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

Instance Attribute Details

#commentsObject (readonly)

Returns the value of attribute comments.



23
24
25
# File 'lib/mailparser/rfc2822/scanner.rb', line 23

def comments
  @comments
end

Instance Method Details

#cfws(ss) ⇒ String

scan from after “(” to end of comment part

Returns:

  • (String)

    comment



73
74
75
76
77
78
79
80
81
82
83
# 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) ⇒ String

process comment part

Returns:

  • (String)

    comment part

Raises:



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# 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) ⇒ Object

Parameters:

  • s (Integer)

    start index

  • e (Integer)

    end index



109
110
111
112
# 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) ⇒ Object

Parameters:

  • s_id (Integer)

    start object id

  • e_id (Integer)

    end object id



116
117
118
119
120
# 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

#restObject



67
68
69
# File 'lib/mailparser/rfc2822/scanner.rb', line 67

def rest()
  @ss.rest
end

#scan {|nil| ... } ⇒ Object

Yields:

  • (nil)


25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# 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