1 /*
2 ** Copyright 2004, Double Precision Inc.
3 **
4 ** See COPYING for distribution information.
5 */
6 #include "libmail_config.h"
7 #include "rfcaddr.H"
8 #include "headers.H"
9 #include "rfc2047encode.H"
10 #include "rfc2047decode.H"
11 #include "rfc2045/rfc2045.h"
12 #include <errno.h>
13
14 using namespace std;
15
~Header()16 mail::Header::~Header()
17 {
18 }
19
wrap(string s)20 string mail::Header::wrap(string s) const
21 {
22 string ws=name + ": ";
23 size_t init_offset=ws.size();
24 size_t offset=init_offset;
25 string::iterator b=s.begin(), e=s.end();
26 bool first=true;
27
28 while (b != e)
29 {
30 string::iterator c=b;
31
32 while (c != e)
33 {
34 if (*c != ' ' && *c != '\t')
35 break;
36 ++c;
37 }
38
39 while (c != e)
40 {
41 if (*c == ' ' || *c == '\t')
42 break;
43 ++c;
44 }
45
46 if (c-b + offset > 76 && !first)
47 {
48 while (b != c && (*b == ' ' || *b == '\t'))
49 ++b;
50 if (b == e)
51 break;
52
53 ws += "\n";
54 ws.insert(ws.end(), init_offset, ' ');
55 offset=init_offset;
56 }
57 ws.insert(ws.end(), b, c);
58 offset += c-b;
59 b=c;
60 first=false;
61 }
62 return ws;
63 }
64
~plain()65 mail::Header::plain::~plain()
66 {
67 }
68
clone()69 mail::Header *mail::Header::plain::clone() const
70 {
71 mail::Header::plain *c=new plain(name, text);
72
73 if (!c)
74 throw strerror(errno);
75 return c;
76 }
77
toString()78 string mail::Header::plain::toString() const
79 {
80 return wrap(text);
81 }
82
encode(string text,string charset,string lang)83 string mail::Header::encoded::encode(string text, string charset, string lang)
84 {
85 if (lang.size() > 0)
86 charset += "*" + lang;
87
88 return mail::rfc2047::encode(text, charset);
89 }
90
encoded(string name,string text,string charset,string lang)91 mail::Header::encoded::encoded(string name,
92 string text, string charset, string lang)
93 : Header::plain(name, encode(text, charset, lang))
94 {
95 }
96
~encoded()97 mail::Header::encoded::~encoded()
98 {
99 }
100
addresslist(string name)101 mail::Header::addresslist::addresslist(string name)
102 : mail::Header(name)
103 {
104 }
105
addresslist(string name,const std::vector<mail::emailAddress> & addressesArg)106 mail::Header::addresslist::addresslist(string name,
107 const std::vector<mail::emailAddress>
108 &addressesArg)
109 : mail::Header(name), addresses(addressesArg)
110 {
111 }
112
~addresslist()113 mail::Header::addresslist::~addresslist()
114 {
115 }
116
clone()117 mail::Header *mail::Header::addresslist::clone() const
118 {
119 mail::Header::addresslist *c=new addresslist(name, addresses);
120
121 if (!c)
122 throw strerror(errno);
123 return c;
124 }
125
toString()126 std::string mail::Header::addresslist::toString() const
127 {
128 return mail::address::toString(name + ": ",
129 addresses);
130 }
131
mime(string name)132 mail::Header::mime::mime(string name)
133 : mail::Header(name)
134 {
135 }
136
mime(string name,string valueArg)137 mail::Header::mime::mime(string name, string valueArg)
138 : mail::Header(name), value(valueArg)
139 {
140 }
141
fromString(string header)142 mail::Header::mime mail::Header::mime::fromString(string header)
143 {
144 size_t n=header.find(':');
145
146 if (n != std::string::npos)
147 ++n;
148 else
149 n=header.size();
150
151 mime m(header.substr(0, n));
152
153 header=header.substr(n);
154
155 rfc2045_parse_mime_header(header.c_str(), cb_type, cb_param, &m);
156 return m;
157 }
158
cb_type(const char * t,void * void_arg)159 void mail::Header::mime::cb_type(const char *t, void *void_arg)
160 {
161 mail::Header::mime *a=(mail::Header::mime *)void_arg;
162
163 a->value=t;
164 mail::upper(a->value);
165 }
166
cb_param(const char * name,const char * value,void * void_arg)167 void mail::Header::mime::cb_param(const char *name,
168 const char *value,
169 void *void_arg)
170 {
171 mail::Header::mime *a=(mail::Header::mime *)void_arg;
172
173 string n=name;
174
175 mail::upper(n);
176
177 if (!a->parameters.exists(name))
178 a->parameters.set_simple(name, value);
179 }
180
~mime()181 mail::Header::mime::~mime()
182 {
183 }
184
toString()185 string mail::Header::mime::toString() const
186 {
187 string h=name + ": " + value;
188 size_t init_offset=name.size()+2;
189
190 const_parameter_iterator b=begin();
191 const_parameter_iterator e=end();
192
193 size_t offset=h.size();
194
195 while (b != e)
196 {
197 string w=b->first;
198 string s=b->second;
199
200 string::iterator sb=s.begin(), se=s.end();
201
202 if (sb != se)
203 w += "=";
204
205 while (sb != se)
206 {
207 if (!strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789?*+-/=_", *sb))
208 break;
209 ++sb;
210 }
211
212 if (sb == se)
213 {
214 w += s;
215 }
216 else
217 {
218 w += "\"";
219
220 string::iterator p=s.begin();
221
222 for (sb=p; sb != se; sb++)
223 {
224 if (*sb == '\\' || *sb == '"')
225 {
226 w += string(p, sb) + "\\";
227 w += *sb;
228 p=sb+1;
229 }
230 }
231 w += string(p, sb);
232 w += "\"";
233 }
234
235 if (offset + w.size() > 74)
236 {
237 h += ";\n";
238 h.insert(h.end(), init_offset, ' ');
239 offset=init_offset;
240 }
241 else
242 {
243 h += "; ";
244 offset += 2;
245 }
246 h += w;
247 offset += w.size();
248 ++b;
249 }
250 return h;
251 }
252
clone()253 mail::Header *mail::Header::mime::clone() const
254 {
255 mail::Header::mime *c=new mime(name, value);
256
257 if (!c)
258 throw strerror(errno);
259 c->parameters=parameters;
260 return c;
261 }
262
listitem(const listitem & hArg)263 mail::Header::listitem::listitem(const listitem &hArg)
264 : h(hArg.h->clone())
265 {
266 }
267
listitem(const mail::Header & hArg)268 mail::Header::listitem::listitem(const mail::Header &hArg)
269 : h(hArg.clone())
270 {
271 }
272
~listitem()273 mail::Header::listitem::~listitem()
274 {
275 delete h;
276 }
277
278 mail::Header::listitem &mail::Header::listitem::operator=(const listitem &hArg)
279 {
280 Header *p=hArg.h->clone();
281
282 delete h;
283 h=p;
284 return *this;
285 }
286
287 mail::Header::listitem &mail::Header::listitem::operator=(const Header &hArg)
288 {
289 Header *p=hArg.clone();
290
291 delete h;
292 h=p;
293 return *this;
294 }
295
list()296 mail::Header::list::list()
297 {
298 }
299
~list()300 mail::Header::list::~list()
301 {
302 }
303
string()304 mail::Header::list::operator string() const
305 {
306 string h;
307
308 const_iterator b=begin();
309 const_iterator e=end();
310
311 while (b != e)
312 {
313 const Header &hh= *b;
314 h += hh.toString();
315 h += "\n";
316 ++b;
317 }
318 return h;
319 }
320