Imported Upstream version 0.66.1
[hcoop/debian/courier-authlib.git] / libs / rfc822 / encodeautodetect.c
1 /*
2 ** Copyright 2003-2011 Double Precision, Inc. See COPYING for
3 ** distribution information.
4 */
5
6 /*
7 */
8 #include "encode.h"
9 #include <string.h>
10 #include <stdlib.h>
11 #include "../unicode/unicode.h"
12
13 static const char *libmail_encode_autodetect(int use7bit,
14 int (*func)(void *), void *arg,
15 int *binaryflag)
16 {
17 int l=0;
18 int longline=0;
19 int c;
20
21 size_t charcnt=0;
22 size_t bit8cnt=0;
23
24 if (binaryflag)
25 *binaryflag=0;
26
27 while ((c = (*func)(arg)) != EOF)
28 {
29 unsigned char ch= (unsigned char)c;
30
31 ++charcnt;
32
33 ++l;
34 if (ch < 0x20 || ch >= 0x80)
35 {
36 if (ch != '\t' && ch != '\r' && ch != '\n')
37 {
38 ++bit8cnt;
39 l += 2;
40 }
41 }
42
43 if (ch == 0)
44 {
45 if (binaryflag)
46 *binaryflag=1;
47
48 return "base64";
49 }
50
51 if (ch == '\n') l=0;
52 else if (l > 990)
53 {
54 longline=1;
55 }
56
57 }
58
59 if (use7bit || longline)
60 {
61 if (bit8cnt > charcnt / 10)
62 return "base64";
63
64 return "quoted-printable";
65 }
66
67 return bit8cnt ? "8bit":"7bit";
68 }
69
70 struct file_info {
71 FILE *fp;
72 off_t pos;
73 off_t end;
74 };
75
76 static int read_file(void *arg)
77 {
78 int c;
79 struct file_info *fi = (struct file_info *)arg;
80 if (fi->end >= 0 && fi->pos > fi->end)
81 return EOF;
82 c = getc(fi->fp);
83 fi->pos++;
84 return c;
85 }
86
87 static int read_string(void * arg)
88 {
89 int c;
90 unsigned char **strp = (unsigned char **)arg;
91 if (**strp == 0)
92 return EOF;
93 c = (int)**strp;
94 (*strp)++;
95 return c;
96 }
97
98 const char *libmail_encode_autodetect_fp(FILE *fp, int use7bit,
99 int *binaryflag)
100 {
101 return libmail_encode_autodetect_fpoff(fp, use7bit, 0, -1,
102 binaryflag);
103 }
104
105 const char *libmail_encode_autodetect_fpoff(FILE *fp, int use7bit,
106 off_t start_pos, off_t end_pos,
107 int *binaryflag)
108 {
109 struct file_info fi;
110 off_t orig_pos = ftell(fp);
111 off_t pos = orig_pos;
112 const char *rc;
113
114 if (start_pos >= 0)
115 {
116 if (fseek(fp, start_pos, SEEK_SET) == (off_t)-1)
117 return NULL;
118 else
119 pos = start_pos;
120 }
121
122 fi.fp = fp;
123 fi.pos = pos;
124 fi.end = end_pos;
125
126 rc = libmail_encode_autodetect(use7bit, &read_file, &fi,
127 binaryflag);
128
129 if (fseek(fp, orig_pos, SEEK_SET) == (off_t)-1)
130 return NULL;
131 return rc;
132 }
133
134 const char *libmail_encode_autodetect_buf(const char *str, int use7bit)
135 {
136 return libmail_encode_autodetect(use7bit, &read_string, &str,
137 NULL);
138 }