Import Upstream version 0.66.4
[hcoop/debian/courier-authlib.git] / libs / rfc822 / encodeautodetect.c
CommitLineData
b0322a85
CE
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>
d50284c4 11#include <courier-unicode.h>
b0322a85
CE
12
13static 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
70struct file_info {
71 FILE *fp;
72 off_t pos;
73 off_t end;
74};
75
76static int read_file(void *arg)
77{
78int c;
79struct 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
87static int read_string(void * arg)
88{
89int c;
90unsigned char **strp = (unsigned char **)arg;
91 if (**strp == 0)
92 return EOF;
93 c = (int)**strp;
94 (*strp)++;
95 return c;
96}
97
98const 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
105const char *libmail_encode_autodetect_fpoff(FILE *fp, int use7bit,
106 off_t start_pos, off_t end_pos,
107 int *binaryflag)
108{
109struct file_info fi;
110off_t orig_pos = ftell(fp);
111off_t pos = orig_pos;
112const 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
134const char *libmail_encode_autodetect_buf(const char *str, int use7bit)
135{
136 return libmail_encode_autodetect(use7bit, &read_string, &str,
137 NULL);
138}