35 |
-c auto to set Content-Type: to text/plain or |
-c auto to set Content-Type: to text/plain or |
36 |
application/octet-stream based on picked encoding. |
application/octet-stream based on picked encoding. |
37 |
-j file1 file2 - join mime section file2 to multipart section file1. |
-j file1 file2 - join mime section file2 to multipart section file1. |
38 |
-o file - write ther result to file, instead of stdout (not |
-o file - write the result to file, instead of stdout (not |
39 |
allowed in child processes). |
allowed in child processes). |
40 |
-a header - prepend an additional header to the output. |
-a header - prepend an additional header to the output. |
41 |
|
|
42 |
@file - read all of the above options from file, one option or |
@file - read all of the above options from file, one option or |
43 |
value on each line. |
value on each line. |
44 |
|
{which version of makemime is this? What do we support?} |
45 |
|
*/ |
46 |
|
|
47 |
|
|
48 |
|
/* In busybox 1.15.0.svn, makemime generates output like this |
49 |
|
* (empty lines are shown exactly!): |
50 |
|
{headers added with -a HDR} |
51 |
|
Mime-Version: 1.0 |
52 |
|
Content-Type: multipart/mixed; boundary="24269534-2145583448-1655890676" |
53 |
|
|
54 |
|
--24269534-2145583448-1655890676 |
55 |
|
Content-Type: {set by -c, e.g. text/plain}; charset={set by -C, e.g. us-ascii} |
56 |
|
Content-Disposition: inline; filename="A" |
57 |
|
Content-Transfer-Encoding: base64 |
58 |
|
|
59 |
|
...file A contents... |
60 |
|
--24269534-2145583448-1655890676 |
61 |
|
Content-Type: {set by -c, e.g. text/plain}; charset={set by -C, e.g. us-ascii} |
62 |
|
Content-Disposition: inline; filename="B" |
63 |
|
Content-Transfer-Encoding: base64 |
64 |
|
|
65 |
|
...file B contents... |
66 |
|
--24269534-2145583448-1655890676-- |
67 |
|
|
68 |
|
*/ |
69 |
|
|
70 |
|
|
71 |
|
/* For reference: here is an example email to LKML which has |
72 |
|
* 1st unnamed part (so it serves as an email body) |
73 |
|
* and one attached file: |
74 |
|
...other headers... |
75 |
|
Content-Type: multipart/mixed; boundary="=-tOfTf3byOS0vZgxEWcX+" |
76 |
|
...other headers... |
77 |
|
Mime-Version: 1.0 |
78 |
|
...other headers... |
79 |
|
|
80 |
|
|
81 |
|
--=-tOfTf3byOS0vZgxEWcX+ |
82 |
|
Content-Type: text/plain |
83 |
|
Content-Transfer-Encoding: 7bit |
84 |
|
|
85 |
|
...email text... |
86 |
|
...email text... |
87 |
|
|
88 |
|
|
89 |
|
--=-tOfTf3byOS0vZgxEWcX+ |
90 |
|
Content-Disposition: attachment; filename="xyz" |
91 |
|
Content-Type: text/plain; name="xyz"; charset="UTF-8" |
92 |
|
Content-Transfer-Encoding: 7bit |
93 |
|
|
94 |
|
...file contents... |
95 |
|
...file contents... |
96 |
|
|
97 |
|
--=-tOfTf3byOS0vZgxEWcX+-- |
98 |
|
|
99 |
|
...random junk added by mailing list robots and such... |
100 |
*/ |
*/ |
101 |
|
|
102 |
int makemime_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
int makemime_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
142 |
|
|
143 |
// make a random string -- it will delimit message parts |
// make a random string -- it will delimit message parts |
144 |
srand(monotonic_us()); |
srand(monotonic_us()); |
145 |
boundary = xasprintf("%d-%d-%d", rand(), rand(), rand()); |
boundary = xasprintf("%u-%u-%u", |
146 |
|
(unsigned)rand(), (unsigned)rand(), (unsigned)rand()); |
147 |
|
|
148 |
// put multipart header |
// put multipart header |
149 |
printf( |
printf( |
177 |
static const char *find_token(const char *const string_array[], const char *key, const char *defvalue) |
static const char *find_token(const char *const string_array[], const char *key, const char *defvalue) |
178 |
{ |
{ |
179 |
const char *r = NULL; |
const char *r = NULL; |
180 |
for (int i = 0; string_array[i] != 0; i++) { |
int i; |
181 |
|
for (i = 0; string_array[i] != NULL; i++) { |
182 |
if (strcasecmp(string_array[i], key) == 0) { |
if (strcasecmp(string_array[i], key) == 0) { |
183 |
r = (char *)string_array[i+1]; |
r = (char *)string_array[i+1]; |
184 |
break; |
break; |
233 |
// N.B. to avoid false positives let us seek to the _last_ occurance |
// N.B. to avoid false positives let us seek to the _last_ occurance |
234 |
p = NULL; |
p = NULL; |
235 |
s = line; |
s = line; |
236 |
while ((s=strcasestr(s, "Content-Type:")) != NULL) |
while ((s = strcasestr(s, "Content-Type:")) != NULL) |
237 |
p = s++; |
p = s++; |
238 |
if (!p) |
if (!p) |
239 |
goto next; |
goto next; |
282 |
pid = vfork(); |
pid = vfork(); |
283 |
if (0 == pid) { |
if (0 == pid) { |
284 |
// child reads from fd[0] |
// child reads from fd[0] |
285 |
xdup2(fd[0], STDIN_FILENO); |
close(fd[1]); |
286 |
close(fd[0]); close(fd[1]); |
xmove_fd(fd[0], STDIN_FILENO); |
287 |
xsetenv("CONTENT_TYPE", type); |
xsetenv("CONTENT_TYPE", type); |
288 |
xsetenv("CHARSET", charset); |
xsetenv("CHARSET", charset); |
289 |
xsetenv("ENCODING", encoding); |
xsetenv("ENCODING", encoding); |
293 |
} |
} |
294 |
// parent dumps to fd[1] |
// parent dumps to fd[1] |
295 |
close(fd[0]); |
close(fd[0]); |
296 |
fp = fdopen(fd[1], "w"); |
fp = xfdopen_for_write(fd[1]); |
297 |
signal(SIGPIPE, SIG_IGN); // ignore EPIPE |
signal(SIGPIPE, SIG_IGN); // ignore EPIPE |
298 |
// or create a file for dump |
// or create a file for dump |
299 |
} else { |
} else { |
309 |
if (0 == strcasecmp(encoding, "base64")) { |
if (0 == strcasecmp(encoding, "base64")) { |
310 |
decode_base64(stdin, fp); |
decode_base64(stdin, fp); |
311 |
} else if (0 != strcasecmp(encoding, "7bit") |
} else if (0 != strcasecmp(encoding, "7bit") |
312 |
&& 0 != strcasecmp(encoding, "8bit")) { |
&& 0 != strcasecmp(encoding, "8bit") |
313 |
|
) { |
314 |
// quoted-printable, binary, user-defined are unsupported so far |
// quoted-printable, binary, user-defined are unsupported so far |
315 |
bb_error_msg_and_die("no support of encoding '%s'", encoding); |
bb_error_msg_and_die("no support of encoding '%s'", encoding); |
316 |
} else { |
} else { |
325 |
// no means to truncate what we already have sent to the helper. |
// no means to truncate what we already have sent to the helper. |
326 |
p = xmalloc_fgets_str(stdin, "\r\n"); |
p = xmalloc_fgets_str(stdin, "\r\n"); |
327 |
while (p) { |
while (p) { |
328 |
if ((s = xmalloc_fgets_str(stdin, "\r\n")) == NULL) |
s = xmalloc_fgets_str(stdin, "\r\n"); |
329 |
|
if (s == NULL) |
330 |
break; |
break; |
331 |
if ('-' == s[0] && '-' == s[1] |
if ('-' == s[0] |
332 |
&& 0 == strncmp(s+2, boundary, boundary_len)) |
&& '-' == s[1] |
333 |
|
&& 0 == strncmp(s+2, boundary, boundary_len) |
334 |
|
) { |
335 |
break; |
break; |
336 |
|
} |
337 |
fputs(p, fp); |
fputs(p, fp); |
338 |
p = s; |
p = s; |
339 |
} |
} |
369 |
} |
} |
370 |
} |
} |
371 |
next: |
next: |
372 |
free(line); |
free(line); |
373 |
} |
} |
374 |
|
|
375 |
//bb_info_msg("ENDPARSE[%s]", boundary); |
//bb_info_msg("ENDPARSE[%s]", boundary); |
404 |
|
|
405 |
// parse options |
// parse options |
406 |
// N.B. only -x and -X are supported so far |
// N.B. only -x and -X are supported so far |
407 |
opt_complementary = "x--X:X--x" USE_FEATURE_REFORMIME_COMPAT(":m::"); |
opt_complementary = "x--X:X--x" IF_FEATURE_REFORMIME_COMPAT(":m::"); |
408 |
opts = getopt32(argv, |
opts = getopt32(argv, |
409 |
"x:X" USE_FEATURE_REFORMIME_COMPAT("deis:r:c:m:h:o:O:"), |
"x:X" IF_FEATURE_REFORMIME_COMPAT("deis:r:c:m:h:o:O:"), |
410 |
&opt_prefix |
&opt_prefix |
411 |
USE_FEATURE_REFORMIME_COMPAT(, NULL, NULL, &G.opt_charset, NULL, NULL, NULL, NULL) |
IF_FEATURE_REFORMIME_COMPAT(, NULL, NULL, &G.opt_charset, NULL, NULL, NULL, NULL) |
412 |
); |
); |
413 |
//argc -= optind; |
//argc -= optind; |
414 |
argv += optind; |
argv += optind; |