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