|
a/src/internfile/mh_mbox.cpp |
|
b/src/internfile/mh_mbox.cpp |
|
... |
|
... |
51 |
}
|
51 |
}
|
52 |
}
|
52 |
}
|
53 |
private: FILE **m_fpp;
|
53 |
private: FILE **m_fpp;
|
54 |
};
|
54 |
};
|
55 |
|
55 |
|
56 |
static PTMutexInit o_mutex;
|
56 |
static PTMutexInit o_mcache_mutex;
|
57 |
|
57 |
|
58 |
/**
|
58 |
/**
|
59 |
* Handles a cache for message numbers to offset translations. Permits direct
|
59 |
* Handles a cache for message numbers to offset translations. Permits direct
|
60 |
* accesses inside big folders instead of having to scan up to the right place
|
60 |
* accesses inside big folders instead of having to scan up to the right place
|
61 |
*
|
61 |
*
|
|
... |
|
... |
84 |
msgnum));
|
84 |
msgnum));
|
85 |
if (!ok(config)) {
|
85 |
if (!ok(config)) {
|
86 |
LOGDEB0(("MboxCache::get_offsets: init failed\n"));
|
86 |
LOGDEB0(("MboxCache::get_offsets: init failed\n"));
|
87 |
return -1;
|
87 |
return -1;
|
88 |
}
|
88 |
}
|
89 |
PTMutexLocker locker(o_mutex);
|
89 |
PTMutexLocker locker(o_mcache_mutex);
|
90 |
string fn = makefilename(udi);
|
90 |
string fn = makefilename(udi);
|
91 |
FILE *fp = 0;
|
91 |
FILE *fp = 0;
|
92 |
if ((fp = fopen(fn.c_str(), "r")) == 0) {
|
92 |
if ((fp = fopen(fn.c_str(), "r")) == 0) {
|
93 |
LOGDEB(("MboxCache::get_offsets: open failed, errno %d\n", errno));
|
93 |
LOGDEB(("MboxCache::get_offsets: open failed, errno %d\n", errno));
|
94 |
return -1;
|
94 |
return -1;
|
|
... |
|
... |
131 |
LOGDEB0(("MboxCache::put_offsets: %u offsets\n", offs.size()));
|
131 |
LOGDEB0(("MboxCache::put_offsets: %u offsets\n", offs.size()));
|
132 |
if (!ok(config) || !maybemakedir())
|
132 |
if (!ok(config) || !maybemakedir())
|
133 |
return;
|
133 |
return;
|
134 |
if (fsize < m_minfsize)
|
134 |
if (fsize < m_minfsize)
|
135 |
return;
|
135 |
return;
|
136 |
PTMutexLocker locker(o_mutex);
|
136 |
PTMutexLocker locker(o_mcache_mutex);
|
137 |
string fn = makefilename(udi);
|
137 |
string fn = makefilename(udi);
|
138 |
FILE *fp;
|
138 |
FILE *fp;
|
139 |
if ((fp = fopen(fn.c_str(), "w")) == 0) {
|
139 |
if ((fp = fopen(fn.c_str(), "w")) == 0) {
|
140 |
LOGDEB(("MboxCache::put_offsets: fopen errno %d\n", errno));
|
140 |
LOGDEB(("MboxCache::put_offsets: fopen errno %d\n", errno));
|
141 |
return;
|
141 |
return;
|
|
... |
|
... |
161 |
}
|
161 |
}
|
162 |
}
|
162 |
}
|
163 |
|
163 |
|
164 |
// Check state, possibly initialize
|
164 |
// Check state, possibly initialize
|
165 |
bool ok(RclConfig *config) {
|
165 |
bool ok(RclConfig *config) {
|
166 |
PTMutexLocker locker(o_mutex);
|
166 |
PTMutexLocker locker(o_mcache_mutex);
|
167 |
if (m_minfsize == -1)
|
167 |
if (m_minfsize == -1)
|
168 |
return false;
|
168 |
return false;
|
169 |
if (!m_ok) {
|
169 |
if (!m_ok) {
|
170 |
int minmbs = 5;
|
170 |
int minmbs = 5;
|
171 |
config->getConfParam("mboxcacheminmbs", &minmbs);
|
171 |
config->getConfParam("mboxcacheminmbs", &minmbs);
|
|
... |
|
... |
222 |
}
|
222 |
}
|
223 |
};
|
223 |
};
|
224 |
|
224 |
|
225 |
const size_t MboxCache::o_b1size = 1024;
|
225 |
const size_t MboxCache::o_b1size = 1024;
|
226 |
|
226 |
|
227 |
static class MboxCache mcache;
|
227 |
static class MboxCache o_mcache;
|
228 |
|
228 |
|
229 |
static const string keyquirks("mhmboxquirks");
|
229 |
static const string cstr_keyquirks("mhmboxquirks");
|
230 |
|
230 |
|
231 |
MimeHandlerMbox::~MimeHandlerMbox()
|
231 |
MimeHandlerMbox::~MimeHandlerMbox()
|
232 |
{
|
232 |
{
|
233 |
clear();
|
233 |
clear();
|
234 |
}
|
234 |
}
|
|
... |
|
... |
269 |
m_offsets.clear();
|
269 |
m_offsets.clear();
|
270 |
m_quirks = 0;
|
270 |
m_quirks = 0;
|
271 |
|
271 |
|
272 |
// Check for location-based quirks:
|
272 |
// Check for location-based quirks:
|
273 |
string quirks;
|
273 |
string quirks;
|
274 |
if (m_config && m_config->getConfParam(keyquirks, quirks)) {
|
274 |
if (m_config && m_config->getConfParam(cstr_keyquirks, quirks)) {
|
275 |
if (quirks == "tbird") {
|
275 |
if (quirks == "tbird") {
|
276 |
LOGDEB(("MimeHandlerMbox: setting quirks TBIRD\n"));
|
276 |
LOGDEB(("MimeHandlerMbox: setting quirks TBIRD\n"));
|
277 |
m_quirks |= MBOXQUIRK_TBIRD;
|
277 |
m_quirks |= MBOXQUIRK_TBIRD;
|
278 |
}
|
278 |
}
|
279 |
}
|
279 |
}
|
|
... |
|
... |
356 |
static const char *miniTbirdFrom = "^From $";
|
356 |
static const char *miniTbirdFrom = "^From $";
|
357 |
|
357 |
|
358 |
static regex_t fromregex;
|
358 |
static regex_t fromregex;
|
359 |
static regex_t minifromregex;
|
359 |
static regex_t minifromregex;
|
360 |
static bool regcompiled;
|
360 |
static bool regcompiled;
|
|
|
361 |
static PTMutexInit o_regex_mutex;
|
|
|
362 |
|
|
|
363 |
static void compileregexes()
|
|
|
364 |
{
|
|
|
365 |
PTMutexLocker locker(o_regex_mutex);
|
|
|
366 |
// As the initial test of regcompiled is unprotected the value may
|
|
|
367 |
// have changed while we were waiting for the lock. Test again now
|
|
|
368 |
// that we are alone.
|
|
|
369 |
if (regcompiled)
|
|
|
370 |
return;
|
|
|
371 |
regcomp(&fromregex, frompat, REG_NOSUB|REG_EXTENDED);
|
|
|
372 |
regcomp(&minifromregex, miniTbirdFrom, REG_NOSUB|REG_EXTENDED);
|
|
|
373 |
regcompiled = true;
|
|
|
374 |
}
|
361 |
|
375 |
|
362 |
bool MimeHandlerMbox::next_document()
|
376 |
bool MimeHandlerMbox::next_document()
|
363 |
{
|
377 |
{
|
364 |
if (m_vfp == 0) {
|
378 |
if (m_vfp == 0) {
|
365 |
LOGERR(("MimeHandlerMbox::next_document: not open\n"));
|
379 |
LOGERR(("MimeHandlerMbox::next_document: not open\n"));
|
|
... |
|
... |
381 |
m_fn.c_str(), m_msgnum, mtarg));
|
395 |
m_fn.c_str(), m_msgnum, mtarg));
|
382 |
if (mtarg == 0)
|
396 |
if (mtarg == 0)
|
383 |
mtarg = -1;
|
397 |
mtarg = -1;
|
384 |
|
398 |
|
385 |
if (!regcompiled) {
|
399 |
if (!regcompiled) {
|
386 |
regcomp(&fromregex, frompat, REG_NOSUB|REG_EXTENDED);
|
400 |
compileregexes();
|
387 |
regcomp(&minifromregex, miniTbirdFrom, REG_NOSUB|REG_EXTENDED);
|
|
|
388 |
regcompiled = true;
|
|
|
389 |
}
|
401 |
}
|
390 |
|
402 |
|
391 |
// If we are called to retrieve a specific message, seek to bof
|
403 |
// If we are called to retrieve a specific message, seek to bof
|
392 |
// (then scan up to the message). This is for the case where the
|
404 |
// (then scan up to the message). This is for the case where the
|
393 |
// same object is reused to fetch several messages (else the fp is
|
405 |
// same object is reused to fetch several messages (else the fp is
|
|
... |
|
... |
401 |
mbhoff_type off;
|
413 |
mbhoff_type off;
|
402 |
line_type line;
|
414 |
line_type line;
|
403 |
LOGDEB0(("MimeHandlerMbox::next_doc: mtarg %d m_udi[%s]\n",
|
415 |
LOGDEB0(("MimeHandlerMbox::next_doc: mtarg %d m_udi[%s]\n",
|
404 |
mtarg, m_udi.c_str()));
|
416 |
mtarg, m_udi.c_str()));
|
405 |
if (!m_udi.empty() &&
|
417 |
if (!m_udi.empty() &&
|
406 |
(off = mcache.get_offset(m_config, m_udi, mtarg)) >= 0 &&
|
418 |
(off = o_mcache.get_offset(m_config, m_udi, mtarg)) >= 0 &&
|
407 |
fseeko(fp, (off_t)off, SEEK_SET) >= 0 &&
|
419 |
fseeko(fp, (off_t)off, SEEK_SET) >= 0 &&
|
408 |
fgets(line, LL, fp) &&
|
420 |
fgets(line, LL, fp) &&
|
409 |
(!regexec(&fromregex, line, 0, 0, 0) ||
|
421 |
(!regexec(&fromregex, line, 0, 0, 0) ||
|
410 |
((m_quirks & MBOXQUIRK_TBIRD) &&
|
422 |
((m_quirks & MBOXQUIRK_TBIRD) &&
|
411 |
!regexec(&minifromregex, line, 0, 0, 0))) ) {
|
423 |
!regexec(&minifromregex, line, 0, 0, 0))) ) {
|
|
... |
|
... |
490 |
m_metaData["mimetype"] = "message/rfc822";
|
502 |
m_metaData["mimetype"] = "message/rfc822";
|
491 |
if (iseof) {
|
503 |
if (iseof) {
|
492 |
LOGDEB2(("MimeHandlerMbox::next: eof hit\n"));
|
504 |
LOGDEB2(("MimeHandlerMbox::next: eof hit\n"));
|
493 |
m_havedoc = false;
|
505 |
m_havedoc = false;
|
494 |
if (!m_udi.empty() && storeoffsets) {
|
506 |
if (!m_udi.empty() && storeoffsets) {
|
495 |
mcache.put_offsets(m_config, m_udi, m_fsize, m_offsets);
|
507 |
o_mcache.put_offsets(m_config, m_udi, m_fsize, m_offsets);
|
496 |
}
|
508 |
}
|
497 |
}
|
509 |
}
|
498 |
return msgtxt.empty() ? false : true;
|
510 |
return msgtxt.empty() ? false : true;
|
499 |
}
|
511 |
}
|
500 |
|
512 |
|