1 /*----------------------------------------------------------------------
2 * Module name: my_iconv
3 * Author name: Arkadiusz Firus
4 * Create date: 07 Sep 08
5 * Purpose: iconv handles
6 *----------------------------------------------------------------------
7 Changes:
8 * 04 Jan 10, daved@physiol.usyd.edu.au: use path specfied with -P to
9 * load charmap file(s)
10 * 07 Oct 11, jf@dockes.org, major changes to unicode translations
11 *--------------------------------------------------------------------*/
12
13 #include <stdio.h>
14 #include <string.h>
15 #ifndef _WIN32
16 #include <unistd.h>
17 #endif
18 #include <stdlib.h>
19 #include <errno.h>
20
21 #include "malloc.h"
22 #include "my_iconv.h"
23 #include "util.h"
24 #include "unicode.h"
25 #include "path.h"
26
27 extern int verbose_mode;
28
29 /* Convert from charmap file entry to charmap table one.
30 1st byte in table entry is code length
31 */
32 static char *
get_code_str(FILE * f,iconv_t desc)33 get_code_str(FILE *f, iconv_t desc)
34 {
35 char *icp, *ocp0, *ocp;
36 size_t ibytes, obytes;
37 char *obuf;
38
39 char *utf8 = get_unicode_utf8(f);
40 if (utf8 == NULL || *utf8 == 0)
41 {
42 /* fprintf(stderr, "get_code_str: NULL entry\n");*/
43 my_free(utf8);
44 return NULL;
45 }
46 #if 0 /* debug */
47 fprintf(stderr, "get_code_str: utf8: ");
48 for (ocp = utf8; *ocp; ocp++)
49 {
50 fprintf(stderr, "%x", (unsigned)*ocp);
51 }
52 fprintf(stderr, "\n");
53 #endif
54
55 obytes = 10;
56 ibytes = strlen(utf8);
57 obuf = malloc(obytes);
58 if (obuf == NULL)
59 {
60 my_free(utf8);
61 return NULL;
62 }
63 icp = utf8;
64 ocp0 = ocp = obuf + 1;
65 if (iconv(desc, &icp, &ibytes, &ocp, &obytes) == -1)
66 {
67 /* fprintf(stderr, "unrtf: my_iconv: iconv error\n");*/
68 my_free(utf8);
69 return NULL;
70 }
71
72 // Set 1st byte to length
73 obuf[0] = ocp - ocp0;
74 my_free(utf8);
75 return obuf;
76 }
77
78 my_iconv_t
my_iconv_open(const char * tocode,const char * fromcode)79 my_iconv_open(const char *tocode, const char *fromcode)
80 {
81 FILE *f;
82 my_iconv_t cd = MY_ICONV_T_CLEAR;
83 int c, i;
84 /* fprintf(stderr, "my_iconv_open: from %s to %s\n", fromcode, tocode);*/
85 if ((cd.desc = iconv_open(tocode, fromcode)) == (iconv_t) - 1)
86 {
87 char *path = search_in_path(fromcode, "charmap");
88 if (path == NULL)
89 {
90 return cd;
91 }
92 if ((f = fopen(path, "r")) == NULL && verbose_mode)
93 {
94 fprintf(stderr, "failed to open charmap file %s\n", path);
95 }
96
97 if (f != NULL)
98 {
99 /* Open iconv utf8->tocode conversion */
100 iconv_t desc;
101 if ((desc = iconv_open(tocode, "UTF-8")) == (iconv_t) - 1)
102 {
103 fclose(f);
104 return cd;
105 }
106 cd.char_table = (char **)my_malloc(char_table_size *
107 sizeof(char *));
108 c = fgetc(f);
109
110 for (i = 0; i < char_table_size && c != EOF; i++)
111 {
112 if (c == '<')
113 {
114 cd.char_table[i] = get_code_str(f, desc);
115 }
116 leave_line(f);//read up to including \n or eof
117 c = fgetc(f);
118 }
119 iconv_close(desc);
120 fclose(f);
121 }
122
123 my_free(path);
124 }
125
126 return cd;
127 }
128
129 size_t
my_iconv(my_iconv_t cd,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)130 my_iconv(my_iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
131 {
132 int c, i;
133 size_t result = 0;
134 **outbuf = 0;
135 if (cd.desc == (iconv_t) - 1)
136 {
137 if (cd.char_table != NULL)
138 {
139 while (*inbytesleft > 0 && *outbytesleft > 0)
140 {
141 c = **(unsigned char **)inbuf;
142 if (cd.char_table[c] != NULL)
143 {
144 for (i = 0; i < cd.char_table[c][0] && *outbytesleft > 0; i++)
145 {
146 **outbuf = cd.char_table[c][i + 1];
147 (*outbytesleft)--;
148 (*outbuf)++;
149 }
150 }
151 else
152 {
153 /* fprintf(stderr, "my_iconv: no conversion for 0x%x\n",
154 (unsigned)c);*/
155 errno = EILSEQ;
156 return (size_t) - 1;
157 }
158
159 (*inbuf)++;
160 (*inbytesleft)--;
161 result++;
162 }
163
164 if (*outbytesleft == 0 && *inbytesleft > 0)
165 {
166 errno = E2BIG;
167 result = (size_t) - 1;
168 }
169 }
170 }
171 else
172 {
173 result = iconv(cd.desc, inbuf, inbytesleft, outbuf, outbytesleft);
174 }
175
176 return result;
177 }
178
179 my_iconv_t
my_iconv_close(my_iconv_t cd)180 my_iconv_close(my_iconv_t cd)
181 {
182 int i;
183
184 if (cd.char_table != NULL)
185 {
186 for (i = 0; i < char_table_size; i++)
187 {
188 if (cd.char_table[i] != NULL)
189 {
190 my_free(cd.char_table[i]);
191 }
192 }
193
194 my_free((void *)cd.char_table);
195 cd.char_table = NULL;
196 }
197
198 if (cd.desc != (iconv_t) - 1)
199 {
200 iconv_close(cd.desc);
201 cd.desc = (iconv_t) - 1;
202 }
203
204 return cd;
205 }
206
207 int
my_iconv_is_valid(my_iconv_t cd)208 my_iconv_is_valid(my_iconv_t cd)
209 {
210 if (cd.desc != (iconv_t) - 1 || cd.char_table != NULL)
211 {
212 return 1;
213 }
214
215 return 0;
216 }
217
218 void
my_iconv_t_make_invalid(my_iconv_t * cd)219 my_iconv_t_make_invalid(my_iconv_t *cd)
220 {
221 cd->desc = (iconv_t) - 1;
222 cd->char_table = NULL;
223 }
224
225