|
a/src/internfile/mh_mail.cpp |
|
b/src/internfile/mh_mail.cpp |
1 |
#ifndef lint
|
1 |
#ifndef lint
|
2 |
static char rcsid[] = "@(#$Id: mh_mail.cpp,v 1.29 2007-01-17 13:53:40 dockes Exp $ (C) 2005 J.F.Dockes";
|
2 |
static char rcsid[] = "@(#$Id: mh_mail.cpp,v 1.30 2007-10-17 11:40:35 dockes Exp $ (C) 2005 J.F.Dockes";
|
3 |
#endif
|
3 |
#endif
|
4 |
/*
|
4 |
/*
|
5 |
* This program is free software; you can redistribute it and/or modify
|
5 |
* This program is free software; you can redistribute it and/or modify
|
6 |
* it under the terms of the GNU General Public License as published by
|
6 |
* it under the terms of the GNU General Public License as published by
|
7 |
* the Free Software Foundation; either version 2 of the License, or
|
7 |
* the Free Software Foundation; either version 2 of the License, or
|
|
... |
|
... |
133 |
m_idx++;
|
133 |
m_idx++;
|
134 |
m_havedoc = m_idx < (int)m_attachments.size();
|
134 |
m_havedoc = m_idx < (int)m_attachments.size();
|
135 |
return res;
|
135 |
return res;
|
136 |
}
|
136 |
}
|
137 |
|
137 |
|
138 |
// Decode according to content transfer encoding
|
138 |
// Decode according to content transfer encoding. May actually do nothing,
|
139 |
static bool decodeBody(const string& cte, const string& body, string& decoded,
|
139 |
// which will be indicated by the *respp argument pointing to the original
|
140 |
const string** respp)
|
140 |
// text on exit
|
|
|
141 |
static bool decodeBody(const string& cte, // Content transfer encoding
|
|
|
142 |
const string& body, // Source text
|
|
|
143 |
string& decoded, // Decoded text if actual decoding
|
|
|
144 |
const string** respp // Decoding Indicator
|
|
|
145 |
)
|
141 |
{
|
146 |
{
|
142 |
// By default, there is no encoding (7bit,8bit,raw). Also in case of
|
147 |
// By default, there is no encoding (7bit,8bit,raw). Also in case of
|
143 |
// decoding error
|
148 |
// decoding error
|
144 |
*respp = &body;
|
149 |
*respp = &body;
|
145 |
|
150 |
|
146 |
if (!stringlowercmp("quoted-printable", cte)) {
|
151 |
if (!stringlowercmp("quoted-printable", cte)) {
|
147 |
if (!qp_decode(body, decoded)) {
|
152 |
if (!qp_decode(body, decoded)) {
|
148 |
LOGERR(("decodeBody: quoted-printable decoding failed !\n"));
|
153 |
LOGERR(("decodeBody: quoted-printable decoding failed !\n"));
|
|
|
154 |
LOGDEB((" Body: \n%s\n", body.c_str()));
|
149 |
return false;
|
155 |
return false;
|
150 |
}
|
156 |
}
|
151 |
*respp = &decoded;
|
157 |
*respp = &decoded;
|
152 |
} else if (!stringlowercmp("base64", cte)) {
|
158 |
} else if (!stringlowercmp("base64", cte)) {
|
153 |
if (!base64_decode(body, decoded)) {
|
159 |
if (!base64_decode(body, decoded)) {
|
|
|
160 |
// base64 encoding errors are actually relatively common
|
154 |
LOGERR(("decodeBody: base64 decoding failed !. body [%s]\n",
|
161 |
LOGERR(("decodeBody: base64 decoding failed !\n"));
|
155 |
body.c_str()));
|
162 |
LOGDEB((" Body: \n%s\n", body.c_str()));
|
156 |
return false;
|
163 |
return false;
|
157 |
}
|
164 |
}
|
158 |
*respp = &decoded;
|
165 |
*respp = &decoded;
|
159 |
}
|
166 |
}
|
160 |
return true;
|
167 |
return true;
|
|
... |
|
... |
169 |
m_havedoc = false;
|
176 |
m_havedoc = false;
|
170 |
return false;
|
177 |
return false;
|
171 |
}
|
178 |
}
|
172 |
MHMailAttach *att = m_attachments[m_idx];
|
179 |
MHMailAttach *att = m_attachments[m_idx];
|
173 |
|
180 |
|
174 |
LOGDEB1(("processAttach:content-type: %s\n", att->m_contentType.c_str()));
|
|
|
175 |
m_metaData["mimetype"] = att->m_contentType;
|
181 |
m_metaData["mimetype"] = att->m_contentType;
|
176 |
m_metaData["charset"] = att->m_charset;
|
182 |
m_metaData["charset"] = att->m_charset;
|
177 |
m_metaData["filename"] = att->m_filename;
|
183 |
m_metaData["filename"] = att->m_filename;
|
|
|
184 |
// Change the title to something helpul
|
|
|
185 |
m_metaData["title"] = att->m_filename + " (" + m_subject + ")";
|
|
|
186 |
LOGDEB1((" processAttach:ct [%s] cs [%s] fn [%s]\n",
|
|
|
187 |
att->m_contentType.c_str(),
|
|
|
188 |
att->m_charset.c_str(),
|
|
|
189 |
att->m_filename.c_str()));
|
178 |
|
190 |
|
179 |
m_metaData["content"] = "";
|
191 |
m_metaData["content"] = "";
|
180 |
string& body = m_metaData["content"];
|
192 |
string& body = m_metaData["content"];
|
181 |
att->m_part->getBody(body, 0, att->m_part->bodylength);
|
193 |
att->m_part->getBody(body, 0, att->m_part->bodylength);
|
182 |
string decoded;
|
194 |
string decoded;
|
|
... |
|
... |
184 |
if (!decodeBody(att->m_contentTransferEncoding, body, decoded, &bdp)) {
|
196 |
if (!decodeBody(att->m_contentTransferEncoding, body, decoded, &bdp)) {
|
185 |
return false;
|
197 |
return false;
|
186 |
}
|
198 |
}
|
187 |
if (bdp != &body)
|
199 |
if (bdp != &body)
|
188 |
body = decoded;
|
200 |
body = decoded;
|
|
|
201 |
|
|
|
202 |
// Special case for text/plain content. Internfile should deal
|
|
|
203 |
// with this but it expects text/plain to be utf-8 already, so we
|
|
|
204 |
// handle the transcoding if needed
|
|
|
205 |
if (m_metaData["mimetype"] == "text/plain" &&
|
|
|
206 |
stringicmp(m_metaData["charset"], "UTF-8")) {
|
|
|
207 |
string utf8;
|
|
|
208 |
if (!transcode(body, utf8, m_metaData["charset"], "UTF-8")) {
|
|
|
209 |
LOGERR((" processAttach: transcode to utf-8 failed "
|
|
|
210 |
"for charset [%s]\n", m_metaData["charset"].c_str()));
|
|
|
211 |
// Just let it through and hope for the best...
|
|
|
212 |
} else {
|
|
|
213 |
body = utf8;
|
|
|
214 |
}
|
|
|
215 |
}
|
|
|
216 |
|
|
|
217 |
// Ipath
|
189 |
char nbuf[10];
|
218 |
char nbuf[10];
|
190 |
sprintf(nbuf, "%d", m_idx);
|
219 |
sprintf(nbuf, "%d", m_idx);
|
191 |
m_metaData["ipath"] = nbuf;
|
220 |
m_metaData["ipath"] = nbuf;
|
|
|
221 |
|
192 |
return true;
|
222 |
return true;
|
193 |
}
|
223 |
}
|
194 |
|
224 |
|
195 |
// Transform a single message into a document. The subject becomes the
|
225 |
// Transform a single message into a document. The subject becomes the
|
196 |
// title, and any simple body part with a content-type of text or html
|
226 |
// title, and any simple body part with a content-type of text or html
|
|
... |
|
... |
240 |
}
|
270 |
}
|
241 |
text += string("Date: ") + transcoded + string("\n");
|
271 |
text += string("Date: ") + transcoded + string("\n");
|
242 |
}
|
272 |
}
|
243 |
if (doc->h.getFirstHeader("Subject", hi)) {
|
273 |
if (doc->h.getFirstHeader("Subject", hi)) {
|
244 |
rfc2047_decode(hi.getValue(), transcoded);
|
274 |
rfc2047_decode(hi.getValue(), transcoded);
|
245 |
if (depth == 1)
|
275 |
if (depth == 1) {
|
246 |
m_metaData["title"] = transcoded;
|
276 |
m_metaData["title"] = transcoded;
|
|
|
277 |
m_subject = transcoded;
|
|
|
278 |
}
|
247 |
text += string("Subject: ") + transcoded + string("\n");
|
279 |
text += string("Subject: ") + transcoded + string("\n");
|
248 |
}
|
280 |
}
|
249 |
text += '\n';
|
281 |
text += '\n';
|
250 |
|
282 |
|
251 |
LOGDEB2(("MimeHandlerMail::processMsg:ismultipart %d mime subtype '%s'\n",
|
283 |
LOGDEB2(("MimeHandlerMail::processMsg:ismultipart %d mime subtype '%s'\n",
|
|
... |
|
... |
404 |
if (doc->h.getFirstHeader("Content-Transfer-Encoding", hi)) {
|
436 |
if (doc->h.getFirstHeader("Content-Transfer-Encoding", hi)) {
|
405 |
cte = hi.getValue();
|
437 |
cte = hi.getValue();
|
406 |
}
|
438 |
}
|
407 |
|
439 |
|
408 |
// If the Content-Disposition is not inline, we treat it as
|
440 |
// If the Content-Disposition is not inline, we treat it as
|
409 |
// attachment, as per rfc2183. We don't process attachments
|
441 |
// attachment, as per rfc2183.
|
410 |
// for now, except for indexing/displaying the file name
|
|
|
411 |
// If it is inline but not text or html, same thing.
|
442 |
// If it is inline but not text or html, same thing.
|
412 |
if (stringlowercmp("inline", content_disposition.value) ||
|
443 |
if (stringlowercmp("inline", content_disposition.value) ||
|
413 |
(stringlowercmp("text/plain", content_type.value) &&
|
444 |
(stringlowercmp("text/plain", content_type.value) &&
|
414 |
stringlowercmp("text/html", content_type.value)) ) {
|
445 |
stringlowercmp("text/html", content_type.value)) ) {
|
415 |
if (!filename.empty()) {
|
446 |
if (!filename.empty()) {
|
|
... |
|
... |
419 |
out += filename;
|
450 |
out += filename;
|
420 |
if (m_forPreview)
|
451 |
if (m_forPreview)
|
421 |
out += "]";
|
452 |
out += "]";
|
422 |
out += "\n\n";
|
453 |
out += "\n\n";
|
423 |
}
|
454 |
}
|
424 |
LOGDEB(("walkmime: pushing attchmnt fn [%s]\n", filename.c_str()));
|
|
|
425 |
MHMailAttach *att = new MHMailAttach;
|
455 |
MHMailAttach *att = new MHMailAttach;
|
426 |
if (att == 0) {
|
456 |
if (att == 0) {
|
427 |
LOGERR(("Out of memory\n"));
|
457 |
LOGERR(("Out of memory\n"));
|
428 |
return;
|
458 |
return;
|
429 |
}
|
459 |
}
|
|
... |
|
... |
431 |
stringtolower(att->m_contentType);
|
461 |
stringtolower(att->m_contentType);
|
432 |
att->m_filename = filename;
|
462 |
att->m_filename = filename;
|
433 |
att->m_charset = charset;
|
463 |
att->m_charset = charset;
|
434 |
att->m_contentTransferEncoding = cte;
|
464 |
att->m_contentTransferEncoding = cte;
|
435 |
att->m_part = doc;
|
465 |
att->m_part = doc;
|
|
|
466 |
LOGDEB(("walkmime: attachmnt: ct [%s] cte [%s] cs [%s] fn [%s]\n",
|
|
|
467 |
att->m_contentType.c_str(),
|
|
|
468 |
att->m_contentTransferEncoding.c_str(),
|
|
|
469 |
att->m_charset.c_str(),
|
|
|
470 |
filename.c_str()));
|
436 |
m_attachments.push_back(att);
|
471 |
m_attachments.push_back(att);
|
437 |
return;
|
472 |
return;
|
438 |
}
|
473 |
}
|
439 |
|
474 |
|
440 |
// We are dealing with an inline part of text/plain or text/html type
|
475 |
// We are dealing with an inline part of text/plain or text/html type
|