comments and indent
This commit is contained in:
parent
385a7b9547
commit
9a9ce69647
@ -70,16 +70,16 @@ void MimeHandlerMail::clear_impl()
|
|||||||
{
|
{
|
||||||
delete m_bincdoc; m_bincdoc = 0;
|
delete m_bincdoc; m_bincdoc = 0;
|
||||||
if (m_fd >= 0) {
|
if (m_fd >= 0) {
|
||||||
close(m_fd);
|
close(m_fd);
|
||||||
m_fd = -1;
|
m_fd = -1;
|
||||||
}
|
}
|
||||||
delete m_stream; m_stream = 0;
|
delete m_stream; m_stream = 0;
|
||||||
m_idx = -1;
|
m_idx = -1;
|
||||||
m_startoftext = 0;
|
m_startoftext = 0;
|
||||||
m_subject.erase();
|
m_subject.erase();
|
||||||
for (vector<MHMailAttach*>::iterator it = m_attachments.begin();
|
for (vector<MHMailAttach*>::iterator it = m_attachments.begin();
|
||||||
it != m_attachments.end(); it++) {
|
it != m_attachments.end(); it++) {
|
||||||
delete *it;
|
delete *it;
|
||||||
}
|
}
|
||||||
m_attachments.clear();
|
m_attachments.clear();
|
||||||
}
|
}
|
||||||
@ -88,25 +88,25 @@ bool MimeHandlerMail::set_document_file_impl(const string& mt, const string &fn)
|
|||||||
{
|
{
|
||||||
LOGDEB("MimeHandlerMail::set_document_file(" << fn << ")\n");
|
LOGDEB("MimeHandlerMail::set_document_file(" << fn << ")\n");
|
||||||
if (m_fd >= 0) {
|
if (m_fd >= 0) {
|
||||||
close(m_fd);
|
close(m_fd);
|
||||||
m_fd = -1;
|
m_fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_forPreview) {
|
if (!m_forPreview) {
|
||||||
// Yes, we read the file twice. It would be possible in theory
|
// Yes, we read the file twice. It would be possible in theory
|
||||||
// to add the md5 computation to the mime analysis, but ...
|
// to add the md5 computation to the mime analysis, but ...
|
||||||
string md5, xmd5, reason;
|
string md5, xmd5, reason;
|
||||||
if (MD5File(fn, md5, &reason)) {
|
if (MD5File(fn, md5, &reason)) {
|
||||||
m_metaData[cstr_dj_keymd5] = MD5HexPrint(md5, xmd5);
|
m_metaData[cstr_dj_keymd5] = MD5HexPrint(md5, xmd5);
|
||||||
} else {
|
} else {
|
||||||
LOGERR("MimeHandlerMail: md5 [" << fn << "]: " << reason << "\n");
|
LOGERR("MimeHandlerMail: md5 [" << fn << "]: " << reason << "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_fd = open(fn.c_str(), 0);
|
m_fd = open(fn.c_str(), 0);
|
||||||
if (m_fd < 0) {
|
if (m_fd < 0) {
|
||||||
LOGERR("MimeHandlerMail::set_document_file: open(" << fn <<
|
LOGERR("MimeHandlerMail::set_document_file: open(" << fn <<
|
||||||
") errno " << errno << "\n");
|
") errno " << errno << "\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#if defined O_NOATIME && O_NOATIME != 0
|
#if defined O_NOATIME && O_NOATIME != 0
|
||||||
if (fcntl(m_fd, F_SETFL, O_NOATIME) < 0) {
|
if (fcntl(m_fd, F_SETFL, O_NOATIME) < 0) {
|
||||||
@ -117,8 +117,8 @@ bool MimeHandlerMail::set_document_file_impl(const string& mt, const string &fn)
|
|||||||
m_bincdoc = new Binc::MimeDocument;
|
m_bincdoc = new Binc::MimeDocument;
|
||||||
m_bincdoc->parseFull(m_fd);
|
m_bincdoc->parseFull(m_fd);
|
||||||
if (!m_bincdoc->isHeaderParsed() && !m_bincdoc->isAllParsed()) {
|
if (!m_bincdoc->isHeaderParsed() && !m_bincdoc->isAllParsed()) {
|
||||||
LOGERR("MimeHandlerMail::mkDoc: mime parse error for " << fn << "\n");
|
LOGERR("MimeHandlerMail::mkDoc: mime parse error for " << fn << "\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_havedoc = true;
|
m_havedoc = true;
|
||||||
return true;
|
return true;
|
||||||
@ -132,26 +132,26 @@ bool MimeHandlerMail::set_document_string_impl(const string& mt,
|
|||||||
delete m_stream;
|
delete m_stream;
|
||||||
|
|
||||||
if (!m_forPreview) {
|
if (!m_forPreview) {
|
||||||
string md5, xmd5;
|
string md5, xmd5;
|
||||||
MD5String(msgtxt, md5);
|
MD5String(msgtxt, md5);
|
||||||
m_metaData[cstr_dj_keymd5] = MD5HexPrint(md5, xmd5);
|
m_metaData[cstr_dj_keymd5] = MD5HexPrint(md5, xmd5);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_stream = new stringstream(msgtxt)) == 0 || !m_stream->good()) {
|
if ((m_stream = new stringstream(msgtxt)) == 0 || !m_stream->good()) {
|
||||||
LOGERR("MimeHandlerMail::set_document_string: stream create error."
|
LOGERR("MimeHandlerMail::set_document_string: stream create error."
|
||||||
"msgtxt.size() " << msgtxt.size() << "\n");
|
"msgtxt.size() " << msgtxt.size() << "\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
delete m_bincdoc;
|
delete m_bincdoc;
|
||||||
if ((m_bincdoc = new Binc::MimeDocument) == 0) {
|
if ((m_bincdoc = new Binc::MimeDocument) == 0) {
|
||||||
LOGERR("MimeHandlerMail::set_doc._string: new Binc:Document failed. "
|
LOGERR("MimeHandlerMail::set_doc._string: new Binc:Document failed. "
|
||||||
"Out of memory?");
|
"Out of memory?");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_bincdoc->parseFull(*m_stream);
|
m_bincdoc->parseFull(*m_stream);
|
||||||
if (!m_bincdoc->isHeaderParsed() && !m_bincdoc->isAllParsed()) {
|
if (!m_bincdoc->isHeaderParsed() && !m_bincdoc->isAllParsed()) {
|
||||||
LOGERR("MimeHandlerMail::set_document_string: mime parse error\n");
|
LOGERR("MimeHandlerMail::set_document_string: mime parse error\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_havedoc = true;
|
m_havedoc = true;
|
||||||
return true;
|
return true;
|
||||||
@ -161,14 +161,14 @@ bool MimeHandlerMail::skip_to_document(const string& ipath)
|
|||||||
{
|
{
|
||||||
LOGDEB("MimeHandlerMail::skip_to_document(" << ipath << ")\n");
|
LOGDEB("MimeHandlerMail::skip_to_document(" << ipath << ")\n");
|
||||||
if (m_idx == -1) {
|
if (m_idx == -1) {
|
||||||
// No decoding done yet. If ipath is null need do nothing
|
// No decoding done yet. If ipath is null need do nothing
|
||||||
if (ipath.empty() || ipath == "-1")
|
if (ipath.empty() || ipath == "-1")
|
||||||
return true;
|
return true;
|
||||||
// ipath points to attachment: need to decode message
|
// ipath points to attachment: need to decode message
|
||||||
if (!next_document()) {
|
if (!next_document()) {
|
||||||
LOGERR("MimeHandlerMail::skip_to_doc: next_document failed\n");
|
LOGERR("MimeHandlerMail::skip_to_doc: next_document failed\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_idx = atoi(ipath.c_str());
|
m_idx = atoi(ipath.c_str());
|
||||||
return true;
|
return true;
|
||||||
@ -179,25 +179,25 @@ bool MimeHandlerMail::next_document()
|
|||||||
LOGDEB("MimeHandlerMail::next_document m_idx " << m_idx << " m_havedoc " <<
|
LOGDEB("MimeHandlerMail::next_document m_idx " << m_idx << " m_havedoc " <<
|
||||||
m_havedoc << "\n");
|
m_havedoc << "\n");
|
||||||
if (!m_havedoc)
|
if (!m_havedoc)
|
||||||
return false;
|
return false;
|
||||||
bool res = false;
|
bool res = false;
|
||||||
|
|
||||||
if (m_idx == -1) {
|
if (m_idx == -1) {
|
||||||
m_metaData[cstr_dj_keymt] = cstr_textplain;
|
m_metaData[cstr_dj_keymt] = cstr_textplain;
|
||||||
res = processMsg(m_bincdoc, 0);
|
res = processMsg(m_bincdoc, 0);
|
||||||
LOGDEB1("MimeHandlerMail::next_document: mt " <<
|
LOGDEB1("MimeHandlerMail::next_document: mt " <<
|
||||||
m_metaData[cstr_dj_keymt] << ", att cnt " <<
|
m_metaData[cstr_dj_keymt] << ", att cnt " <<
|
||||||
m_attachments.size() << "\n");
|
m_attachments.size() << "\n");
|
||||||
const string& txt = m_metaData[cstr_dj_keycontent];
|
const string& txt = m_metaData[cstr_dj_keycontent];
|
||||||
if (m_startoftext < txt.size())
|
if (m_startoftext < txt.size())
|
||||||
m_metaData[cstr_dj_keyabstract] =
|
m_metaData[cstr_dj_keyabstract] =
|
||||||
truncate_to_word(txt.substr(m_startoftext), 250);
|
truncate_to_word(txt.substr(m_startoftext), 250);
|
||||||
if (m_attachments.size() > 0) {
|
if (m_attachments.size() > 0) {
|
||||||
m_metaData[cstr_dj_keyanc] = "t";
|
m_metaData[cstr_dj_keyanc] = "t";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_metaData[cstr_dj_keyabstract].clear();
|
m_metaData[cstr_dj_keyabstract].clear();
|
||||||
res = processAttach();
|
res = processAttach();
|
||||||
}
|
}
|
||||||
m_idx++;
|
m_idx++;
|
||||||
m_havedoc = m_idx < (int)m_attachments.size();
|
m_havedoc = m_idx < (int)m_attachments.size();
|
||||||
@ -211,30 +211,30 @@ bool MimeHandlerMail::next_document()
|
|||||||
// which will be indicated by the *respp argument pointing to the original
|
// which will be indicated by the *respp argument pointing to the original
|
||||||
// text on exit
|
// text on exit
|
||||||
static bool decodeBody(const string& cte, // Content transfer encoding
|
static bool decodeBody(const string& cte, // Content transfer encoding
|
||||||
const string& body, // Source text
|
const string& body, // Source text
|
||||||
string& decoded, // Decoded text if actual decoding
|
string& decoded, // Decoded text if actual decoding
|
||||||
const string** respp // Decoding Indicator
|
const string** respp // Decoding Indicator
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// By default, there is no encoding (7bit,8bit,raw). Also in case of
|
// By default, there is no encoding (7bit,8bit,raw). Also in case of
|
||||||
// decoding error
|
// decoding error
|
||||||
*respp = &body;
|
*respp = &body;
|
||||||
|
|
||||||
if (!stringlowercmp("quoted-printable", cte)) {
|
if (!stringlowercmp("quoted-printable", cte)) {
|
||||||
if (!qp_decode(body, decoded)) {
|
if (!qp_decode(body, decoded)) {
|
||||||
LOGERR("decodeBody: quoted-printable decoding failed !\n");
|
LOGERR("decodeBody: quoted-printable decoding failed !\n");
|
||||||
LOGDEB(" Body: \n" << body << "\n");
|
LOGDEB(" Body: \n" << body << "\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*respp = &decoded;
|
*respp = &decoded;
|
||||||
} else if (!stringlowercmp("base64", cte)) {
|
} else if (!stringlowercmp("base64", cte)) {
|
||||||
if (!base64_decode(body, decoded)) {
|
if (!base64_decode(body, decoded)) {
|
||||||
// base64 encoding errors are actually relatively common
|
// base64 encoding errors are actually relatively common
|
||||||
LOGERR("decodeBody: base64 decoding failed !\n");
|
LOGERR("decodeBody: base64 decoding failed !\n");
|
||||||
LOGDEB(" Body: \n" << body << "\n");
|
LOGDEB(" Body: \n" << body << "\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*respp = &decoded;
|
*respp = &decoded;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -243,10 +243,10 @@ bool MimeHandlerMail::processAttach()
|
|||||||
{
|
{
|
||||||
LOGDEB("MimeHandlerMail::processAttach() m_idx " << m_idx << "\n");
|
LOGDEB("MimeHandlerMail::processAttach() m_idx " << m_idx << "\n");
|
||||||
if (!m_havedoc)
|
if (!m_havedoc)
|
||||||
return false;
|
return false;
|
||||||
if (m_idx >= (int)m_attachments.size()) {
|
if (m_idx >= (int)m_attachments.size()) {
|
||||||
m_havedoc = false;
|
m_havedoc = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
MHMailAttach *att = m_attachments[m_idx];
|
MHMailAttach *att = m_attachments[m_idx];
|
||||||
|
|
||||||
@ -263,31 +263,31 @@ bool MimeHandlerMail::processAttach()
|
|||||||
body.clear();
|
body.clear();
|
||||||
att->m_part->getBody(body, 0, att->m_part->bodylength);
|
att->m_part->getBody(body, 0, att->m_part->bodylength);
|
||||||
{
|
{
|
||||||
string decoded;
|
string decoded;
|
||||||
const string *bdp;
|
const string *bdp;
|
||||||
if (!decodeBody(att->m_contentTransferEncoding, body, decoded, &bdp)) {
|
if (!decodeBody(att->m_contentTransferEncoding, body, decoded, &bdp)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (bdp != &body)
|
if (bdp != &body)
|
||||||
body.swap(decoded);
|
body.swap(decoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case for application/octet-stream: try to better
|
// Special case for application/octet-stream: try to better
|
||||||
// identify content, using file name if set
|
// identify content, using file name if set
|
||||||
if (m_metaData[cstr_dj_keymt] == "application/octet-stream" &&
|
if (m_metaData[cstr_dj_keymt] == "application/octet-stream" &&
|
||||||
!m_metaData[cstr_dj_keyfn].empty()) {
|
!m_metaData[cstr_dj_keyfn].empty()) {
|
||||||
string mt = mimetype(m_metaData[cstr_dj_keyfn], 0,
|
string mt = mimetype(m_metaData[cstr_dj_keyfn], 0,
|
||||||
m_config, false);
|
m_config, false);
|
||||||
if (!mt.empty())
|
if (!mt.empty())
|
||||||
m_metaData[cstr_dj_keymt] = mt;
|
m_metaData[cstr_dj_keymt] = mt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case for text/plain content. Internfile should deal
|
// Special case for text/plain content. Internfile should deal
|
||||||
// with this but it expects text/plain to be utf-8 already, so we
|
// with this but it expects text/plain to be utf-8 already, so we
|
||||||
// handle the transcoding if needed. Same kind of issue for the MD5
|
// handle the transcoding if needed. Same kind of issue for the MD5
|
||||||
if (m_metaData[cstr_dj_keymt] == cstr_textplain) {
|
if (m_metaData[cstr_dj_keymt] == cstr_textplain) {
|
||||||
if (!txtdcode("MimeHandlerMail::processAttach")) {
|
if (!txtdcode("MimeHandlerMail::processAttach")) {
|
||||||
body.clear();
|
body.clear();
|
||||||
} else if (!m_forPreview) {
|
} else if (!m_forPreview) {
|
||||||
string md5, xmd5;
|
string md5, xmd5;
|
||||||
MD5String(body, md5);
|
MD5String(body, md5);
|
||||||
@ -314,76 +314,76 @@ bool MimeHandlerMail::processMsg(Binc::MimePart *doc, int depth)
|
|||||||
{
|
{
|
||||||
LOGDEB2("MimeHandlerMail::processMsg: depth " << depth << "\n");
|
LOGDEB2("MimeHandlerMail::processMsg: depth " << depth << "\n");
|
||||||
if (depth++ >= maxdepth) {
|
if (depth++ >= maxdepth) {
|
||||||
// Have to stop somewhere
|
// Have to stop somewhere
|
||||||
LOGINFO("MimeHandlerMail::processMsg: maxdepth " << maxdepth <<
|
LOGINFO("MimeHandlerMail::processMsg: maxdepth " << maxdepth <<
|
||||||
" exceeded\n");
|
" exceeded\n");
|
||||||
// Return true anyway, better to index partially than not at all
|
// Return true anyway, better to index partially than not at all
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle some headers.
|
// Handle some headers.
|
||||||
string& text = m_metaData[cstr_dj_keycontent];
|
string& text = m_metaData[cstr_dj_keycontent];
|
||||||
Binc::HeaderItem hi;
|
Binc::HeaderItem hi;
|
||||||
string decoded;
|
string decoded;
|
||||||
if (doc->h.getFirstHeader("From", hi)) {
|
if (doc->h.getFirstHeader("From", hi)) {
|
||||||
rfc2047_decode(hi.getValue(), decoded);
|
rfc2047_decode(hi.getValue(), decoded);
|
||||||
if (preview())
|
if (preview())
|
||||||
text += string("From: ");
|
text += string("From: ");
|
||||||
text += decoded + cstr_newline;
|
text += decoded + cstr_newline;
|
||||||
if (depth == 1) {
|
if (depth == 1) {
|
||||||
m_metaData[cstr_dj_keyauthor] = decoded;
|
m_metaData[cstr_dj_keyauthor] = decoded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (doc->h.getFirstHeader("To", hi)) {
|
if (doc->h.getFirstHeader("To", hi)) {
|
||||||
rfc2047_decode(hi.getValue(), decoded);
|
rfc2047_decode(hi.getValue(), decoded);
|
||||||
if (preview())
|
if (preview())
|
||||||
text += string("To: ");
|
text += string("To: ");
|
||||||
text += decoded + cstr_newline;
|
text += decoded + cstr_newline;
|
||||||
if (depth == 1) {
|
if (depth == 1) {
|
||||||
m_metaData[cstr_dj_keyrecipient] = decoded;
|
m_metaData[cstr_dj_keyrecipient] = decoded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (doc->h.getFirstHeader("Cc", hi)) {
|
if (doc->h.getFirstHeader("Cc", hi)) {
|
||||||
rfc2047_decode(hi.getValue(), decoded);
|
rfc2047_decode(hi.getValue(), decoded);
|
||||||
if (preview())
|
if (preview())
|
||||||
text += string("Cc: ");
|
text += string("Cc: ");
|
||||||
text += decoded + cstr_newline;
|
text += decoded + cstr_newline;
|
||||||
if (depth == 1) {
|
if (depth == 1) {
|
||||||
m_metaData[cstr_dj_keyrecipient] += " " + decoded;
|
m_metaData[cstr_dj_keyrecipient] += " " + decoded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (doc->h.getFirstHeader("Message-Id", hi)) {
|
if (doc->h.getFirstHeader("Message-Id", hi)) {
|
||||||
if (depth == 1) {
|
if (depth == 1) {
|
||||||
m_metaData[cstr_dj_keymsgid] = hi.getValue();
|
m_metaData[cstr_dj_keymsgid] = hi.getValue();
|
||||||
trimstring(m_metaData[cstr_dj_keymsgid], "<>");
|
trimstring(m_metaData[cstr_dj_keymsgid], "<>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (doc->h.getFirstHeader("Date", hi)) {
|
if (doc->h.getFirstHeader("Date", hi)) {
|
||||||
rfc2047_decode(hi.getValue(), decoded);
|
rfc2047_decode(hi.getValue(), decoded);
|
||||||
if (depth == 1) {
|
if (depth == 1) {
|
||||||
time_t t = rfc2822DateToUxTime(decoded);
|
time_t t = rfc2822DateToUxTime(decoded);
|
||||||
if (t != (time_t)-1) {
|
if (t != (time_t)-1) {
|
||||||
char ascuxtime[100];
|
char ascuxtime[100];
|
||||||
sprintf(ascuxtime, "%ld", (long)t);
|
sprintf(ascuxtime, "%ld", (long)t);
|
||||||
m_metaData[cstr_dj_keymd] = ascuxtime;
|
m_metaData[cstr_dj_keymd] = ascuxtime;
|
||||||
} else {
|
} else {
|
||||||
// Leave mtime field alone, ftime will be used instead.
|
// Leave mtime field alone, ftime will be used instead.
|
||||||
LOGDEB("rfc2822Date...: failed: [" << decoded << "]\n");
|
LOGDEB("rfc2822Date...: failed: [" << decoded << "]\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (preview())
|
if (preview())
|
||||||
text += string("Date: ");
|
text += string("Date: ");
|
||||||
text += decoded + cstr_newline;
|
text += decoded + cstr_newline;
|
||||||
}
|
}
|
||||||
if (doc->h.getFirstHeader("Subject", hi)) {
|
if (doc->h.getFirstHeader("Subject", hi)) {
|
||||||
rfc2047_decode(hi.getValue(), decoded);
|
rfc2047_decode(hi.getValue(), decoded);
|
||||||
if (depth == 1) {
|
if (depth == 1) {
|
||||||
m_metaData[cstr_dj_keytitle] = decoded;
|
m_metaData[cstr_dj_keytitle] = decoded;
|
||||||
m_subject = decoded;
|
m_subject = decoded;
|
||||||
}
|
}
|
||||||
if (preview())
|
if (preview())
|
||||||
text += string("Subject: ");
|
text += string("Subject: ");
|
||||||
text += decoded + cstr_newline;
|
text += decoded + cstr_newline;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for the presence of configured additional headers and possibly
|
// Check for the presence of configured additional headers and possibly
|
||||||
@ -424,58 +424,58 @@ void MimeHandlerMail::walkmime(Binc::MimePart* doc, int depth)
|
|||||||
{
|
{
|
||||||
LOGDEB2("MimeHandlerMail::walkmime: depth " << depth << "\n");
|
LOGDEB2("MimeHandlerMail::walkmime: depth " << depth << "\n");
|
||||||
if (depth++ >= maxdepth) {
|
if (depth++ >= maxdepth) {
|
||||||
LOGINFO("walkmime: max depth (" << maxdepth << ") exceeded\n");
|
LOGINFO("walkmime: max depth (" << maxdepth << ") exceeded\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string& out = m_metaData[cstr_dj_keycontent];
|
string& out = m_metaData[cstr_dj_keycontent];
|
||||||
|
|
||||||
if (doc->isMultipart()) {
|
if (doc->isMultipart()) {
|
||||||
LOGDEB2("walkmime: ismultipart " << doc->isMultipart() <<
|
LOGDEB2("walkmime: ismultipart " << doc->isMultipart() <<
|
||||||
" subtype '" << doc->getSubType() << "'\n");
|
" subtype '" << doc->getSubType() << "'\n");
|
||||||
// We only handle alternative, related and mixed (no digests).
|
// We only handle alternative, related and mixed (no digests).
|
||||||
std::vector<Binc::MimePart>::iterator it;
|
std::vector<Binc::MimePart>::iterator it;
|
||||||
|
|
||||||
if (!stringicmp("mixed", doc->getSubType()) ||
|
if (!stringicmp("mixed", doc->getSubType()) ||
|
||||||
!stringicmp("signed", doc->getSubType()) ||
|
!stringicmp("signed", doc->getSubType()) ||
|
||||||
!stringicmp("related", doc->getSubType())) {
|
!stringicmp("related", doc->getSubType())) {
|
||||||
// Multipart mixed and related: process each part.
|
// Multipart mixed and related: process each part.
|
||||||
for (it = doc->members.begin(); it != doc->members.end();it++) {
|
for (it = doc->members.begin(); it != doc->members.end();it++) {
|
||||||
walkmime(&(*it), depth);
|
walkmime(&(*it), depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (!stringicmp("alternative", doc->getSubType())) {
|
} else if (!stringicmp("alternative", doc->getSubType())) {
|
||||||
// Multipart/alternative: look for a text/plain part, then html.
|
// Multipart/alternative: look for a text/plain part, then html.
|
||||||
// Process if found
|
// Process if found
|
||||||
std::vector<Binc::MimePart>::iterator ittxt, ithtml;
|
std::vector<Binc::MimePart>::iterator ittxt, ithtml;
|
||||||
ittxt = ithtml = doc->members.end();
|
ittxt = ithtml = doc->members.end();
|
||||||
int i = 1;
|
int i = 1;
|
||||||
for (it = doc->members.begin();
|
for (it = doc->members.begin();
|
||||||
it != doc->members.end(); it++, i++) {
|
it != doc->members.end(); it++, i++) {
|
||||||
// Get and parse content-type header
|
// Get and parse content-type header
|
||||||
Binc::HeaderItem hi;
|
Binc::HeaderItem hi;
|
||||||
if (!it->h.getFirstHeader("Content-Type", hi)) {
|
if (!it->h.getFirstHeader("Content-Type", hi)) {
|
||||||
LOGDEB("walkmime:no ctent-type header for part "<<i<< "\n");
|
LOGDEB("walkmime:no ctent-type header for part "<<i<< "\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
MimeHeaderValue content_type;
|
MimeHeaderValue content_type;
|
||||||
parseMimeHeaderValue(hi.getValue(), content_type);
|
parseMimeHeaderValue(hi.getValue(), content_type);
|
||||||
LOGDEB2("walkmime: C-type: " << content_type.value << "\n");
|
LOGDEB2("walkmime: C-type: " << content_type.value << "\n");
|
||||||
if (!stringlowercmp(cstr_textplain, content_type.value))
|
if (!stringlowercmp(cstr_textplain, content_type.value))
|
||||||
ittxt = it;
|
ittxt = it;
|
||||||
else if (!stringlowercmp("text/html", content_type.value))
|
else if (!stringlowercmp("text/html", content_type.value))
|
||||||
ithtml = it;
|
ithtml = it;
|
||||||
}
|
}
|
||||||
if (ittxt != doc->members.end() && ittxt->bodylength) {
|
if (ittxt != doc->members.end() && ittxt->bodylength) {
|
||||||
LOGDEB2("walkmime: alternative: choose text/plain. Size: " <<
|
LOGDEB2("walkmime: alternative: choose text/plain. Size: " <<
|
||||||
ittxt->bodylength << endl);
|
ittxt->bodylength << endl);
|
||||||
walkmime(&(*ittxt), depth);
|
walkmime(&(*ittxt), depth);
|
||||||
} else if (ithtml != doc->members.end()) {
|
} else if (ithtml != doc->members.end()) {
|
||||||
LOGDEB2("walkmime: alternative: choose text/html.\n");
|
LOGDEB2("walkmime: alternative: choose text/html.\n");
|
||||||
walkmime(&(*ithtml), depth);
|
walkmime(&(*ithtml), depth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Part is not multipart: it must be either simple or message. Take
|
// Part is not multipart: it must be either simple or message. Take
|
||||||
@ -485,57 +485,60 @@ void MimeHandlerMail::walkmime(Binc::MimePart* doc, int depth)
|
|||||||
Binc::HeaderItem hi;
|
Binc::HeaderItem hi;
|
||||||
string ctt = cstr_textplain;
|
string ctt = cstr_textplain;
|
||||||
if (doc->h.getFirstHeader("Content-Type", hi)) {
|
if (doc->h.getFirstHeader("Content-Type", hi)) {
|
||||||
ctt = hi.getValue();
|
ctt = hi.getValue();
|
||||||
}
|
}
|
||||||
LOGDEB2("walkmime:content-type: " << ctt << "\n");
|
LOGDEB2("walkmime:content-type: " << ctt << "\n");
|
||||||
MimeHeaderValue content_type;
|
MimeHeaderValue content_type;
|
||||||
parseMimeHeaderValue(ctt, content_type);
|
parseMimeHeaderValue(ctt, content_type);
|
||||||
|
|
||||||
// Get and parse Content-Disposition header
|
// Get and parse Content-Disposition header
|
||||||
string ctd = "inline";
|
string ctd = "inline";
|
||||||
if (doc->h.getFirstHeader("Content-Disposition", hi)) {
|
if (doc->h.getFirstHeader("Content-Disposition", hi)) {
|
||||||
ctd = hi.getValue();
|
ctd = hi.getValue();
|
||||||
}
|
}
|
||||||
MimeHeaderValue content_disposition;
|
MimeHeaderValue content_disposition;
|
||||||
parseMimeHeaderValue(ctd, content_disposition);
|
parseMimeHeaderValue(ctd, content_disposition);
|
||||||
LOGDEB2("Content_disposition:[" << content_disposition.value << "]\n");
|
LOGDEB2("Content_disposition:[" << content_disposition.value << "]\n");
|
||||||
string dispindic;
|
string dispindic;
|
||||||
if (stringlowercmp("inline", content_disposition.value))
|
if (stringlowercmp("inline", content_disposition.value))
|
||||||
dispindic = "Attachment";
|
dispindic = "Attachment";
|
||||||
else
|
else
|
||||||
dispindic = "Inline";
|
dispindic = "Inline";
|
||||||
|
|
||||||
// See if we have a filename.
|
// See if we have a filename.
|
||||||
string filename;
|
string filename;
|
||||||
map<string,string>::const_iterator it;
|
map<string,string>::const_iterator it;
|
||||||
it = content_disposition.params.find(string("filename"));
|
it = content_disposition.params.find(string("filename"));
|
||||||
if (it != content_disposition.params.end())
|
if (it != content_disposition.params.end())
|
||||||
filename = it->second;
|
filename = it->second;
|
||||||
if (filename.empty()) {
|
if (filename.empty()) {
|
||||||
it = content_type.params.find(string("name"));
|
it = content_type.params.find(string("name"));
|
||||||
if (it != content_type.params.end())
|
if (it != content_type.params.end())
|
||||||
filename = it->second;
|
filename = it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: I have never seen anything useful in the Content-Description field.
|
||||||
|
// So it's not processed. Use rfc2047 to decode if we ever do it.
|
||||||
|
|
||||||
if (doc->isMessageRFC822()) {
|
if (doc->isMessageRFC822()) {
|
||||||
LOGDEB2("walkmime: message/RFC822 part\n");
|
LOGDEB2("walkmime: message/RFC822 part\n");
|
||||||
|
|
||||||
// The first part is the already parsed message. Call
|
// The first part is the already parsed message. Call
|
||||||
// processMsg instead of walkmime so that mail headers get
|
// processMsg instead of walkmime so that mail headers get
|
||||||
// printed. The depth will tell it what to do
|
// printed. The depth will tell it what to do
|
||||||
if (doc->members.empty()) {
|
if (doc->members.empty()) {
|
||||||
//??
|
//??
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
out += "\n";
|
out += "\n";
|
||||||
if (m_forPreview)
|
if (m_forPreview)
|
||||||
out += "[" + dispindic + " " + content_type.value + ": ";
|
out += "[" + dispindic + " " + content_type.value + ": ";
|
||||||
out += filename;
|
out += filename;
|
||||||
if (m_forPreview)
|
if (m_forPreview)
|
||||||
out += "]";
|
out += "]";
|
||||||
out += "\n\n";
|
out += "\n\n";
|
||||||
processMsg(&doc->members[0], depth);
|
processMsg(&doc->members[0], depth);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "Simple" part.
|
// "Simple" part.
|
||||||
@ -550,13 +553,13 @@ void MimeHandlerMail::walkmime(Binc::MimePart* doc, int depth)
|
|||||||
string charset;
|
string charset;
|
||||||
it = content_type.params.find(cstr_mail_charset);
|
it = content_type.params.find(cstr_mail_charset);
|
||||||
if (it != content_type.params.end())
|
if (it != content_type.params.end())
|
||||||
charset = it->second;
|
charset = it->second;
|
||||||
if (charset.empty() ||
|
if (charset.empty() ||
|
||||||
!stringlowercmp("us-ascii", charset) ||
|
!stringlowercmp("us-ascii", charset) ||
|
||||||
!stringlowercmp("default", charset) ||
|
!stringlowercmp("default", charset) ||
|
||||||
!stringlowercmp("x-user-defined", charset) ||
|
!stringlowercmp("x-user-defined", charset) ||
|
||||||
!stringlowercmp("x-unknown", charset) ||
|
!stringlowercmp("x-unknown", charset) ||
|
||||||
!stringlowercmp("unknown", charset) ) {
|
!stringlowercmp("unknown", charset) ) {
|
||||||
if (!m_config->getConfParam("maildefcharset", charset))
|
if (!m_config->getConfParam("maildefcharset", charset))
|
||||||
charset = "CP1252";
|
charset = "CP1252";
|
||||||
}
|
}
|
||||||
@ -564,7 +567,7 @@ void MimeHandlerMail::walkmime(Binc::MimePart* doc, int depth)
|
|||||||
// Content transfer encoding
|
// Content transfer encoding
|
||||||
string cte = "7bit";
|
string cte = "7bit";
|
||||||
if (doc->h.getFirstHeader("Content-Transfer-Encoding", hi)) {
|
if (doc->h.getFirstHeader("Content-Transfer-Encoding", hi)) {
|
||||||
cte = hi.getValue();
|
cte = hi.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the Content-Disposition is not inline, we treat it as
|
// If the Content-Disposition is not inline, we treat it as
|
||||||
@ -572,34 +575,34 @@ void MimeHandlerMail::walkmime(Binc::MimePart* doc, int depth)
|
|||||||
// If it is inline but not text or html, same thing.
|
// If it is inline but not text or html, same thing.
|
||||||
// Some early MIME msgs have "text" instead of "text/plain" as type
|
// Some early MIME msgs have "text" instead of "text/plain" as type
|
||||||
if (stringlowercmp("inline", content_disposition.value) ||
|
if (stringlowercmp("inline", content_disposition.value) ||
|
||||||
(stringlowercmp(cstr_textplain, content_type.value) &&
|
(stringlowercmp(cstr_textplain, content_type.value) &&
|
||||||
stringlowercmp("text", content_type.value) &&
|
stringlowercmp("text", content_type.value) &&
|
||||||
stringlowercmp("text/html", content_type.value)) ) {
|
stringlowercmp("text/html", content_type.value)) ) {
|
||||||
if (!filename.empty()) {
|
if (!filename.empty()) {
|
||||||
out += "\n";
|
out += "\n";
|
||||||
if (m_forPreview)
|
if (m_forPreview)
|
||||||
out += "[" + dispindic + " " + content_type.value + ": ";
|
out += "[" + dispindic + " " + content_type.value + ": ";
|
||||||
out += filename;
|
out += filename;
|
||||||
if (m_forPreview)
|
if (m_forPreview)
|
||||||
out += "]";
|
out += "]";
|
||||||
out += "\n\n";
|
out += "\n\n";
|
||||||
}
|
}
|
||||||
MHMailAttach *att = new MHMailAttach;
|
MHMailAttach *att = new MHMailAttach;
|
||||||
if (att == 0) {
|
if (att == 0) {
|
||||||
LOGERR("Out of memory\n");
|
LOGERR("Out of memory\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
att->m_contentType = content_type.value;
|
att->m_contentType = content_type.value;
|
||||||
stringtolower(att->m_contentType);
|
stringtolower(att->m_contentType);
|
||||||
att->m_filename = filename;
|
att->m_filename = filename;
|
||||||
att->m_charset = charset;
|
att->m_charset = charset;
|
||||||
att->m_contentTransferEncoding = cte;
|
att->m_contentTransferEncoding = cte;
|
||||||
att->m_part = doc;
|
att->m_part = doc;
|
||||||
LOGDEB("walkmime: attachmnt: ct [" << att->m_contentType <<
|
LOGDEB("walkmime: attachmnt: ct [" << att->m_contentType <<
|
||||||
"] cte [" << att->m_contentTransferEncoding << "] cs [" <<
|
"] cte [" << att->m_contentTransferEncoding << "] cs [" <<
|
||||||
att->m_charset << "] fn [" << filename << "]\n");
|
att->m_charset << "] fn [" << filename << "]\n");
|
||||||
m_attachments.push_back(att);
|
m_attachments.push_back(att);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We are dealing with an inline part of text/plain or text/html
|
// We are dealing with an inline part of text/plain or text/html
|
||||||
@ -612,43 +615,42 @@ void MimeHandlerMail::walkmime(Binc::MimePart* doc, int depth)
|
|||||||
string body;
|
string body;
|
||||||
doc->getBody(body, 0, doc->bodylength);
|
doc->getBody(body, 0, doc->bodylength);
|
||||||
{
|
{
|
||||||
string decoded;
|
string decoded;
|
||||||
const string *bdp;
|
const string *bdp;
|
||||||
if (!decodeBody(cte, body, decoded, &bdp)) {
|
if (!decodeBody(cte, body, decoded, &bdp)) {
|
||||||
LOGERR("MimeHandlerMail::walkmime: failed decoding body\n");
|
LOGERR("MimeHandlerMail::walkmime: failed decoding body\n");
|
||||||
}
|
}
|
||||||
if (bdp != &body)
|
if (bdp != &body)
|
||||||
body.swap(decoded);
|
body.swap(decoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle html stripping and transcoding to utf8
|
// Handle html stripping and transcoding to utf8
|
||||||
if (!stringlowercmp("text/html", content_type.value)) {
|
if (!stringlowercmp("text/html", content_type.value)) {
|
||||||
MimeHandlerHtml mh(m_config, "1234");
|
MimeHandlerHtml mh(m_config, "1234");
|
||||||
mh.set_property(Dijon::Filter::OPERATING_MODE,
|
mh.set_property(Dijon::Filter::OPERATING_MODE,
|
||||||
m_forPreview ? "view" : "index");
|
m_forPreview ? "view" : "index");
|
||||||
mh.set_property(Dijon::Filter::DEFAULT_CHARSET, charset);
|
mh.set_property(Dijon::Filter::DEFAULT_CHARSET, charset);
|
||||||
mh.set_document_string("text/html", body);
|
mh.set_document_string("text/html", body);
|
||||||
mh.next_document();
|
mh.next_document();
|
||||||
map<string, string>::const_iterator it =
|
map<string, string>::const_iterator it =
|
||||||
mh.get_meta_data().find(cstr_dj_keycontent);
|
mh.get_meta_data().find(cstr_dj_keycontent);
|
||||||
if (it != mh.get_meta_data().end())
|
if (it != mh.get_meta_data().end())
|
||||||
out += it->second;
|
out += it->second;
|
||||||
} else {
|
} else {
|
||||||
string utf8;
|
string utf8;
|
||||||
// Transcode to utf-8
|
// Transcode to utf-8
|
||||||
LOGDEB1("walkmime: transcoding from " << charset << " to UTF-8\n");
|
LOGDEB1("walkmime: transcoding from " << charset << " to UTF-8\n");
|
||||||
if (!transcode(body, utf8, charset, cstr_utf8)) {
|
if (!transcode(body, utf8, charset, cstr_utf8)) {
|
||||||
LOGERR("walkmime: transcode failed from cs '" << charset <<
|
LOGERR("walkmime: transcode failed from cs '" << charset <<
|
||||||
"' to UTF-8\n");
|
"' to UTF-8\n");
|
||||||
out += body;
|
out += body;
|
||||||
} else {
|
} else {
|
||||||
out += utf8;
|
out += utf8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out.length() && out[out.length()-1] != '\n')
|
if (out.length() && out[out.length()-1] != '\n')
|
||||||
out += '\n';
|
out += '\n';
|
||||||
|
|
||||||
LOGDEB2("walkmime: out now: [" << out << "]\n");
|
LOGDEB2("walkmime: out now: [" << out << "]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,25 +24,23 @@
|
|||||||
#include "mimehandler.h"
|
#include "mimehandler.h"
|
||||||
|
|
||||||
namespace Binc {
|
namespace Binc {
|
||||||
class MimeDocument;
|
class MimeDocument;
|
||||||
class MimePart;
|
class MimePart;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MHMailAttach;
|
class MHMailAttach;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translate a mail folder file into internal documents (also works
|
* Process a mail message (rfc822) into internal documents.
|
||||||
* for maildir files). This has to keep state while parsing a mail folder
|
|
||||||
* file.
|
|
||||||
*/
|
*/
|
||||||
class MimeHandlerMail : public RecollFilter {
|
class MimeHandlerMail : public RecollFilter {
|
||||||
public:
|
public:
|
||||||
MimeHandlerMail(RclConfig *cnf, const std::string &id);
|
MimeHandlerMail(RclConfig *cnf, const std::string &id);
|
||||||
virtual ~MimeHandlerMail();
|
virtual ~MimeHandlerMail();
|
||||||
virtual bool is_data_input_ok(DataInput input) const {
|
virtual bool is_data_input_ok(DataInput input) const {
|
||||||
if (input == DOCUMENT_FILE_NAME || input == DOCUMENT_STRING)
|
if (input == DOCUMENT_FILE_NAME || input == DOCUMENT_STRING)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
virtual bool next_document();
|
virtual bool next_document();
|
||||||
virtual bool skip_to_document(const std::string& ipath);
|
virtual bool skip_to_document(const std::string& ipath);
|
||||||
@ -76,10 +74,10 @@ private:
|
|||||||
|
|
||||||
class MHMailAttach {
|
class MHMailAttach {
|
||||||
public:
|
public:
|
||||||
std::string m_contentType;
|
std::string m_contentType;
|
||||||
std::string m_filename;
|
std::string m_filename;
|
||||||
std::string m_charset;
|
std::string m_charset;
|
||||||
std::string m_contentTransferEncoding;
|
std::string m_contentTransferEncoding;
|
||||||
Binc::MimePart *m_part;
|
Binc::MimePart *m_part;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user