Imported upstream version 0.59.3
[hcoop/debian/courier-authlib.git] / rfc822 / rfc2047u.c
1 /*
2 ** Copyright 1998 - 2000 Double Precision, Inc. See COPYING for
3 ** distribution information.
4 */
5
6
7 #include <stdio.h>
8 #include <ctype.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <errno.h>
12
13 #include "rfc822.h"
14 #include "rfc2047.h"
15
16 static const char rcsid[]="$Id: rfc2047u.c,v 1.5 2004/05/23 14:28:24 mrsam Exp $";
17
18 #if HAVE_LIBUNICODE
19
20 #include "../unicode/unicode.h"
21
22 struct decode_unicode_s {
23 const struct unicode_info *mychset;
24 int options;
25
26 char *bufptr;
27 size_t bufsize;
28 } ;
29
30 static void save_unicode_text(const char *p, int l, struct decode_unicode_s *s)
31 {
32 if (s->bufptr)
33 memcpy(s->bufptr+s->bufsize, p, l);
34
35 s->bufsize += l;
36 }
37
38 static int save_unicode(const char *txt, int len, const char *chset,
39 const char *lang,
40 void *arg)
41 {
42 struct decode_unicode_s *p=(struct decode_unicode_s *)arg;
43 char *txts=malloc(len+1);
44 char *s;
45 int i;
46
47 if (!txts)
48 return (-1);
49 memcpy(txts, txt, len);
50 txts[len]=0;
51
52 if (!chset)
53 chset=unicode_ISO8859_1.chset;
54
55 s=unicode_convert_fromchset(txts, chset, p->mychset);
56 if (!s && p->options & RFC2047_DECODE_REPLACE)
57 {
58 const struct unicode_info *uiptr=unicode_find(chset);
59 if (uiptr)
60 s=unicode_xconvert(txts, uiptr, p->mychset);
61 }
62 free(txts);
63 if (s)
64 {
65 save_unicode_text(s, strlen(s), p);
66 free(s);
67 return (0);
68 }
69
70 if (p->options & RFC2047_DECODE_ABORT)
71 {
72 errno=EINVAL;
73 return (-1);
74 }
75
76 if (p->options & RFC2047_DECODE_DISCARD)
77 return (0);
78
79 if (!(p->options & RFC2047_DECODE_NOTAG))
80 {
81 save_unicode_text(" [", 2, p);
82 save_unicode_text(chset, strlen(chset), p);
83 save_unicode_text("] ", 2, p);
84 if (!(p->options & RFC2047_DECODE_REPLACE))
85 {
86 save_unicode_text(txt, len, p);
87 return (0);
88 }
89 }
90
91 if (p->options & RFC2047_DECODE_REPLACE)
92 for (i=0; i < strlen(txt); i++)
93 save_unicode_text("?", 1, p);
94
95 return (0);
96 }
97
98 char *rfc2047_decode_unicode(const char *text,
99 const struct unicode_info *mychset,
100 int options)
101 {
102 struct decode_unicode_s s;
103 char *p=0;
104
105 s.mychset=mychset;
106 s.options=0;
107
108 s.bufptr=0;
109 s.bufsize=1;
110
111
112 if (rfc2047_decode(text, &save_unicode, &s))
113 return (0);
114
115 s.bufptr=p=malloc(s.bufsize);
116 if (!s.bufptr)
117 return (0);
118
119 s.bufsize=0;
120 if (rfc2047_decode(text, &save_unicode, &s))
121 {
122 free(p);
123 return (0);
124 }
125 save_unicode_text("", 1, (void *)&s);
126 return (p);
127 }
128
129
130 static char *do_rfc2047_decode_enhanced(const char *text, const char *mychset)
131 {
132 const struct unicode_info *u=unicode_find(mychset);
133
134 if (!u) u=&unicode_ISO8859_1;
135
136 return rfc2047_decode_unicode(text, u, 0);
137 }
138
139 void rfc2047_print_unicode(const struct rfc822a *a,
140 const char *charset,
141 void (*print_func)(char, void *),
142 void (*print_separator)(const char *, void *),
143 void *ptr)
144 {
145 rfc822_print_common(a, &do_rfc2047_decode_enhanced, charset,
146 print_func, print_separator, ptr);
147 }
148
149
150 #endif