index and display attachment file names

This commit is contained in:
dockes 2006-09-05 08:05:02 +00:00
parent 258bad35c0
commit 92b930f2c4
2 changed files with 57 additions and 33 deletions

View File

@ -1,5 +1,5 @@
#ifndef lint #ifndef lint
static char rcsid[] = "@(#$Id: mh_mail.cpp,v 1.14 2006-04-07 08:51:15 dockes Exp $ (C) 2005 J.F.Dockes"; static char rcsid[] = "@(#$Id: mh_mail.cpp,v 1.15 2006-09-05 08:05:02 dockes Exp $ (C) 2005 J.F.Dockes";
#endif #endif
/* /*
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -47,9 +47,6 @@ static char rcsid[] = "@(#$Id: mh_mail.cpp,v 1.14 2006-04-07 08:51:15 dockes Exp
using namespace std; using namespace std;
#endif /* NO_NAMESPACES */ #endif /* NO_NAMESPACES */
static void
walkmime(RclConfig *cnf, string &out, Binc::MimePart& doc, int depth);
MimeHandlerMail::~MimeHandlerMail() MimeHandlerMail::~MimeHandlerMail()
{ {
if (m_vfp) { if (m_vfp) {
@ -241,18 +238,17 @@ MimeHandlerMail::processone(const string &fn, Binc::MimeDocument& doc,
docout.text += string("Subject: ") + transcoded + string("\n"); docout.text += string("Subject: ") + transcoded + string("\n");
} }
LOGDEB2(("MimeHandlerMail::processone: ismultipart %d mime subtype '%s'\n", LOGDEB2(("MimeHandlerMail::processone:ismultipart %d mime subtype '%s'\n",
doc.isMultipart(), doc.getSubType().c_str())); doc.isMultipart(), doc.getSubType().c_str()));
walkmime(m_conf, docout.text, doc, 0); walkmime(docout.text, doc, 0);
// LOGDEB(("MimeHandlerMail::processone: text: '%s'\n", docout.text.c_str())); LOGDEB2(("MimeHandlerMail::processone:text:[%s]\n", docout.text.c_str()));
return MimeHandler::MHDone; return MimeHandler::MHDone;
} }
// Recursively walk the message mime parts and concatenate all the // Recursively walk the message mime parts and concatenate all the
// inline html or text that we find anywhere. // inline html or text that we find anywhere.
static void walkmime(RclConfig *cnf, string &out, Binc::MimePart& doc, void MimeHandlerMail::walkmime(string &out, Binc::MimePart& doc, int depth)
int depth)
{ {
if (depth > 5) { if (depth > 5) {
LOGINFO(("walkmime: max depth exceeded\n")); LOGINFO(("walkmime: max depth exceeded\n"));
@ -269,7 +265,7 @@ static void walkmime(RclConfig *cnf, string &out, Binc::MimePart& doc,
if (!stringicmp("mixed", doc.getSubType()) || if (!stringicmp("mixed", doc.getSubType()) ||
!stringicmp("related", doc.getSubType())) { !stringicmp("related", doc.getSubType())) {
for (it = doc.members.begin(); it != doc.members.end();it++) { for (it = doc.members.begin(); it != doc.members.end();it++) {
walkmime(cnf, out, *it, depth+1); walkmime(out, *it, depth+1);
} }
} else if (!stringicmp("alternative", doc.getSubType())) { } else if (!stringicmp("alternative", doc.getSubType())) {
std::vector<Binc::MimePart>::iterator ittxt, ithtml; std::vector<Binc::MimePart>::iterator ittxt, ithtml;
@ -292,15 +288,14 @@ static void walkmime(RclConfig *cnf, string &out, Binc::MimePart& doc,
} }
if (ittxt != doc.members.end()) { if (ittxt != doc.members.end()) {
LOGDEB2(("walkmime: alternative: chose text/plain part\n")) LOGDEB2(("walkmime: alternative: chose text/plain part\n"))
walkmime(cnf, out, *ittxt, depth+1); walkmime(out, *ittxt, depth+1);
} else if (ithtml != doc.members.end()) { } else if (ithtml != doc.members.end()) {
LOGDEB2(("walkmime: alternative: chose text/html part\n")) LOGDEB2(("walkmime: alternative: chose text/html part\n"))
walkmime(cnf, out, *ithtml, depth+1); walkmime(out, *ithtml, depth+1);
} }
} }
} else { } else {
// If content-type is text or html and content-disposition is inline, // "Simple" part. See what it is:
// decode and add to text.
// Get and parse content-type header. // Get and parse content-type header.
Binc::HeaderItem hi; Binc::HeaderItem hi;
@ -311,6 +306,43 @@ static void walkmime(RclConfig *cnf, string &out, Binc::MimePart& doc,
LOGDEB2(("walkmime:content-type: %s\n", ctt.c_str())); LOGDEB2(("walkmime:content-type: %s\n", ctt.c_str()));
MimeHeaderValue content_type; MimeHeaderValue content_type;
parseMimeHeaderValue(ctt, content_type); parseMimeHeaderValue(ctt, content_type);
// Get and parse Content-Disposition header
string ctd = "inline";
if (doc.h.getFirstHeader("Content-Disposition", hi)) {
ctd = hi.getValue();
}
MimeHeaderValue content_disposition;
parseMimeHeaderValue(ctd, content_disposition);
LOGDEB2(("Content_disposition:[%s]\n",
content_disposition.value.c_str()));
// If this is an attachment, we index the file name if any and, when
// previewing, at least show that it was there.
if (!stringlowercmp("attachment", content_disposition.value)) {
string rafn = "NoFileName", afn;
map<string,string>::const_iterator it;
it = content_disposition.params.find(string("filename"));
if (it != content_type.params.end())
rafn = it->second;
rfc2047_decode(rafn, afn);
out += "\n";
if (m_forPreview)
out += "[Attachment: ";
out += afn;
if (m_forPreview)
out += "]";
out += "\n\n";
// Attachment: we're done with this part
return;
}
// The only other disposition that interests us is "inline", and then
// this has to be plain text or html
if (stringlowercmp("inline", content_disposition.value)) {
return;
}
if (stringlowercmp("text/plain", content_type.value) && if (stringlowercmp("text/plain", content_type.value) &&
stringlowercmp("text/html", content_type.value)) { stringlowercmp("text/html", content_type.value)) {
return; return;
@ -334,17 +366,6 @@ static void walkmime(RclConfig *cnf, string &out, Binc::MimePart& doc,
!stringlowercmp("unknown", charset) ) { !stringlowercmp("unknown", charset) ) {
charset = "iso-8859-1"; charset = "iso-8859-1";
} }
// Content disposition
string ctd = "inline";
if (doc.h.getFirstHeader("Content-Disposition", hi)) {
ctd = hi.getValue();
}
MimeHeaderValue content_disposition;
parseMimeHeaderValue(ctd, content_disposition);
if (stringlowercmp("inline", content_disposition.value)) {
return;
}
// Content transfer encoding // Content transfer encoding
string cte = "7bit"; string cte = "7bit";
@ -357,7 +378,7 @@ static void walkmime(RclConfig *cnf, string &out, Binc::MimePart& doc,
string body; string body;
doc.getBody(body, 0, doc.bodylength); doc.getBody(body, 0, doc.bodylength);
// Decode content transfer encoding // Decode according to content transfer encoding
if (!stringlowercmp("quoted-printable", cte)) { if (!stringlowercmp("quoted-printable", cte)) {
string decoded; string decoded;
if (!qp_decode(body, decoded)) { if (!qp_decode(body, decoded)) {
@ -381,23 +402,24 @@ static void walkmime(RclConfig *cnf, string &out, Binc::MimePart& doc,
body = decoded; body = decoded;
} }
string transcoded; // Handle html stripping and transcoding to utf8
string utf8;
if (!stringlowercmp("text/html", content_type.value)) { if (!stringlowercmp("text/html", content_type.value)) {
MimeHandlerHtml mh; MimeHandlerHtml mh;
Rcl::Doc hdoc; Rcl::Doc hdoc;
mh.charsethint = charset; mh.charsethint = charset;
mh.mkDoc(cnf, "", body, content_type.value, hdoc); mh.mkDoc(m_conf, "", body, content_type.value, hdoc);
transcoded = hdoc.text; utf8 = hdoc.text;
} else { } else {
// Transcode to utf-8 // Transcode to utf-8
if (!transcode(body, transcoded, charset, "UTF-8")) { if (!transcode(body, utf8, charset, "UTF-8")) {
LOGERR(("walkmime: transcode failed from cs '%s' to UTF-8\n", LOGERR(("walkmime: transcode failed from cs '%s' to UTF-8\n",
charset.c_str())); charset.c_str()));
transcoded = body; utf8 = body;
} }
} }
out += string("\r\n") + transcoded; out += string("\r\n") + utf8;
LOGDEB2(("walkmime: out now: [%s]\n", out.c_str())); LOGDEB2(("walkmime: out now: [%s]\n", out.c_str()));
} }
} }

View File

@ -16,12 +16,13 @@
*/ */
#ifndef _MAIL_H_INCLUDED_ #ifndef _MAIL_H_INCLUDED_
#define _MAIL_H_INCLUDED_ #define _MAIL_H_INCLUDED_
/* @(#$Id: mh_mail.h,v 1.6 2006-04-07 08:51:15 dockes Exp $ (C) 2004 J.F.Dockes */ /* @(#$Id: mh_mail.h,v 1.7 2006-09-05 08:05:02 dockes Exp $ (C) 2004 J.F.Dockes */
#include "mimehandler.h" #include "mimehandler.h"
namespace Binc { namespace Binc {
class MimeDocument; class MimeDocument;
class MimePart;
} }
/** /**
@ -48,6 +49,7 @@ class MimeHandlerMail : public MimeHandler {
Rcl::Doc &docout); Rcl::Doc &docout);
MimeHandler::Status processmbox(const string &fn, Rcl::Doc &docout, MimeHandler::Status processmbox(const string &fn, Rcl::Doc &docout,
string &ipath); string &ipath);
void walkmime(string &out, Binc::MimePart& doc, int depth);
}; };
#endif /* _MAIL_H_INCLUDED_ */ #endif /* _MAIL_H_INCLUDED_ */