merge
This commit is contained in:
commit
d88b2a8bc9
@ -14,9 +14,10 @@
|
|||||||
* Free Software Foundation, Inc.,
|
* Free Software Foundation, Inc.,
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
#include "autoconfig.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include "autoconfig.h"
|
||||||
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
@ -24,11 +25,11 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
#include "cstr.h"
|
#include "cstr.h"
|
||||||
#include "mimehandler.h"
|
#include "mimehandler.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "readfile.h"
|
|
||||||
#include "mh_mbox.h"
|
#include "mh_mbox.h"
|
||||||
#include "smallut.h"
|
#include "smallut.h"
|
||||||
#include "rclconfig.h"
|
#include "rclconfig.h"
|
||||||
@ -38,11 +39,6 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define fseeko _fseeki64
|
|
||||||
#define ftello _ftelli64
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Define maximum message size for safety. 100MB would seem reasonable
|
// Define maximum message size for safety. 100MB would seem reasonable
|
||||||
static const unsigned int max_mbox_member_size = 100 * 1024 * 1024;
|
static const unsigned int max_mbox_member_size = 100 * 1024 * 1024;
|
||||||
|
|
||||||
@ -109,21 +105,6 @@ static const string miniTbirdFrom{"^From $"};
|
|||||||
static SimpleRegexp fromregex(frompat, SimpleRegexp::SRE_NOSUB);
|
static SimpleRegexp fromregex(frompat, SimpleRegexp::SRE_NOSUB);
|
||||||
static SimpleRegexp minifromregex(miniTbirdFrom, SimpleRegexp::SRE_NOSUB);
|
static SimpleRegexp minifromregex(miniTbirdFrom, SimpleRegexp::SRE_NOSUB);
|
||||||
|
|
||||||
// Automatic fp closing
|
|
||||||
class FpKeeper {
|
|
||||||
public:
|
|
||||||
FpKeeper(FILE **fpp)
|
|
||||||
: m_fpp(fpp) {}
|
|
||||||
~FpKeeper() {
|
|
||||||
if (m_fpp && *m_fpp) {
|
|
||||||
fclose(*m_fpp);
|
|
||||||
*m_fpp = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
FILE **m_fpp;
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::mutex o_mcache_mutex;
|
static std::mutex o_mcache_mutex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -154,20 +135,19 @@ public:
|
|||||||
LOGDEB0("MboxCache::get_offsets: udi [" << udi << "] msgnum "
|
LOGDEB0("MboxCache::get_offsets: udi [" << udi << "] msgnum "
|
||||||
<< msgnum << "\n");
|
<< msgnum << "\n");
|
||||||
if (!ok(config)) {
|
if (!ok(config)) {
|
||||||
LOGDEB0("MboxCache::get_offsets: init failed\n");
|
LOGDEB("MboxCache::get_offsets: init failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
std::unique_lock<std::mutex> locker(o_mcache_mutex);
|
std::unique_lock<std::mutex> locker(o_mcache_mutex);
|
||||||
string fn = makefilename(udi);
|
string fn = makefilename(udi);
|
||||||
FILE *fp = 0;
|
ifstream instream(fn.c_str(), std::ifstream::binary);
|
||||||
if ((fp = fopen(fn.c_str(), "rb")) == 0) {
|
if (!instream.good()) {
|
||||||
LOGSYSERR("MboxCache::get_offsets", "open", fn);
|
LOGSYSERR("MboxCache::get_offsets", "open", fn);
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
FpKeeper keeper(&fp);
|
|
||||||
|
|
||||||
char blk1[M_o_b1size];
|
char blk1[M_o_b1size];
|
||||||
if (fread(blk1, M_o_b1size, 1, fp) != 1) {
|
instream.read(blk1, M_o_b1size);
|
||||||
|
if (!instream.good()) {
|
||||||
LOGSYSERR("MboxCache::get_offsets", "read blk1", "");
|
LOGSYSERR("MboxCache::get_offsets", "read blk1", "");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -180,14 +160,15 @@ public:
|
|||||||
}
|
}
|
||||||
LOGDEB1("MboxCache::get_offsets: reading offsets file at offs "
|
LOGDEB1("MboxCache::get_offsets: reading offsets file at offs "
|
||||||
<< cacheoffset(msgnum) << "\n");
|
<< cacheoffset(msgnum) << "\n");
|
||||||
if (fseeko(fp, cacheoffset(msgnum), SEEK_SET) != 0) {
|
instream.seekg(cacheoffset(msgnum));
|
||||||
|
if (!instream.good()) {
|
||||||
LOGSYSERR("MboxCache::get_offsets", "seek",
|
LOGSYSERR("MboxCache::get_offsets", "seek",
|
||||||
lltodecstr(cacheoffset(msgnum)));
|
lltodecstr(cacheoffset(msgnum)));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int64_t offset = -1;
|
int64_t offset = -1;
|
||||||
size_t ret;
|
instream.read((char*)&offset, sizeof(int64_t));
|
||||||
if ((ret = fread(&offset, sizeof(int64_t), 1, fp)) != 1) {
|
if (!instream.good()) {
|
||||||
LOGSYSERR("MboxCache::get_offsets", "read", "");
|
LOGSYSERR("MboxCache::get_offsets", "read", "");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -202,35 +183,41 @@ public:
|
|||||||
if (!ok(config) || !maybemakedir())
|
if (!ok(config) || !maybemakedir())
|
||||||
return;
|
return;
|
||||||
if (fsize < m_minfsize) {
|
if (fsize < m_minfsize) {
|
||||||
LOGDEB0("MboxCache::put_offsets: fsize " << fsize << " < minsize " <<
|
LOGDEB0("MboxCache::put_offsets: fsize " << fsize << " < minsize "
|
||||||
m_minfsize << endl);
|
<< m_minfsize << endl);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::unique_lock<std::mutex> locker(o_mcache_mutex);
|
std::unique_lock<std::mutex> locker(o_mcache_mutex);
|
||||||
string fn = makefilename(udi);
|
string fn = makefilename(udi);
|
||||||
FILE *fp;
|
std::ofstream os(fn.c_str(), std::ios::out|std::ios::binary);
|
||||||
if ((fp = fopen(fn.c_str(), "wb")) == 0) {
|
if (!os.good()) {
|
||||||
LOGSYSERR("MboxCache::put_offsets", "fopen", fn);
|
LOGSYSERR("MboxCache::put_offsets", "open", fn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FpKeeper keeper(&fp);
|
|
||||||
string blk1("udi=");
|
string blk1("udi=");
|
||||||
blk1.append(udi);
|
blk1.append(udi);
|
||||||
blk1.append(cstr_newline);
|
blk1.append(cstr_newline);
|
||||||
blk1.resize(M_o_b1size, 0);
|
blk1.resize(M_o_b1size, 0);
|
||||||
if (fwrite(blk1.c_str(), M_o_b1size, 1, fp) != 1) {
|
os.write(blk1.c_str(), M_o_b1size);
|
||||||
LOGSYSERR("MboxCache::put_offsets", "fwrite blk1", "");
|
if (!os.good()) {
|
||||||
|
LOGSYSERR("MboxCache::put_offsets", "write blk1", "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& off : offs) {
|
for (const auto& off : offs) {
|
||||||
LOGDEB1("MboxCache::put_offsets: writing value " << off <<
|
LOGDEB1("MboxCache::put_offsets: writing value " << off <<
|
||||||
" at offset " << ftello(fp) << endl);
|
" at offset " << ftello(fp) << endl);
|
||||||
if (fwrite((char*)&off, sizeof(int64_t), 1, fp) != 1) {
|
os.write((char*)&off, sizeof(int64_t));
|
||||||
LOGSYSERR("MboxCache::put_offsets", "fwrite", "");
|
if (!os.good()) {
|
||||||
|
LOGSYSERR("MboxCache::put_offsets", "write", "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
os.flush();
|
||||||
|
if (!os.good()) {
|
||||||
|
LOGSYSERR("MboxCache::put_offsets", "flush", "");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check state, possibly initialize
|
// Check state, possibly initialize
|
||||||
@ -294,7 +281,7 @@ public:
|
|||||||
Internal(MimeHandlerMbox *p) : pthis(p) {}
|
Internal(MimeHandlerMbox *p) : pthis(p) {}
|
||||||
std::string fn; // File name
|
std::string fn; // File name
|
||||||
std::string ipath;
|
std::string ipath;
|
||||||
void *vfp{nullptr}; // File pointer for folder
|
ifstream instream;
|
||||||
int msgnum{0}; // Current message number in folder. Starts at 1
|
int msgnum{0}; // Current message number in folder. Starts at 1
|
||||||
int64_t lineno{0}; // debug
|
int64_t lineno{0}; // debug
|
||||||
int64_t fsize{0};
|
int64_t fsize{0};
|
||||||
@ -322,10 +309,7 @@ void MimeHandlerMbox::clear_impl()
|
|||||||
{
|
{
|
||||||
m->fn.erase();
|
m->fn.erase();
|
||||||
m->ipath.erase();
|
m->ipath.erase();
|
||||||
if (m->vfp) {
|
m->instream = ifstream();
|
||||||
fclose((FILE *)m->vfp);
|
|
||||||
m->vfp = 0;
|
|
||||||
}
|
|
||||||
m->msgnum = m->lineno = m->fsize = 0;
|
m->msgnum = m->lineno = m->fsize = 0;
|
||||||
m->offsets.clear();
|
m->offsets.clear();
|
||||||
m->quirks = 0;
|
m->quirks = 0;
|
||||||
@ -341,17 +325,14 @@ bool MimeHandlerMbox::set_document_file_impl(const string& mt, const string &fn)
|
|||||||
LOGDEB("MimeHandlerMbox::set_document_file(" << fn << ")\n");
|
LOGDEB("MimeHandlerMbox::set_document_file(" << fn << ")\n");
|
||||||
clear_impl();
|
clear_impl();
|
||||||
m->fn = fn;
|
m->fn = fn;
|
||||||
if (m->vfp) {
|
m->instream = ifstream(fn.c_str(), std::ifstream::binary);
|
||||||
fclose((FILE *)m->vfp);
|
if (!m->instream.good()) {
|
||||||
m->vfp = 0;
|
LOGSYSERR("MimeHandlerMail::set_document_file", "ifstream", fn);
|
||||||
}
|
|
||||||
|
|
||||||
m->vfp = fopen(fn.c_str(), "rb");
|
|
||||||
if (m->vfp == nullptr) {
|
|
||||||
LOGSYSERR("MimeHandlerMail::set_document_file", "fopen rb", fn);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#if defined O_NOATIME && O_NOATIME != 0
|
|
||||||
|
// TBD
|
||||||
|
#if 0 && defined O_NOATIME && O_NOATIME != 0
|
||||||
if (fcntl(fileno((FILE *)m->vfp), F_SETFL, O_NOATIME) < 0) {
|
if (fcntl(fileno((FILE *)m->vfp), F_SETFL, O_NOATIME) < 0) {
|
||||||
// perror("fcntl");
|
// perror("fcntl");
|
||||||
}
|
}
|
||||||
@ -372,33 +353,19 @@ bool MimeHandlerMbox::set_document_file_impl(const string& mt, const string &fn)
|
|||||||
// And double check for thunderbird
|
// And double check for thunderbird
|
||||||
string tbirdmsf = fn + ".msf";
|
string tbirdmsf = fn + ".msf";
|
||||||
if (!(m->quirks & MBOXQUIRK_TBIRD) && path_exists(tbirdmsf)) {
|
if (!(m->quirks & MBOXQUIRK_TBIRD) && path_exists(tbirdmsf)) {
|
||||||
LOGDEB("MimeHandlerMbox: detected unconf'd tbird mbox in " << fn <<"\n");
|
LOGDEB("MimeHandlerMbox: detected unconf'd tbird mbox in "<< fn <<"\n");
|
||||||
m->quirks |= MBOXQUIRK_TBIRD;
|
m->quirks |= MBOXQUIRK_TBIRD;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LL 20000
|
|
||||||
typedef char line_type[LL+10];
|
|
||||||
static inline void stripendnl(line_type& line, int& ll)
|
|
||||||
{
|
|
||||||
ll = int(strlen(line));
|
|
||||||
while (ll > 0) {
|
|
||||||
if (line[ll-1] == '\n' || line[ll-1] == '\r') {
|
|
||||||
line[ll-1] = 0;
|
|
||||||
ll--;
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MimeHandlerMbox::Internal::tryUseCache(int mtarg)
|
bool MimeHandlerMbox::Internal::tryUseCache(int mtarg)
|
||||||
{
|
{
|
||||||
bool cachefound = false;
|
bool cachefound = false;
|
||||||
|
string line;
|
||||||
int64_t off;
|
int64_t off;
|
||||||
line_type line;
|
|
||||||
LOGDEB0("MimeHandlerMbox::next_doc: mtarg " << mtarg << " m_udi[" <<
|
LOGDEB0("MimeHandlerMbox::next_doc: mtarg " << mtarg << " m_udi[" <<
|
||||||
pthis->m_udi << "]\n");
|
pthis->m_udi << "]\n");
|
||||||
if (pthis->m_udi.empty()) {
|
if (pthis->m_udi.empty()) {
|
||||||
@ -407,21 +374,22 @@ bool MimeHandlerMbox::Internal::tryUseCache(int mtarg)
|
|||||||
if ((off = o_mcache.get_offset(pthis->m_config, pthis->m_udi, mtarg)) < 0) {
|
if ((off = o_mcache.get_offset(pthis->m_config, pthis->m_udi, mtarg)) < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
LOGDEB1("MimeHandlerMbox::next_doc: got offset " << off <<
|
instream.seekg(off);
|
||||||
" from cache\n");
|
if (!instream.good()) {
|
||||||
if (fseeko((FILE*)vfp, off, SEEK_SET) < 0) {
|
LOGSYSERR("tryUseCache", "seekg", "");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
LOGDEB1("MimeHandlerMbox::next_doc: fseeko ok\n");
|
getline(instream, line, '\n');
|
||||||
if (!fgets(line, LL, (FILE*)vfp)) {
|
if (!instream.good()) {
|
||||||
|
LOGSYSERR("tryUseCache", "getline", "");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
LOGDEB1("MimeHandlerMbox::next_doc: fgets ok. line:[" << line << "]\n");
|
LOGDEB1("MimeHandlerMbox::tryUseCache:getl ok. line:[" << line << "]\n");
|
||||||
|
|
||||||
if ((fromregex(line) ||
|
if ((fromregex(line) ||
|
||||||
((quirks & MBOXQUIRK_TBIRD) && minifromregex(line))) ) {
|
((quirks & MBOXQUIRK_TBIRD) && minifromregex(line))) ) {
|
||||||
LOGDEB0("MimeHandlerMbox: Cache: From_ Ok\n");
|
LOGDEB0("MimeHandlerMbox: Cache: From_ Ok\n");
|
||||||
fseeko((FILE*)vfp, off, SEEK_SET);
|
instream.seekg(off);
|
||||||
msgnum = mtarg -1;
|
msgnum = mtarg -1;
|
||||||
cachefound = true;
|
cachefound = true;
|
||||||
} else {
|
} else {
|
||||||
@ -431,7 +399,7 @@ bool MimeHandlerMbox::Internal::tryUseCache(int mtarg)
|
|||||||
out:
|
out:
|
||||||
if (!cachefound) {
|
if (!cachefound) {
|
||||||
// No cached result: scan.
|
// No cached result: scan.
|
||||||
fseek((FILE*)vfp, 0, SEEK_SET);
|
instream.seekg(0);
|
||||||
msgnum = 0;
|
msgnum = 0;
|
||||||
}
|
}
|
||||||
return cachefound;
|
return cachefound;
|
||||||
@ -439,7 +407,7 @@ out:
|
|||||||
|
|
||||||
bool MimeHandlerMbox::next_document()
|
bool MimeHandlerMbox::next_document()
|
||||||
{
|
{
|
||||||
if (nullptr == m->vfp) {
|
if (!m->instream.good()) {
|
||||||
LOGERR("MimeHandlerMbox::next_document: not open\n");
|
LOGERR("MimeHandlerMbox::next_document: not open\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -469,25 +437,40 @@ bool MimeHandlerMbox::next_document()
|
|||||||
}
|
}
|
||||||
|
|
||||||
int64_t message_end = 0;
|
int64_t message_end = 0;
|
||||||
int64_t message_end1 = 0;
|
|
||||||
bool iseof = false;
|
bool iseof = false;
|
||||||
bool hademptyline = true;
|
bool hademptyline = true;
|
||||||
string& msgtxt = m_metaData[cstr_dj_keycontent];
|
string& msgtxt = m_metaData[cstr_dj_keycontent];
|
||||||
msgtxt.erase();
|
msgtxt.erase();
|
||||||
line_type line;
|
string line;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
message_end = ftello((FILE*)m->vfp);
|
message_end = m->instream.tellg();
|
||||||
if (!fgets(line, LL, (FILE*)m->vfp)) {
|
getline(m->instream, line, '\n');
|
||||||
LOGDEB2("MimeHandlerMbox:next: eof\n");
|
if (!m->instream.good()) {
|
||||||
|
ifstream::iostate st = m->instream.rdstate();
|
||||||
|
if (st & std::ifstream::eofbit) {
|
||||||
|
LOGDEB0("MimeHandlerMbox:next: eof\n");
|
||||||
|
}
|
||||||
|
if (st & std::ifstream::failbit) {
|
||||||
|
LOGDEB0("MimeHandlerMbox:next: fail\n");
|
||||||
|
LOGSYSERR("MimeHandlerMbox:next:", "", "");
|
||||||
|
}
|
||||||
|
if (st & std::ifstream::badbit) {
|
||||||
|
LOGDEB0("MimeHandlerMbox:next: bad\n");
|
||||||
|
LOGSYSERR("MimeHandlerMbox:next:", "", "");
|
||||||
|
}
|
||||||
|
if (st & std::ifstream::goodbit) {
|
||||||
|
LOGDEB0("MimeHandlerMbox:next: good\n");
|
||||||
|
}
|
||||||
|
LOGDEB0("MimeHandlerMbox:next: eof at " << message_end << endl);
|
||||||
iseof = true;
|
iseof = true;
|
||||||
m->msgnum++;
|
m->msgnum++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
m->lineno++;
|
m->lineno++;
|
||||||
int ll;
|
rtrimstring(line, "\r\n");
|
||||||
stripendnl(line, ll);
|
int ll = line.size();
|
||||||
LOGDEB2("mhmbox:next: hadempty " << hademptyline << " lineno " <<
|
LOGDEB2("mhmbox:next: hadempty " << hademptyline << " lineno " <<
|
||||||
m->lineno << " ll " << ll << " Line: [" << line << "]\n");
|
m->lineno << " ll " << ll << " Line: [" << line << "]\n");
|
||||||
if (hademptyline) {
|
if (hademptyline) {
|
||||||
if (ll > 0) {
|
if (ll > 0) {
|
||||||
// Non-empty line with empty line flag set, reset flag
|
// Non-empty line with empty line flag set, reset flag
|
||||||
@ -504,7 +487,7 @@ bool MimeHandlerMbox::next_document()
|
|||||||
fromregex(line) ||
|
fromregex(line) ||
|
||||||
((m->quirks & MBOXQUIRK_TBIRD) && minifromregex(line)))
|
((m->quirks & MBOXQUIRK_TBIRD) && minifromregex(line)))
|
||||||
) {
|
) {
|
||||||
LOGDEB0("MimeHandlerMbox: msgnum " << m->msgnum <<
|
LOGDEB1("MimeHandlerMbox: msgnum " << m->msgnum <<
|
||||||
", From_ at line " << m->lineno << " foffset " <<
|
", From_ at line " << m->lineno << " foffset " <<
|
||||||
message_end << " line: [" << line << "]\n");
|
message_end << " line: [" << line << "]\n");
|
||||||
|
|
||||||
@ -527,8 +510,7 @@ bool MimeHandlerMbox::next_document()
|
|||||||
|
|
||||||
if (mtarg <= 0 || m->msgnum == mtarg) {
|
if (mtarg <= 0 || m->msgnum == mtarg) {
|
||||||
// Accumulate message lines
|
// Accumulate message lines
|
||||||
line[ll] = '\n';
|
line += '\n';
|
||||||
line[ll+1] = 0;
|
|
||||||
msgtxt += line;
|
msgtxt += line;
|
||||||
if (msgtxt.size() > max_mbox_member_size) {
|
if (msgtxt.size() > max_mbox_member_size) {
|
||||||
LOGERR("mh_mbox: huge message (more than " <<
|
LOGERR("mh_mbox: huge message (more than " <<
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user