292
static void decode_header(char *it);
290
static void decode_header(char *it, unsigned itsize);
293
291
static char *header[MAX_HDR_PARSED] = {
294
292
"From","Subject","Date",
297
static int check_header(char *line, char **hdr_data, int overwrite)
295
static int check_header(char *line, unsigned linesize, char **hdr_data, int overwrite)
307
305
/* Unwrap inline B and Q encoding, and optionally
308
306
* normalize the meta information to utf8.
310
decode_header(line + len + 2);
308
decode_header(line + len + 2, linesize - len - 2);
311
309
hdr_data[i] = xmalloc(1000 * sizeof(char));
312
310
if (! handle_header(line, hdr_data[i], len + 2)) {
318
316
/* Content stuff */
319
317
if (!strncasecmp(line, "Content-Type", 12) &&
320
318
line[12] == ':' && isspace(line[12 + 1])) {
321
decode_header(line + 12 + 2);
319
decode_header(line + 12 + 2, linesize - 12 - 2);
322
320
if (! handle_content_type(line)) {
326
324
if (!strncasecmp(line, "Content-Transfer-Encoding", 25) &&
327
325
line[25] == ':' && isspace(line[25 + 1])) {
328
decode_header(line + 25 + 2);
326
decode_header(line + 25 + 2, linesize - 25 - 2);
329
327
if (! handle_content_transfer_encoding(line)) {
436
static int decode_q_segment(char *in, char *ot, char *ep, int rfc2047)
435
static int decode_q_segment(char *in, char *ot, unsigned otsize, char *ep, int rfc2047)
437
char *otend = ot + otsize;
439
439
while ((c = *in++) != 0 && (in <= ep)) {
442
446
if (d == '\n' || !d)
455
static int decode_b_segment(char *in, char *ot, char *ep)
459
static int decode_b_segment(char *in, char *ot, unsigned otsize, char *ep)
457
461
/* Decode in..ep, possibly in-place to ot */
458
462
int c, pos = 0, acc = 0;
463
char *otend = ot + otsize;
460
465
while ((c = *in++) != 0 && (in <= ep)) {
463
472
else if (c == '/')
502
static void convert_to_utf8(char *line, const char *charset)
504
static const char latin_one[] = "latin1";
505
const char *input_charset = *charset ? charset : latin_one;
506
char *out = reencode_string(line, metainfo_charset, input_charset);
512
* When there is no known charset, guess.
514
* Right now we assume that if the target is UTF-8 (the default),
515
* and it already looks like UTF-8 (which includes US-ASCII as its
516
* subset, of course) then that is what it is and there is nothing
519
* Otherwise, we default to assuming it is Latin1 for historical
522
static const char *guess_charset(const char *line, const char *target_charset)
524
if (is_encoding_utf8(target_charset)) {
531
static void convert_to_utf8(char *line, unsigned linesize, const char *charset)
535
if (!charset || !*charset) {
536
charset = guess_charset(line, metainfo_charset);
541
if (!strcmp(metainfo_charset, charset))
543
out = reencode_string(line, metainfo_charset, charset);
509
545
die("cannot convert from %s to %s\n",
510
input_charset, metainfo_charset);
546
charset, metainfo_charset);
547
strlcpy(line, out, linesize);
515
static int decode_header_bq(char *it)
551
static int decode_header_bq(char *it, unsigned itsize)
517
553
char *in, *out, *ep, *cp, *sp;
518
554
char outbuf[1000];
553
589
return rfc2047; /* no munging */
555
sz = decode_b_segment(cp + 3, piecebuf, ep);
591
sz = decode_b_segment(cp + 3, piecebuf, sizeof(piecebuf), ep);
558
sz = decode_q_segment(cp + 3, piecebuf, ep, 1);
594
sz = decode_q_segment(cp + 3, piecebuf, sizeof(piecebuf), ep, 1);
563
599
if (metainfo_charset)
564
convert_to_utf8(piecebuf, charset_q);
600
convert_to_utf8(piecebuf, sizeof(piecebuf), charset_q);
602
sz = strlen(piecebuf);
603
if (outbuf + sizeof(outbuf) <= out + sz)
604
return rfc2047; /* no munging */
565
605
strcpy(out, piecebuf);
610
strlcpy(it, outbuf, itsize);
574
static void decode_header(char *it)
614
static void decode_header(char *it, unsigned itsize)
577
if (decode_header_bq(it))
617
if (decode_header_bq(it, itsize))
579
619
/* otherwise "it" is a straight copy of the input.
580
620
* This can be binary guck but there is no charset specified.
582
622
if (metainfo_charset)
583
convert_to_utf8(it, "");
623
convert_to_utf8(it, itsize, "");
586
static void decode_transfer_encoding(char *line)
626
static void decode_transfer_encoding(char *line, unsigned linesize)
590
630
switch (transfer_encoding) {
592
632
ep = line + strlen(line);
593
decode_q_segment(line, line, ep, 0);
633
decode_q_segment(line, line, linesize, ep, 0);
596
636
ep = line + strlen(line);
597
decode_b_segment(line, line, ep);
637
decode_b_segment(line, line, linesize, ep);
599
639
case TE_DONTCARE:
604
static int handle_filter(char *line);
644
static int handle_filter(char *line, unsigned linesize);
606
646
static int find_boundary(void)
645
685
/* slurp in this section's info */
646
686
while (read_one_header_line(line, sizeof(line), fin))
647
check_header(line, p_hdr_data, 0);
687
check_header(line, sizeof(line), p_hdr_data, 0);
649
689
/* eat the blank line after section info */
650
690
return (fgets(line, sizeof(line), fin) != NULL);
703
if ((still_looking = check_header(cp, s_hdr_data, 0)) != 0)
744
if ((still_looking = check_header(cp, endline - cp, s_hdr_data, 0)) != 0)
707
748
/* normalize the log message to UTF-8. */
708
749
if (metainfo_charset)
709
convert_to_utf8(line, charset);
750
convert_to_utf8(line, endline - line, charset);
711
752
if (patchbreak(line)) {
766
807
/* flush any leftover */
767
808
if ((transfer_encoding == TE_BASE64) &&
768
809
(np != newline)) {
769
handle_filter(newline);
810
handle_filter(newline, sizeof(newline));
771
812
if (!handle_boundary())
775
816
/* Unwrap transfer encoding */
776
decode_transfer_encoding(line);
817
decode_transfer_encoding(line, sizeof(line));
778
819
switch (transfer_encoding) {
863
static void output_header_lines(FILE *fout, const char *hdr, char *data)
866
char *ep = strchr(data, '\n');
872
fprintf(fout, "%s: %.*s\n", hdr, len, data);
822
879
static void handle_info(void)
838
895
if (!memcmp(header[i], "Subject", 7)) {
839
sub = cleanup_subject(hdr);
841
fprintf(fout, "Subject: %s\n", sub);
899
sub = cleanup_subject(hdr);
902
output_header_lines(fout, "Subject", sub);
842
903
} else if (!memcmp(header[i], "From", 4)) {
843
904
handle_from(hdr);
844
905
fprintf(fout, "Author: %s\n", name);
851
912
fprintf(fout, "\n");
854
int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,
855
const char *msg, const char *patch)
915
static int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,
916
const char *msg, const char *patch)
857
918
keep_subject = ks;
858
919
metainfo_charset = encoding;
877
938
/* process the email header */
878
939
while (read_one_header_line(line, sizeof(line), fin))
879
check_header(line, p_hdr_data, 1);
940
check_header(line, sizeof(line), p_hdr_data, 1);