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
|