@@ -36,6 +36,18 @@ using namespace gromox;
3636using namespace gi_dump ;
3737using message_ptr = std::unique_ptr<MESSAGE_CONTENT, mc_delete>;
3838
39+ /* *
40+ * @content: MAPI representation with broken-down fields
41+ * @im_std: Original RFC5322, stored in a std::string
42+ * @im_raw: Original RFC5322, stored in a malloc buffer
43+ */
44+ struct fat_message {
45+ message_ptr content;
46+ std::string im_std;
47+ std::unique_ptr<char [], stdlib_delete> im_raw;
48+ size_t im_len = 0 ;
49+ };
50+
3951enum {
4052 IMPORT_MAIL,
4153 IMPORT_ICAL,
@@ -85,44 +97,44 @@ static void terse_help()
8597 fprintf (stderr, " Documentation: man gromox-eml2mt\n " );
8698}
8799
88- static std::unique_ptr<MESSAGE_CONTENT, mc_delete>
89- do_mail (const char *file, char *data, size_t dsize)
100+ static message_ptr do_mail (const char *file, char *data, size_t dsize)
90101{
91102 MAIL imail;
92103 if (!imail.load_from_str (data, dsize)) {
93104 fprintf (stderr, " Unable to parse %s\n " , file);
94105 return nullptr ;
95106 }
96- std::unique_ptr<MESSAGE_CONTENT, mc_delete> msg (oxcmail_import (nullptr ,
97- " UTC" , &imail, gi_alloc, ee_get_propids));
107+ message_ptr msg (oxcmail_import (nullptr , " UTC" , &imail, gi_alloc, ee_get_propids));
98108 if (msg == nullptr )
99109 fprintf (stderr, " Failed to convert IM %s to MAPI\n " , file);
100110 return msg;
101111}
102112
103- static std::unique_ptr<MESSAGE_CONTENT, mc_delete> do_eml (const char *file)
113+ static fat_message do_eml (const char *file)
104114{
105- size_t slurp_len = 0 ;
106- std::unique_ptr<char [], stdlib_delete> slurp_data (strcmp (file, " -" ) == 0 ?
107- HX_slurp_fd (STDIN_FILENO, &slurp_len) : HX_slurp_file (file, &slurp_len));
108115 static constexpr uint64_t olecf_sig = 0xd0cf11e0a1b11ae1 , olecf_beta = 0x0e11fc0dd0cf110e ;
109- if (slurp_data == nullptr ) {
116+ fat_message mo;
117+
118+ mo.im_raw .reset (strcmp (file, " -" ) == 0 ? HX_slurp_fd (STDIN_FILENO, &mo.im_len ) :
119+ HX_slurp_file (file, &mo.im_len ));
120+ auto raw = mo.im_raw .get ();
121+ if (raw == nullptr ) {
110122 fprintf (stderr, " Unable to read from %s: %s\n " , file, strerror (errno));
111- return nullptr ;
112- } else if (slurp_len >= 8 &&
113- (be64p_to_cpu (slurp_data.get ()) == olecf_sig ||
114- be64p_to_cpu (slurp_data.get ()) == olecf_beta)) {
123+ return {};
124+ } else if (mo.im_len >= 8 && (be64p_to_cpu (raw) == olecf_sig ||
125+ be64p_to_cpu (raw) == olecf_beta)) {
115126 fprintf (stderr, " Input file %s looks like an OLECF file; "
116127 " you should use gromox-oxm2mt, not gromox-eml2mt "
117128 " (which is for Internet/RFC5322 mail).\n " , file);
118129 }
119- return do_mail (file, slurp_data.get (), slurp_len);
130+ mo.content = do_mail (file, raw, mo.im_len );
131+ return mo;
120132}
121133
122134enum class mbox_rid { start, envelope_from, msghdr, msgbody, emit };
123135
124136struct mbox_rdstate {
125- std::vector<message_ptr > &msgvec;
137+ std::vector<fat_message > &msgvec;
126138 std::string filename;
127139 size_t fncut = 0 ;
128140 unsigned int mail_count = 0 ;
@@ -169,8 +181,11 @@ static void mbox_line(mbox_rdstate &rs, const char *line)
169181 }
170182 rs.filename .erase (rs.fncut );
171183 rs.filename += std::to_string (++rs.mail_count );
172- auto mo = do_mail (rs.filename .c_str (), rs.cbuf .data (), rs.cbuf .size ());
173- if (mo == nullptr )
184+
185+ fat_message mo;
186+ mo.im_std = std::move (rs.cbuf );
187+ mo.content = do_mail (rs.filename .c_str (), mo.im_std .data (), mo.im_std .size ());
188+ if (mo.content == nullptr )
174189 throw std::bad_alloc ();
175190 rs.msgvec .push_back (std::move (mo));
176191 rs.cbuf = std::string ();
@@ -182,7 +197,7 @@ static void mbox_line(mbox_rdstate &rs, const char *line)
182197 }
183198}
184199
185- static errno_t do_mbox (const char *file, std::vector<message_ptr > &msgvec)
200+ static errno_t do_mbox (const char *file, std::vector<fat_message > &msgvec)
186201{
187202 std::unique_ptr<FILE, stdlib_delete> extra_fp;
188203 FILE *fp = nullptr ;
@@ -349,41 +364,50 @@ int main(int argc, char **argv) try
349364 auto cfg = config_file_prg (nullptr , " delivery.cfg" , delivery_cfg_defaults);
350365 if (cfg == nullptr )
351366 return EXIT_FAILURE;
352- std::vector<message_ptr> msgs;
353367
368+ std::vector<fat_message> msgs;
354369 for (int i = 1 ; i < argc; ++i) {
355370 if (g_import_mode == IMPORT_MAIL) {
356- auto msg = do_eml (argv[i]);
357- if (msg == nullptr )
371+ auto mo = do_eml (argv[i]);
372+ if (mo. content == nullptr )
358373 continue ;
359- msgs.push_back (std::move (msg ));
374+ msgs.push_back (std::move (mo ));
360375 } else if (g_import_mode == IMPORT_MBOX) {
361376 if (do_mbox (argv[i], msgs) != 0 )
362377 continue ;
363378 } else if (g_import_mode == IMPORT_ICAL) {
364- if (do_ical (argv[i], msgs) != 0 )
379+ std::vector<message_ptr> content_vec;
380+ if (do_ical (argv[i], content_vec) != 0 )
365381 continue ;
382+ for (auto &&ct : std::move (content_vec))
383+ msgs.emplace_back (std::move (ct));
366384 } else if (g_import_mode == IMPORT_VCARD) {
367- if (do_vcard (argv[i], msgs) != 0 )
385+ std::vector<message_ptr> content_vec;
386+ if (do_vcard (argv[i], content_vec) != 0 )
368387 continue ;
388+ for (auto &&ct : std::move (content_vec))
389+ msgs.emplace_back (std::move (ct));
369390 } else if (g_import_mode == IMPORT_TNEF) {
370- if (do_tnef (argv[i], msgs) != 0 )
391+ std::vector<message_ptr> content_vec;
392+ if (do_tnef (argv[i], content_vec) != 0 )
371393 continue ;
394+ for (auto &&ct : std::move (content_vec))
395+ msgs.emplace_back (std::move (ct));
372396 }
373397 }
374398 if (g_attach_decap > 0 ) {
375399 auto osize = msgs.size ();
376400 for (auto &msg : msgs) {
377- auto ret = gi_decapsulate_attachment (msg, g_attach_decap - 1 );
401+ auto ret = gi_decapsulate_attachment (msg. content , g_attach_decap - 1 );
378402 if (ret != 0 )
379- msg.reset ();
403+ msg.content . reset ();
380404 }
381- std::erase_if (msgs, [](const message_ptr &x ) { return x == nullptr ; });
405+ std::erase_if (msgs, [](const fat_message &mo ) { return mo. content == nullptr ; });
382406 fprintf (stderr, " Attachment decapsulation filter: %zu MAPI messages have been turned into %zu\n " ,
383407 osize, msgs.size ());
384408 }
385409
386- if (HXio_fullwrite (STDOUT_FILENO, " GXMT0003 " , 8 ) < 0 )
410+ if (HXio_fullwrite (STDOUT_FILENO, " GXMT0004 " , 8 ) < 0 )
387411 throw YError (" PG-1014: %s" , strerror (errno));
388412 uint8_t flag = false ;
389413 if (HXio_fullwrite (STDOUT_FILENO, &flag, sizeof (flag)) < 0 ) /* splice flag */
@@ -399,7 +423,7 @@ int main(int argc, char **argv) try
399423 for (size_t i = 0 ; i < msgs.size (); ++i) {
400424 if (g_show_tree) {
401425 fprintf (stderr, " Message %zu\n " , i + 1 );
402- gi_print (0 , *msgs[i], ee_get_propname);
426+ gi_print (0 , *msgs[i]. content , ee_get_propname);
403427 }
404428 EXT_PUSH ep;
405429 if (!ep.init (nullptr , 0 , EXT_FLAG_WCOUNT)) {
@@ -410,12 +434,19 @@ int main(int argc, char **argv) try
410434 ep.p_uint32 (i + 1 ) != pack_result::ok ||
411435 ep.p_uint32 (static_cast <uint32_t >(parent.type )) != pack_result::ok ||
412436 ep.p_uint64 (parent.folder_id ) != pack_result::ok ||
413- ep.p_msgctnt (*msgs[i]) != pack_result::ok ||
414- ep.p_str (" " ) != pack_result::ok ||
415- ep.p_str (" " ) != pack_result::ok) {
437+ ep.p_msgctnt (*msgs[i].content ) != pack_result::ok) {
416438 fprintf (stderr, " E-2004\n " );
417439 return EXIT_FAILURE;
418440 }
441+ pack_result pr2 =
442+ msgs[i].im_std .size () > 0 ? ep.p_str (msgs[i].im_std ) :
443+ msgs[i].im_raw != nullptr ? ep.p_str (msgs[i].im_raw .get ()) :
444+ ep.p_str (" " );
445+ if (pr2 != pack_result::ok || ep.p_str (" " ) != pack_result::ok) {
446+ fprintf (stderr, " E-2014\n " );
447+ return EXIT_FAILURE;
448+ }
449+
419450 uint64_t xsize = cpu_to_le64 (ep.m_offset );
420451 if (HXio_fullwrite (STDOUT_FILENO, &xsize, sizeof (xsize)) < 0 )
421452 throw YError (" PG-1017: %s" , strerror (errno));
0 commit comments