@@ -203,17 +203,6 @@ static std::string make_midb_path(const char *d)
203203 return d + " /exmdb/midb.sqlite3" s;
204204}
205205
206- static std::string make_eml_path (const char *d, std::string_view m)
207- {
208- /* P2591r5 only for C++26 */
209- return (d + " /eml/" s) += m;
210- }
211-
212- static std::string make_ext_path (const char *d, std::string_view m)
213- {
214- return (d + " /ext/" s) += m;
215- }
216-
217206static std::unique_ptr<char []> me_ct_to_utf8 (const char *charset,
218207 const char *string) try
219208{
@@ -248,39 +237,26 @@ static std::unique_ptr<char[]> me_ct_to_utf8(const char *charset,
248237static uint64_t me_get_digest (sqlite3 *psqlite, const char *mid_string,
249238 Json::Value &digest) try
250239{
251- size_t size;
252- auto ext_path = make_ext_path (cu_get_maildir (), mid_string);
253- size_t slurp_size = 0 ;
254- std::unique_ptr<char [], stdlib_delete> slurp_data (HX_slurp_file (ext_path.c_str (), &slurp_size));
255- if (slurp_data != nullptr ) {
256- if (!json_from_str (slurp_data.get (), digest))
240+ auto dir = cu_get_maildir ();
241+ std::string slurp_data;
242+ if (exmdb_client::imapfile_read (dir, " ext" , mid_string, &slurp_data)) {
243+ if (!json_from_str (slurp_data.c_str (), digest))
257244 return 0 ;
258- } else if (errno != ENOENT) {
259- mlog (LV_ERR, " E-2139: read %s: %s" , ext_path.c_str (), strerror (errno));
260- return 0 ;
261245 } else {
262- auto eml_path = make_eml_path (cu_get_maildir (), mid_string);
263- slurp_data.reset (HX_slurp_file (eml_path.c_str (), &slurp_size));
264- if (slurp_data == nullptr ) {
265- mlog (LV_ERR, " E-1252: %s: %s" , eml_path.c_str (), strerror (errno));
246+ if (!exmdb_client::imapfile_read (dir, " eml" , mid_string, &slurp_data))
266247 return 0 ;
267- }
268248 MAIL imail;
269- if (!imail.load_from_str (slurp_data.get (), slurp_size ))
249+ if (!imail.load_from_str (slurp_data.c_str (), slurp_data. size () ))
270250 return 0 ;
271- slurp_data. reset () ;
251+ size_t size = 0 ;
272252 if (imail.make_digest (&size, digest) <= 0 )
273253 return 0 ;
274- imail.clear ();
275254 digest[" file" ] = " " ;
276255 auto djson = json_to_str (digest);
277- wrapfd fd = open (ext_path.c_str (), O_CREAT | O_TRUNC | O_WRONLY, FMODE_PRIVATE);
278- if (fd.get () >= 0 ) {
279- if (HXio_fullwrite (fd.get (), djson.c_str (), djson.size ()) < 0 ||
280- fd.close_wr () != 0 )
281- mlog (LV_ERR, " E-2082: write %s: %s" , ext_path.c_str (), strerror (errno));
282- } else {
283- mlog (LV_ERR, " E-2138: open %s for write: %s" , ext_path.c_str (), strerror (errno));
256+ if (!exmdb_client::imapfile_write (dir, " ext" , mid_string, djson)) {
257+ mlog (LV_ERR, " E-1754: imapfile_write %s/ext/%s did not complete" ,
258+ dir, mid_string);
259+ return 0 ;
284260 }
285261 }
286262 auto pstmt = gx_sql_prep (psqlite, " SELECT uid, recent, read,"
@@ -396,70 +372,56 @@ static std::unique_ptr<char[]> me_ct_decode_mime(const char *charset,
396372static void me_ct_enum_mime (MJSON_MIME *pmime, void *param) try
397373{
398374 auto penum = static_cast <KEYWORD_ENUM *>(param);
399- size_t temp_len;
400- const char *charset;
401- const char *filename;
402-
403375 if (penum->b_result )
404376 return ;
405377 if (pmime->get_mtype () != mime_type::single &&
406378 pmime->get_mtype () != mime_type::single_obj)
407379 return ;
408380
409381 if (strncmp (pmime->get_ctype (), " text/" , 5 ) != 0 ) {
410- filename = pmime->get_filename ();
382+ auto filename = pmime->get_filename ();
411383 if (' \0 ' != filename[0 ]) {
412384 auto rs = me_ct_decode_mime (penum->charset , filename);
413385 if (rs != nullptr &&
414386 strcasestr (rs.get (), penum->keyword ) != nullptr )
415387 penum->b_result = TRUE ;
416388 }
417389 }
418- auto length = pmime->get_content_length ();
419- auto pbuff = std::make_unique<char []>(2 * length + 1 );
420- auto fd = penum->pjson ->seek_fd (pmime->get_id (), MJSON_MIME_CONTENT);
421- if (fd == -1 )
422- return ;
423- auto read_len = HXio_fullread (fd, pbuff.get (), length);
424- if (read_len < 0 || static_cast <size_t >(read_len) != length)
390+ std::string content;
391+ if (!exmdb_client::imapfile_read (cu_get_maildir (), " eml" ,
392+ penum->pjson ->filename , &content))
425393 return ;
394+ std::string_view ctview (content.data () + pmime->begin ,
395+ std::min (content.size (), pmime->get_content_length ()));
426396 if (strcasecmp (pmime->get_encoding (), " base64" ) == 0 ) {
427- if (decode64_ex (pbuff.get (), length, &pbuff[length],
428- length, &temp_len) != 0 )
429- return ;
430- pbuff[length + temp_len] = ' \0 ' ;
397+ content = base64_decode (ctview);
431398 } else if (strcasecmp (pmime->get_encoding (), " quoted-printable" ) == 0 ) {
432- auto xl = qp_decode_ex (&pbuff[length ], length, pbuff. get (), length );
399+ auto xl = qp_decode_ex (&content[ 0 ], content. size (), content. c_str (), content. size () );
433400 if (xl < 0 )
434401 return ;
435- temp_len = xl;
436- pbuff[length + temp_len] = ' \0 ' ;
437- } else {
438- memcpy (&pbuff[length], pbuff.get (), length);
439- pbuff[2 *length] = ' \0 ' ;
402+ content.resize (xl);
440403 }
441404
442- charset = pmime->get_charset ();
405+ auto charset = pmime->get_charset ();
443406 auto rs = me_ct_to_utf8 (*charset != ' \0 ' ?
444- charset : penum->charset , &pbuff[length] );
407+ charset : penum->charset , content. c_str () );
445408 if (rs != nullptr && strcasestr (rs.get (), penum->keyword ) != nullptr )
446409 penum->b_result = TRUE ;
447410} catch (const std::bad_alloc &) {
448411 mlog (LV_ERR, " E-1970: ENOMEM" );
449412}
450413
451- static bool me_ct_search_head (const char *charset,
452- const char *file_path, const char *tag, const char *value)
414+ static bool me_ct_search_head (const char *charset, const char *mid_string,
415+ const char *tag, const char *value)
453416{
454- size_t slurp_size = 0 ;
455- std::unique_ptr< char [], stdlib_delete> ct ( HX_slurp_file (file_path, &slurp_size));
456- if (ct == nullptr )
417+ std::string content ;
418+ if (! exmdb_client::imapfile_read ( cu_get_maildir (), " eml " ,
419+ mid_string, &content) )
457420 return false ;
458-
459421 vmime::parsingContext vpctx;
460422 vpctx.setInternationalizedEmailSupport (true ); /* RFC 6532 */
461423 vmime::header hdr;
462- hdr.parse (vpctx, std::string (ct. get (), slurp_size) );
424+ hdr.parse (vpctx, content );
463425
464426 for (const auto &hf : hdr.getFieldList ()) {
465427 auto hk = hf->getName ();
@@ -634,8 +596,7 @@ static bool me_ct_match_mail(sqlite3 *psqlite, const char *charset,
634596 break ;
635597 }
636598 case midb_cond::header:
637- b_result1 = me_ct_search_head (charset,
638- make_eml_path (cu_get_maildir (), mid_string).c_str (),
599+ b_result1 = me_ct_search_head (charset, mid_string,
639600 ptree_node->ct_headers [0 ],
640601 ptree_node->ct_headers [1 ]);
641602 break ;
@@ -1371,15 +1332,9 @@ static void me_insert_message(xstmt &stm_insert, uint32_t *puidnext,
13711332
13721333 auto dir = cu_get_maildir ();
13731334 std::string djson;
1374- if (e.midstr .size () > 0 ) {
1375- auto ext_path = make_ext_path (dir, e.midstr );
1376- size_t slurp_size = 0 ;
1377- std::unique_ptr<char [], stdlib_delete> slurp_data (HX_slurp_file (ext_path.c_str (), &slurp_size));
1378- if (slurp_data == nullptr )
1379- e.midstr .clear ();
1380- else
1381- djson.assign (slurp_data.get (), slurp_size);
1382- }
1335+ if (e.midstr .size () > 0 &&
1336+ !exmdb_client::imapfile_read (dir, " ext" , e.midstr , &djson))
1337+ e.midstr .clear ();
13831338 if (e.midstr .empty ()) {
13841339 if (!cu_switch_allocator ())
13851340 return ;
@@ -1412,28 +1367,18 @@ static void me_insert_message(xstmt &stm_insert, uint32_t *puidnext,
14121367 digest[" file" ] = " " ;
14131368 djson = json_to_str (digest);
14141369 e.midstr = std::to_string (time (nullptr )) + " ." + std::to_string (++g_sequence_id) + " .midb" ;
1415- auto ext_path = make_ext_path (dir, e.midstr );
1416- wrapfd fd = open (ext_path.c_str (), O_CREAT | O_TRUNC | O_WRONLY, FMODE_PRIVATE);
1417- if (fd.get () < 0 ) {
1418- mlog (LV_ERR, " E-1770: open %s for write: %s" , ext_path.c_str (), strerror (errno));
1419- return ;
1420- }
1421- if (HXio_fullwrite (fd.get (), djson.c_str (), djson.size ()) < 0 ||
1422- fd.close_wr () != 0 ) {
1423- mlog (LV_ERR, " E-1134: write %s: %s" , ext_path.c_str (), strerror (errno));
1370+ if (!exmdb_client::imapfile_write (dir, " ext" , e.midstr , djson)) {
1371+ mlog (LV_ERR, " E-1770: imapfile_write %s/ext/%s incomplete" , dir, e.midstr .c_str ());
14241372 return ;
14251373 }
1426- auto eml_path = make_eml_path (dir, e. midstr ) ;
1427- fd = open (eml_path. c_str (), O_CREAT | O_TRUNC | O_WRONLY, FMODE_PRIVATE );
1428- if (fd. get () < 0 ) {
1429- mlog (LV_ERR, " E-1771: open %s for write : %s" , eml_path. c_str (), strerror (errno ));
1374+ std::string emlcontent ;
1375+ auto err = imail. to_str (emlcontent );
1376+ if (err != 0 ) {
1377+ mlog (LV_ERR, " E-1771: imail.to_string failed : %s" , strerror (err ));
14301378 return ;
14311379 }
1432- auto err = imail.to_fd (fd.get ());
1433- if (err == 0 )
1434- err = fd.close_wr ();
1435- if (err != 0 ) {
1436- mlog (LV_ERR, " E-1772: to_file %s failed: %s" , eml_path.c_str (), strerror (err));
1380+ if (!exmdb_client::imapfile_write (dir, " eml" , e.midstr , emlcontent)) {
1381+ mlog (LV_ERR, " E-1772: imapfile_write %s/eml/%s failed" , dir, e.midstr .c_str ());
14371382 return ;
14381383 }
14391384 }
@@ -2173,32 +2118,24 @@ static int me_minst(int argc, char **argv, int sockd) try
21732118
21742119 uint8_t b_unsent = strchr (argv[4 ], midb_flag::unsent) != nullptr ;
21752120 uint8_t b_read = strchr (argv[4 ], midb_flag::seen) != nullptr ;
2176- auto eml_path = make_eml_path (argv[1 ], argv[3 ]);
2177- size_t slurp_size = 0 ;
2178- std::unique_ptr<char [], stdlib_delete> pbuff (HX_slurp_file (eml_path.c_str (), &slurp_size));
2179- if (pbuff == nullptr ) {
2180- mlog (LV_ERR, " E-2071: read %s: %s" , eml_path.c_str (), strerror (errno));
2181- return errno == ENOMEM ? MIDB_E_NO_MEMORY : MIDB_E_DISK_ERROR;
2121+ std::string pbuff;
2122+ if (!exmdb_client::imapfile_read (argv[1 ], " eml" , argv[3 ], &pbuff)) {
2123+ mlog (LV_ERR, " E-2071: imapfile_read %s/eml/%s failed" , argv[1 ], argv[3 ]);
2124+ return MIDB_E_DISK_ERROR;
21822125 }
21832126
21842127 MAIL imail;
2185- if (!imail.load_from_str (pbuff.get (), slurp_size ))
2128+ if (!imail.load_from_str (pbuff.c_str (), pbuff. size () ))
21862129 return MIDB_E_IMAIL_RETRIEVE;
21872130 Json::Value digest;
21882131 if (imail.make_digest (&mess_len, digest) <= 0 )
21892132 return MIDB_E_IMAIL_DIGEST;
21902133 digest[" file" ] = " " ;
21912134 auto djson = json_to_str (digest);
2192- auto ext_path = make_ext_path (argv[1 ], argv[3 ]);
2193- wrapfd fd = open (ext_path.c_str (), O_CREAT | O_TRUNC | O_WRONLY, FMODE_PRIVATE);
2194- if (fd.get () < 0 ) {
2195- mlog (LV_ERR, " E-2073: Opening %s for writing failed: %s" ,
2196- ext_path.c_str (), strerror (errno));
2135+ if (!exmdb_client::imapfile_write (argv[1 ], " ext" , argv[3 ], djson)) {
2136+ mlog (LV_ERR, " E-2073: imapfile_write %s/ext/%s failed" , argv[1 ], argv[3 ]);
21972137 return MIDB_E_DISK_ERROR;
21982138 }
2199- if (HXio_fullwrite (fd.get (), djson.data (), djson.size ()) < 0 ||
2200- fd.close_wr () != 0 )
2201- mlog (LV_ERR, " E-2085: write %s: %s" , ext_path.c_str (), strerror (errno));
22022139 auto pidb = me_get_idb (argv[1 ]);
22032140 if (pidb == nullptr )
22042141 return MIDB_E_HASHTABLE_FULL;
@@ -2222,7 +2159,7 @@ static int me_minst(int argc, char **argv, int sockd) try
22222159 auto pmsgctnt = oxcmail_import (charset, tmzone, &imail,
22232160 cu_alloc_bytes, cu_get_propids_create);
22242161 imail.clear ();
2225- pbuff.reset ();
2162+ pbuff.clear ();
22262163 if (pmsgctnt == nullptr )
22272164 return MIDB_E_OXCMAIL_IMPORT;
22282165 auto cl_msg = make_scope_exit ([&]() { message_content_free (pmsgctnt); });
0 commit comments