d9898ee8 |
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 |