Imported Upstream version 0.63.0
[hcoop/debian/courier-authlib.git] / rfc822 / encodeautodetect.c
CommitLineData
d9898ee8 1/*
8d138742 2** Copyright 2003-2009 Double Precision, Inc. See COPYING for
d9898ee8 3** distribution information.
4*/
5
6/*
8d138742 7** $Id: encodeautodetect.c,v 1.2 2009/11/08 18:14:47 mrsam Exp $
d9898ee8 8*/
9#include "encode.h"
10#include <string.h>
11#include <stdlib.h>
d9898ee8 12#include "../unicode/unicode.h"
d9898ee8 13
14static 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;
d9898ee8 21 const struct unicode_info *ci = unicode_find(charset);
d9898ee8 22
23 while ((c = (*func)(arg)) != EOF)
24 {
25 unsigned char ch= (unsigned char)c;
26
27 if (ch >= 0x80)
28 {
29
d9898ee8 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";
d9898ee8 38 }
39
40 if (ch < 0x20 &&
41 ch != '\t' && ch != '\r' && ch != '\n')
42 {
d9898ee8 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";
d9898ee8 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;
d9898ee8 58 if (ci && ci->flags & UNICODE_BODY_QUOPRI)
59 encoding="quoted-printable";
d9898ee8 60 }
61
62 }
63
64 if (longline)
65 {
d9898ee8 66 if (ci && ci->flags & UNICODE_BODY_QUOPRI)
67 encoding="quoted-printable";
68 else
69 encoding="base64";
d9898ee8 70 }
71 return encoding;
72}
73
74struct file_info {
75 FILE *fp;
76 off_t pos;
77 off_t end;
78};
79
80static int read_file(void *arg)
81{
82int c;
83struct 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
91static int read_string(void * arg)
92{
93int c;
94unsigned char **strp = (unsigned char **)arg;
95 if (**strp == 0)
96 return EOF;
97 c = (int)**strp;
98 (*strp)++;
99 return c;
100}
101
102const 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
110const char *libmail_encode_autodetect_fppos(FILE *fp, const char *charset,
111 off_t start_pos, off_t end_pos)
112{
113struct file_info fi;
114off_t orig_pos = ftell(fp);
115off_t pos = orig_pos;
116const 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
136const char *libmail_encode_autodetect_str(const char *str, const char *charset)
137{
138 return libmail_encode_autodetect(charset, &read_string, &str);
139}