~ubuntu-branches/ubuntu/intrepid/git-core/intrepid-security

« back to all changes in this revision

Viewing changes to builtin-mailinfo.c

  • Committer: Package Import Robot
  • Author(s): Gerrit Pape
  • Date: 2007-10-04 08:27:01 UTC
  • mfrom: (1.1.23)
  • Revision ID: package-import@ubuntu.com-20071004082701-rsd058ontoqz4i30
Tags: 1:1.5.3.4-1
new upstream point release (closes: #445188).

Show diffs side-by-side

added added

removed removed

Lines of Context:
237
237
 
238
238
static char *cleanup_subject(char *subject)
239
239
{
240
 
        if (keep_subject)
241
 
                return subject;
242
240
        for (;;) {
243
241
                char *p;
244
242
                int len, remove;
289
287
        }
290
288
}
291
289
 
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",
295
293
};
296
294
 
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)
298
296
{
299
297
        int i;
300
298
 
307
305
                        /* Unwrap inline B and Q encoding, and optionally
308
306
                         * normalize the meta information to utf8.
309
307
                         */
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)) {
313
311
                                return 1;
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)) {
323
321
                        return 1;
324
322
                }
325
323
        }
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)) {
330
328
                        return 1;
331
329
                }
425
423
                        if (addlen >= sz - len)
426
424
                                addlen = sz - len - 1;
427
425
                        memcpy(line + len, continuation, addlen);
 
426
                        line[len] = '\n';
428
427
                        len += addlen;
429
428
                }
430
429
        }
433
432
        return 1;
434
433
}
435
434
 
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
436
{
 
437
        char *otend = ot + otsize;
438
438
        int c;
439
439
        while ((c = *in++) != 0 && (in <= ep)) {
 
440
                if (ot == otend) {
 
441
                        *--ot = '\0';
 
442
                        return -1;
 
443
                }
440
444
                if (c == '=') {
441
445
                        int d = *in++;
442
446
                        if (d == '\n' || !d)
452
456
        return 0;
453
457
}
454
458
 
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)
456
460
{
457
461
        /* Decode in..ep, possibly in-place to ot */
458
462
        int c, pos = 0, acc = 0;
 
463
        char *otend = ot + otsize;
459
464
 
460
465
        while ((c = *in++) != 0 && (in <= ep)) {
 
466
                if (ot == otend) {
 
467
                        *--ot = '\0';
 
468
                        return -1;
 
469
                }
461
470
                if (c == '+')
462
471
                        c = 62;
463
472
                else if (c == '/')
499
508
        return 0;
500
509
}
501
510
 
502
 
static void convert_to_utf8(char *line, const char *charset)
503
 
{
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);
507
 
 
 
511
/*
 
512
 * When there is no known charset, guess.
 
513
 *
 
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
 
517
 * to do.
 
518
 *
 
519
 * Otherwise, we default to assuming it is Latin1 for historical
 
520
 * reasons.
 
521
 */
 
522
static const char *guess_charset(const char *line, const char *target_charset)
 
523
{
 
524
        if (is_encoding_utf8(target_charset)) {
 
525
                if (is_utf8(line))
 
526
                        return NULL;
 
527
        }
 
528
        return "latin1";
 
529
}
 
530
 
 
531
static void convert_to_utf8(char *line, unsigned linesize, const char *charset)
 
532
{
 
533
        char *out;
 
534
 
 
535
        if (!charset || !*charset) {
 
536
                charset = guess_charset(line, metainfo_charset);
 
537
                if (!charset)
 
538
                        return;
 
539
        }
 
540
 
 
541
        if (!strcmp(metainfo_charset, charset))
 
542
                return;
 
543
        out = reencode_string(line, metainfo_charset, charset);
508
544
        if (!out)
509
545
                die("cannot convert from %s to %s\n",
510
 
                    input_charset, metainfo_charset);
511
 
        strcpy(line, out);
 
546
                    charset, metainfo_charset);
 
547
        strlcpy(line, out, linesize);
512
548
        free(out);
513
549
}
514
550
 
515
 
static int decode_header_bq(char *it)
 
551
static int decode_header_bq(char *it, unsigned itsize)
516
552
{
517
553
        char *in, *out, *ep, *cp, *sp;
518
554
        char outbuf[1000];
552
588
                default:
553
589
                        return rfc2047; /* no munging */
554
590
                case 'b':
555
 
                        sz = decode_b_segment(cp + 3, piecebuf, ep);
 
591
                        sz = decode_b_segment(cp + 3, piecebuf, sizeof(piecebuf), ep);
556
592
                        break;
557
593
                case 'q':
558
 
                        sz = decode_q_segment(cp + 3, piecebuf, ep, 1);
 
594
                        sz = decode_q_segment(cp + 3, piecebuf, sizeof(piecebuf), ep, 1);
559
595
                        break;
560
596
                }
561
597
                if (sz < 0)
562
598
                        return rfc2047;
563
599
                if (metainfo_charset)
564
 
                        convert_to_utf8(piecebuf, charset_q);
 
600
                        convert_to_utf8(piecebuf, sizeof(piecebuf), charset_q);
 
601
 
 
602
                sz = strlen(piecebuf);
 
603
                if (outbuf + sizeof(outbuf) <= out + sz)
 
604
                        return rfc2047; /* no munging */
565
605
                strcpy(out, piecebuf);
566
 
                out += strlen(out);
 
606
                out += sz;
567
607
                in = ep + 2;
568
608
        }
569
609
        strcpy(out, in);
570
 
        strcpy(it, outbuf);
 
610
        strlcpy(it, outbuf, itsize);
571
611
        return rfc2047;
572
612
}
573
613
 
574
 
