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