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