static void decode_header(char *it)
 
614
static void decode_header(char *it, unsigned itsize)
575
615
{
576
616
 
577
 
        if (decode_header_bq(it))
 
617
        if (decode_header_bq(it, itsize))
578
618
                return;
579
619
        /* otherwise "it" is a straight copy of the input.
580
620
         * This can be binary guck but there is no charset specified.
581
621
         */
582
622
        if (metainfo_charset)
583
 
                convert_to_utf8(it, "");
 
623
                convert_to_utf8(it, itsize, "");
584
624
}
585
625
 
586
 
static void decode_transfer_encoding(char *line)
 
626
static void decode_transfer_encoding(char *line, unsigned linesize)
587
627
{
588
628
        char *ep;
589
629
 
590
630
        switch (transfer_encoding) {
591
631
        case TE_QP:
592
632
                ep = line + strlen(line);
593
 
                decode_q_segment(line, line, ep, 0);
 
633
                decode_q_segment(line, line, linesize, ep, 0);
594
634
                break;
595
635
        case TE_BASE64:
596
636
                ep = line + strlen(line);
597
 
                decode_b_segment(line, line, ep);
 
637
                decode_b_segment(line, line, linesize, ep);
598
638
                break;
599
639
        case TE_DONTCARE:
600
640
                break;
601
641
        }
602
642
}
603
643
 
604
 
static int handle_filter(char *line);
 
644
static int handle_filter(char *line, unsigned linesize);
605
645
 
606
646
static int find_boundary(void)
607
647
{
629
669
                                        "can't recover\n");
630
670
                        exit(1);
631
671
                }
632
 
                handle_filter(newline);
 
672
                handle_filter(newline, sizeof(newline));
633
673
 
634
674
                /* skip to the next boundary */
635
675
                if (!find_boundary())
644
684
 
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);
648
688
 
649
689
        /* eat the blank line after section info */
650
690
        return (fgets(line, sizeof(line), fin) != NULL);
683
723
}
684
724
 
685
725
 
686
 
static int handle_commit_msg(char *line)
 
726
static int handle_commit_msg(char *line, unsigned linesize)
687
727
{
688
728
        static int still_looking = 1;
 
729
        char *endline = line + linesize;
689
730
 
690
731
        if (!cmitmsg)
691
732
                return 0;
700
741
                        if (!*cp)
701
742
                                return 0;
702
743
                }
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)
704
745
                        return 0;
705
746
        }
706
747
 
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);
710
751
 
711
752
        if (patchbreak(line)) {
712
753
                fclose(cmitmsg);
725
766
        return 0;
726
767
}
727
768
 
728
 
static int handle_filter(char *line)
 
769
static int handle_filter(char *line, unsigned linesize)
729
770
{
730
771
        static int filter = 0;
731
772
 
734
775
         */
735
776
        switch (filter) {
736
777
        case 0:
737
 
                if (!handle_commit_msg(line))
 
778
                if (!handle_commit_msg(line, linesize))
738
779
                        break;
739
780
                filter++;
740
781
        case 1:
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));
770
811
                        }
771
812
                        if (!handle_boundary())
772
813
                                return;
773
814
                }
774
815
 
775
816
                /* Unwrap transfer encoding */
776
 
                decode_transfer_encoding(line);
 
817
                decode_transfer_encoding(line, sizeof(line));
777
818
 
778
819
                switch (transfer_encoding) {
779
820
                case TE_BASE64:
782
823
 
783
824
                        /* binary data most likely doesn't have newlines */
784
825
                        if (message_type != TYPE_TEXT) {
785
 
                                rc = handle_filter(line);
 
826
                                rc = handle_filter(line, sizeof(newline));
786
827
                                break;
787
828
                        }
788
829
 
799
840
                                        /* should be sitting on a new line */
800
841
                                        *(++np) = 0;
801
842
                                        op++;
802
 
                                        rc = handle_filter(newline);
 
843
                                        rc = handle_filter(newline, sizeof(newline));
803
844
                                        np = newline;
804
845
                                }
805
846
                        } while (*op != 0);
809
850
                        break;
810
851
                }
811
852
                default:
812
 
                        rc = handle_filter(line);
 
853
                        rc = handle_filter(line, sizeof(newline));
813
854
                }
814
855
                if (rc)
815
856
                        /* nothing left to filter */
819
860
        return;
820
861
}
821
862
 
 
863
static void output_header_lines(FILE *fout, const char *hdr, char *data)
 
864
{
 
865
        while (1) {
 
866
                char *ep = strchr(data, '\n');
 
867
                int len;
 
868
                if (!ep)
 
869
                        len = strlen(data);
 
870
                else
 
871
                        len = ep - data;
 
872
                fprintf(fout, "%s: %.*s\n", hdr, len, data);
 
873
                if (!ep)
 
874
                        break;
 
875
                data = ep + 1;
 
876
        }
 
877
}
 
878
 
822
879
static void handle_info(void)
823
880
{
824
881
        char *sub;
836
893
                        continue;
837
894
 
838
895
                if (!memcmp(header[i], "Subject", 7)) {
839
 
                        sub = cleanup_subject(hdr);
840
 
                        cleanup_space(sub);
841
 
                        fprintf(fout, "Subject: %s\n", sub);
 
896
                        if (keep_subject)
 
897
                                sub = hdr;
 
898
                        else {
 
899
                                sub = cleanup_subject(hdr);
 
900
                                cleanup_space(sub);
 
901
                        }
 
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");
852
913
}
853
914
 
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)
856
917
{
857
918
        keep_subject = ks;
858
919
        metainfo_charset = encoding;
876
937
 
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);
880
941
 
881
942
        handle_body();
882
943
        handle_info();