Skip to content

Commit 09a2cee

Browse files
committed
eml2mt: send RFC53222-EML file contents into GXMT stream
References: GXH-155, GXF-2229
1 parent 8886fd4 commit 09a2cee

File tree

1 file changed

+64
-33
lines changed

1 file changed

+64
-33
lines changed

tools/eml2mt.cpp

Lines changed: 64 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,18 @@ using namespace gromox;
3636
using namespace gi_dump;
3737
using 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+
3951
enum {
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

122134
enum class mbox_rid { start, envelope_from, msghdr, msgbody, emit };
123135

124136
struct 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

Comments
 (0)