|
ferencd@0
|
1 //
|
|
ferencd@0
|
2 // VMime library (http://www.vmime.org)
|
|
ferencd@0
|
3 // Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
|
|
ferencd@0
|
4 //
|
|
ferencd@0
|
5 // This program is free software; you can redistribute it and/or
|
|
ferencd@0
|
6 // modify it under the terms of the GNU General Public License as
|
|
ferencd@0
|
7 // published by the Free Software Foundation; either version 3 of
|
|
ferencd@0
|
8 // the License, or (at your option) any later version.
|
|
ferencd@0
|
9 //
|
|
ferencd@0
|
10 // This program is distributed in the hope that it will be useful,
|
|
ferencd@0
|
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
ferencd@0
|
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
ferencd@0
|
13 // General Public License for more details.
|
|
ferencd@0
|
14 //
|
|
ferencd@0
|
15 // You should have received a copy of the GNU General Public License along
|
|
ferencd@0
|
16 // with this program; if not, write to the Free Software Foundation, Inc.,
|
|
ferencd@0
|
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
ferencd@0
|
18 //
|
|
ferencd@0
|
19 // Linking this library statically or dynamically with other modules is making
|
|
ferencd@0
|
20 // a combined work based on this library. Thus, the terms and conditions of
|
|
ferencd@0
|
21 // the GNU General Public License cover the whole combination.
|
|
ferencd@0
|
22 //
|
|
ferencd@0
|
23
|
|
ferencd@0
|
24 #include "vmime/address.hpp"
|
|
ferencd@0
|
25
|
|
ferencd@0
|
26 #include "vmime/mailbox.hpp"
|
|
ferencd@0
|
27 #include "vmime/mailboxGroup.hpp"
|
|
ferencd@0
|
28
|
|
ferencd@0
|
29 #include "vmime/parserHelpers.hpp"
|
|
ferencd@0
|
30
|
|
ferencd@0
|
31
|
|
ferencd@0
|
32 namespace vmime
|
|
ferencd@0
|
33 {
|
|
ferencd@0
|
34
|
|
ferencd@0
|
35
|
|
ferencd@0
|
36 address::address()
|
|
ferencd@0
|
37 {
|
|
ferencd@0
|
38 }
|
|
ferencd@0
|
39
|
|
ferencd@0
|
40
|
|
ferencd@0
|
41 /*
|
|
ferencd@0
|
42
|
|
ferencd@0
|
43 RFC #2822:
|
|
ferencd@0
|
44 3.4. ADDRESS SPECIFICATION
|
|
ferencd@0
|
45
|
|
ferencd@0
|
46 Addresses occur in several message header fields to indicate senders
|
|
ferencd@0
|
47 and recipients of messages. An address may either be an individual
|
|
ferencd@0
|
48 mailbox, or a group of mailboxes.
|
|
ferencd@0
|
49
|
|
ferencd@0
|
50 address = mailbox / group
|
|
ferencd@0
|
51
|
|
ferencd@0
|
52 mailbox = name-addr / addr-spec
|
|
ferencd@0
|
53
|
|
ferencd@0
|
54 name-addr = [display-name] angle-addr
|
|
ferencd@0
|
55
|
|
ferencd@0
|
56 angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
|
|
ferencd@0
|
57
|
|
ferencd@0
|
58 group = display-name ":" [mailbox-list / CFWS] ";"
|
|
ferencd@0
|
59 [CFWS]
|
|
ferencd@0
|
60
|
|
ferencd@0
|
61 display-name = phrase
|
|
ferencd@0
|
62
|
|
ferencd@0
|
63 mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list
|
|
ferencd@0
|
64
|
|
ferencd@0
|
65 address-list = (address *("," address)) / obs-addr-list
|
|
ferencd@0
|
66
|
|
ferencd@0
|
67 */
|
|
ferencd@0
|
68
|
|
ferencd@0
|
69 shared_ptr <address> address::parseNext
|
|
ferencd@0
|
70 (const parsingContext& ctx, const string& buffer, const size_t position,
|
|
ferencd@0
|
71 const size_t end, size_t* newPosition, bool *isLastAddressOfGroup)
|
|
ferencd@0
|
72 {
|
|
ferencd@0
|
73 bool escaped = false;
|
|
ferencd@0
|
74 bool quoted = false;
|
|
ferencd@0
|
75 bool quotedRFC2047 = false;
|
|
ferencd@0
|
76 bool inRouteAddr = false;
|
|
ferencd@0
|
77 bool isGroup = false;
|
|
ferencd@0
|
78 bool stop = false;
|
|
ferencd@0
|
79 int commentLevel = 0;
|
|
ferencd@0
|
80
|
|
ferencd@0
|
81 if (isLastAddressOfGroup)
|
|
ferencd@0
|
82 *isLastAddressOfGroup = false;
|
|
ferencd@0
|
83
|
|
ferencd@0
|
84 size_t pos = position;
|
|
ferencd@0
|
85
|
|
ferencd@0
|
86 while (pos < end && parserHelpers::isSpace(buffer[pos]))
|
|
ferencd@0
|
87 ++pos;
|
|
ferencd@0
|
88
|
|
ferencd@0
|
89 const size_t start = pos;
|
|
ferencd@0
|
90
|
|
ferencd@0
|
91 while (!stop && pos < end)
|
|
ferencd@0
|
92 {
|
|
ferencd@0
|
93 if (escaped)
|
|
ferencd@0
|
94 {
|
|
ferencd@0
|
95 escaped = false;
|
|
ferencd@0
|
96 }
|
|
ferencd@0
|
97 else
|
|
ferencd@0
|
98 {
|
|
ferencd@0
|
99 switch (buffer[pos])
|
|
ferencd@0
|
100 {
|
|
ferencd@0
|
101 case '\\':
|
|
ferencd@0
|
102 escaped = true;
|
|
ferencd@0
|
103 break;
|
|
ferencd@0
|
104 case '"':
|
|
ferencd@0
|
105 quoted = !quoted;
|
|
ferencd@0
|
106 break;
|
|
ferencd@0
|
107 case '<':
|
|
ferencd@0
|
108 inRouteAddr = true;
|
|
ferencd@0
|
109 break;
|
|
ferencd@0
|
110 case '>':
|
|
ferencd@0
|
111 inRouteAddr = false;
|
|
ferencd@0
|
112 break;
|
|
ferencd@0
|
113
|
|
ferencd@0
|
114 case '(':
|
|
ferencd@0
|
115
|
|
ferencd@0
|
116 ++commentLevel;
|
|
ferencd@0
|
117 break;
|
|
ferencd@0
|
118
|
|
ferencd@0
|
119 case ')':
|
|
ferencd@0
|
120
|
|
ferencd@0
|
121 if (commentLevel > 0)
|
|
ferencd@0
|
122 --commentLevel;
|
|
ferencd@0
|
123
|
|
ferencd@0
|
124 break;
|
|
ferencd@0
|
125
|
|
ferencd@0
|
126 case '=':
|
|
ferencd@0
|
127
|
|
ferencd@0
|
128 if (commentLevel == 0 && !quoted && !quotedRFC2047 && pos + 1 < end && buffer[pos + 1] == '?')
|
|
ferencd@0
|
129 {
|
|
ferencd@0
|
130 ++pos;
|
|
ferencd@0
|
131 quotedRFC2047 = true;
|
|
ferencd@0
|
132 }
|
|
ferencd@0
|
133
|
|
ferencd@0
|
134 break;
|
|
ferencd@0
|
135
|
|
ferencd@0
|
136 case '?':
|
|
ferencd@0
|
137
|
|
ferencd@0
|
138 if (commentLevel == 0 && quotedRFC2047 && pos + 1 < end && buffer[pos + 1] == '=')
|
|
ferencd@0
|
139 {
|
|
ferencd@0
|
140 ++pos;
|
|
ferencd@0
|
141 quotedRFC2047 = false;
|
|
ferencd@0
|
142 }
|
|
ferencd@0
|
143
|
|
ferencd@0
|
144 break;
|
|
ferencd@0
|
145
|
|
ferencd@0
|
146 default:
|
|
ferencd@0
|
147 {
|
|
ferencd@0
|
148 if (commentLevel == 0 && !quoted && !quotedRFC2047 && !inRouteAddr)
|
|
ferencd@0
|
149 {
|
|
ferencd@0
|
150 switch (buffer[pos])
|
|
ferencd@0
|
151 {
|
|
ferencd@0
|
152 case ';':
|
|
ferencd@0
|
153
|
|
ferencd@0
|
154 if (isGroup)
|
|
ferencd@0
|
155 {
|
|
ferencd@0
|
156 if (pos + 1 < end && buffer[pos + 1] == ',')
|
|
ferencd@0
|
157 ++pos;
|
|
ferencd@0
|
158 }
|
|
ferencd@0
|
159
|
|
ferencd@0
|
160 if (isLastAddressOfGroup)
|
|
ferencd@0
|
161 *isLastAddressOfGroup = true;
|
|
ferencd@0
|
162
|
|
ferencd@0
|
163 stop = true;
|
|
ferencd@0
|
164 break;
|
|
ferencd@0
|
165
|
|
ferencd@0
|
166 case ':':
|
|
ferencd@0
|
167
|
|
ferencd@0
|
168 isGroup = true;
|
|
ferencd@0
|
169 break;
|
|
ferencd@0
|
170
|
|
ferencd@0
|
171 case ',':
|
|
ferencd@0
|
172
|
|
ferencd@0
|
173 if (!isGroup) stop = true;
|
|
ferencd@0
|
174 break;
|
|
ferencd@0
|
175 }
|
|
ferencd@0
|
176 }
|
|
ferencd@0
|
177
|
|
ferencd@0
|
178 break;
|
|
ferencd@0
|
179 }
|
|
ferencd@0
|
180
|
|
ferencd@0
|
181 }
|
|
ferencd@0
|
182 }
|
|
ferencd@0
|
183
|
|
ferencd@0
|
184 if (!stop)
|
|
ferencd@0
|
185 ++pos;
|
|
ferencd@0
|
186 }
|
|
ferencd@0
|
187
|
|
ferencd@0
|
188 if (newPosition)
|
|
ferencd@0
|
189 {
|
|
ferencd@0
|
190 if (pos == end)
|
|
ferencd@0
|
191 *newPosition = end;
|
|
ferencd@0
|
192 else
|
|
ferencd@0
|
193 *newPosition = pos + 1; // ',' or ';'
|
|
ferencd@0
|
194 }
|
|
ferencd@0
|
195
|
|
ferencd@0
|
196 // Parse extracted address (mailbox or group)
|
|
ferencd@0
|
197 if (pos != start)
|
|
ferencd@0
|
198 {
|
|
ferencd@0
|
199 shared_ptr <address> parsedAddress;
|
|
ferencd@0
|
200
|
|
ferencd@0
|
201 if (isGroup)
|
|
ferencd@0
|
202 parsedAddress = make_shared <mailboxGroup>();
|
|
ferencd@0
|
203 else
|
|
ferencd@0
|
204 parsedAddress = make_shared <mailbox>();
|
|
ferencd@0
|
205
|
|
ferencd@0
|
206 parsedAddress->parse(ctx, buffer, start, pos, NULL);
|
|
ferencd@0
|
207 parsedAddress->setParsedBounds(start, pos);
|
|
ferencd@0
|
208
|
|
ferencd@0
|
209 return (parsedAddress);
|
|
ferencd@0
|
210 }
|
|
ferencd@0
|
211
|
|
ferencd@0
|
212 return null;
|
|
ferencd@0
|
213 }
|
|
ferencd@0
|
214
|
|
ferencd@0
|
215
|
|
ferencd@0
|
216 } // vmime
|