File: address_lists_parser.rb

package info (click to toggle)
ruby-mail 2.6.4%2Bdfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 4,256 kB
  • ctags: 1,327
  • sloc: ruby: 44,678; makefile: 3
file content (133 lines) | stat: -rw-r--r-- 4,107 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# frozen_string_literal: true
module Mail::Parsers
  class AddressListsParser
    include Mail::Utilities

    def parse(s)
      address_list = AddressListStruct.new([],[])

      if Mail::Utilities.blank?(s)
        return address_list
      end

      actions, error = Ragel.parse(:address_lists, s)
      if error
        raise Mail::Field::ParseError.new(Mail::AddressList, s, error)
      end


      phrase_s = phrase_e = qstr_s = qstr = comment_s = nil
      group_name_s = domain_s = group_name = nil
      local_dot_atom_s = local_dot_atom_e = nil
      local_dot_atom_pre_comment_e = nil
      obs_domain_list_s = nil

      address_s = 0
      address = AddressStruct.new(nil, nil, [], nil, nil, nil, nil)
      actions.each_slice(2) do |action_id, p|
        action = Mail::Parsers::Ragel::ACTIONS[action_id]
        case action

        # Phrase
        when :phrase_s then phrase_s = p
        when :phrase_e then phrase_e = p-1

        # Quoted String.
        when :qstr_s then qstr_s = p
        when :qstr_e then qstr = s[qstr_s..(p-1)]

        # Comment
        when :comment_s
          comment_s = p unless comment_s
        when :comment_e
          if address
            address.comments << s[comment_s..(p-2)]
          end
          comment_s = nil

        # Group Name
        when :group_name_s then group_name_s = p
        when :group_name_e
          if qstr
            group = qstr
            qstr = nil
          else
            group = s[group_name_s..(p-1)]
            group_name_s = nil
          end
          address_list.group_names << group
          group_name = group

          # Start next address
          address = AddressStruct.new(nil, nil, [], nil, nil, nil, nil)
          address_s = p
          address.group = group_name

        # Address
        when :address_s
          address_s = p
        when :address_e
          # Ignore address end events if they don't have
          # a matching address start event.
          next if address_s.nil?
          if address.local.nil? && local_dot_atom_pre_comment_e && local_dot_atom_s && local_dot_atom_e
            if address.domain
              address.local = s[local_dot_atom_s..local_dot_atom_e] if address
            else
              address.local = s[local_dot_atom_s..local_dot_atom_pre_comment_e] if address
            end
          end
          address.raw = s[address_s..(p-1)]
          address_list.addresses << address if address

          # Start next address
          address = AddressStruct.new(nil, nil, [], nil, nil, nil, nil)
          address.group = group_name
          address_s = nil

        # Don't set the display name until the
        # address has actually started. This allows
        # us to choose quoted_s version if it
        # exists and always use the 'full' phrase
        # version.
        when :angle_addr_s
          if qstr
            address.display_name = qstr
            qstr = nil
          elsif phrase_e
            address.display_name = s[phrase_s..phrase_e].strip
            phrase_e = phrase_s = nil
          end

        # Domain
        when :domain_s
          domain_s = p
        when :domain_e
          address.domain = s[domain_s..(p-1)].rstrip if address

        # Local
        when :local_dot_atom_s then local_dot_atom_s = p
        when :local_dot_atom_e then local_dot_atom_e = p-1
        when :local_dot_atom_pre_comment_e
          local_dot_atom_pre_comment_e = p-1
        when :local_quoted_string_e
          address.local = '"' + qstr + '"' if address

        # obs_domain_list
        when :obs_domain_list_s then obs_domain_list_s = p
        when :obs_domain_list_e
          address.obs_domain_list = s[obs_domain_list_s..(p-1)]

        else
          raise Mail::Field::ParseError.new(Mail::AddressList, s, "Failed to process unknown action: #{action}")
        end
      end

      if address_list.addresses.empty? && address_list.group_names.empty?
        raise Mail::Field::ParseError.new(Mail::AddressList, s, "Didn't find any addresses or groups")
      end

      address_list
    end
  end
end