1 /*
2
3 gg_utf8.c -- locale charset handling
4
5 version 5.0, 2020 August 1
6
7 Author: Sandro Furieri a.furieri@lqt.it
8
9 ------------------------------------------------------------------------------
10
11 Version: MPL 1.1/GPL 2.0/LGPL 2.1
12
13 The contents of this file are subject to the Mozilla Public License Version
14 1.1 (the "License"); you may not use this file except in compliance with
15 the License. You may obtain a copy of the License at
16 http://www.mozilla.org/MPL/
17
18 Software distributed under the License is distributed on an "AS IS" basis,
19 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
20 for the specific language governing rights and limitations under the
21 License.
22
23 The Original Code is the SpatiaLite library
24
25 The Initial Developer of the Original Code is Alessandro Furieri
26
27 Portions created by the Initial Developer are Copyright (C) 2008-2021
28 the Initial Developer. All Rights Reserved.
29
30 Contributor(s):
31
32 Alternatively, the contents of this file may be used under the terms of
33 either the GNU General Public License Version 2 or later (the "GPL"), or
34 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
35 in which case the provisions of the GPL or the LGPL are applicable instead
36 of those above. If you wish to allow use of your version of this file only
37 under the terms of either the GPL or the LGPL, and not to allow others to
38 use your version of this file under the terms of the MPL, indicate your
39 decision by deleting the provisions above and replace them with the notice
40 and other provisions required by the GPL or the LGPL. If you do not delete
41 the provisions above, a recipient may use your version of this file under
42 the terms of any one of the MPL, the GPL or the LGPL.
43
44 */
45
46 #include <sys/types.h>
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <string.h>
50 #include <errno.h>
51
52 #if defined(_WIN32) && !defined(__MINGW32__)
53 #include "config-msvc.h"
54 #else
55 #include "config.h"
56 #endif
57
58 #include <spatialite/sqlite.h>
59 #include <spatialite/gaiaaux.h>
60 #include <spatialite_private.h>
61
62 #if OMIT_ICONV == 0 /* ICONV is absolutely required */
63
64 #if defined(__MINGW32__) || defined(_WIN32)
65 #define LIBICONV_STATIC
66 #include <iconv.h>
67 #define LIBCHARSET_STATIC
68 #ifdef _MSC_VER
69 /* <localcharset.h> isn't supported on OSGeo4W */
70 /* applying a tricky workaround to fix this issue */
71 extern const char *locale_charset (void);
72 #else /* sane Windows - not OSGeo4W */
73 #include <localcharset.h>
74 #endif /* end localcharset */
75 #else /* not MINGW32 - WIN32 */
76 #if defined(__APPLE__) || defined(__ANDROID__)
77 #include <iconv.h>
78 #include <localcharset.h>
79 #else /* neither Mac OsX nor Android */
80 #include <iconv.h>
81 #include <langinfo.h>
82 #endif
83 #endif
84
85 GAIAAUX_DECLARE const char *
gaiaGetLocaleCharset()86 gaiaGetLocaleCharset ()
87 {
88 /* identifies the locale charset */
89 #if defined(__MINGW32__) || defined(_WIN32)
90 return locale_charset ();
91 #else /* not MINGW32 - WIN32 */
92 #if defined(__APPLE__) || defined(__ANDROID__)
93 return locale_charset ();
94 #else /* neither Mac OsX nor Android */
95 return nl_langinfo (CODESET);
96 #endif
97 #endif
98 }
99
100 GAIAAUX_DECLARE int
gaiaConvertCharset(char ** buf,const char * fromCs,const char * toCs)101 gaiaConvertCharset (char **buf, const char *fromCs, const char *toCs)
102 {
103 /* converting a string from a charset to another "on-the-fly" */
104 char *utf8buf;
105 #if !defined(__MINGW32__) && defined(_WIN32)
106 const char *pBuf;
107 #else /* not WIN32 */
108 char *pBuf;
109 #endif
110 size_t len;
111 size_t utf8len;
112 char *pUtf8buf;
113 int maxlen;
114 iconv_t cvt = iconv_open (toCs, fromCs);
115 if (cvt == (iconv_t) (-1))
116 goto unsupported;
117 len = strlen (*buf);
118 if (len == 0)
119 {
120 /* empty string */
121 utf8buf = sqlite3_malloc (1);
122 *utf8buf = '\0';
123 sqlite3_free (*buf);
124 *buf = utf8buf;
125 iconv_close (cvt);
126 return 1;
127 }
128 maxlen = len * 4;
129 utf8len = maxlen;
130 pBuf = *buf;
131 utf8buf = sqlite3_malloc (utf8len);
132 pUtf8buf = utf8buf;
133 if (iconv (cvt, &pBuf, &len, &pUtf8buf, &utf8len) == (size_t) (-1))
134 goto error;
135 utf8buf[maxlen - utf8len] = '\0';
136 sqlite3_free (*buf);
137 *buf = utf8buf;
138 iconv_close (cvt);
139 return 1;
140 error:
141 iconv_close (cvt);
142 sqlite3_free (*buf);
143 *buf = NULL;
144 unsupported:
145 return 0;
146 }
147
148 GAIAAUX_DECLARE void *
gaiaCreateUTF8Converter(const char * fromCS)149 gaiaCreateUTF8Converter (const char *fromCS)
150 {
151 /* creating a UTF8 converter and returning an opaque reference to it */
152 iconv_t cvt = iconv_open ("UTF-8", fromCS);
153 if (cvt == (iconv_t) (-1))
154 return NULL;
155 return cvt;
156 }
157
158 GAIAAUX_DECLARE void
gaiaFreeUTF8Converter(void * cvtCS)159 gaiaFreeUTF8Converter (void *cvtCS)
160 {
161 /* destroying a UTF8 converter */
162 if (cvtCS)
163 iconv_close (cvtCS);
164 }
165
166 GAIAAUX_DECLARE char *
gaiaConvertToUTF8(void * cvtCS,const char * buf,int buflen,int * err)167 gaiaConvertToUTF8 (void *cvtCS, const char *buf, int buflen, int *err)
168 {
169 /* converting a string to UTF8 */
170 char *utf8buf = 0;
171 #if !defined(__MINGW32__) && defined(_WIN32)
172 const char *pBuf;
173 #else
174 char *pBuf;
175 #endif
176 size_t len;
177 size_t utf8len;
178 int maxlen = buflen * 4;
179 char *pUtf8buf;
180 *err = 0;
181 if (!cvtCS)
182 {
183 *err = 1;
184 return NULL;
185 }
186 utf8buf = malloc (maxlen);
187 len = buflen;
188 utf8len = maxlen;
189 pBuf = (char *) buf;
190 pUtf8buf = utf8buf;
191 if (iconv (cvtCS, &pBuf, &len, &pUtf8buf, &utf8len) == (size_t) (-1))
192 {
193 free (utf8buf);
194 *err = 1;
195 return NULL;
196 }
197 utf8buf[maxlen - utf8len] = '\0';
198 return utf8buf;
199 }
200
201 SPATIALITE_PRIVATE char *
url_toUtf8(const char * url,const char * in_charset)202 url_toUtf8 (const char *url, const char *in_charset)
203 {
204 /* converting an URL to UTF-8 */
205 iconv_t cvt;
206 size_t len;
207 size_t utf8len;
208 int maxlen;
209 char *utf8buf;
210 char *pUtf8buf;
211 #if !defined(__MINGW32__) && defined(_WIN32)
212 const char *pBuf = url;
213 #else /* not WIN32 */
214 char *pBuf = (char *) url;
215 #endif
216
217 if (url == NULL || in_charset == NULL)
218 return NULL;
219 cvt = iconv_open ("UTF-8", in_charset);
220 if (cvt == (iconv_t) (-1))
221 goto unsupported;
222 len = strlen (url);
223 maxlen = len * 4;
224 utf8len = maxlen;
225 utf8buf = malloc (maxlen);
226 pUtf8buf = utf8buf;
227 if (iconv (cvt, &pBuf, &len, &pUtf8buf, &utf8len) == (size_t) (-1))
228 goto error;
229 utf8buf[maxlen - utf8len] = '\0';
230 iconv_close (cvt);
231 return utf8buf;
232
233 error:
234 iconv_close (cvt);
235 free (utf8buf);
236 unsupported:
237 return NULL;
238 }
239
240 SPATIALITE_PRIVATE char *
url_fromUtf8(const char * url,const char * out_charset)241 url_fromUtf8 (const char *url, const char *out_charset)
242 {
243 /* converting an URL from UTF-8 */
244 iconv_t cvt;
245 size_t len;
246 size_t utf8len;
247 int maxlen;
248 char *utf8buf;
249 char *pUtf8buf;
250 #if !defined(__MINGW32__) && defined(_WIN32)
251 const char *pBuf = url;
252 #else /* not WIN32 */
253 char *pBuf = (char *) url;
254 #endif
255
256 if (url == NULL || out_charset == NULL)
257 return NULL;
258 cvt = iconv_open (out_charset, "UTF-8");
259 if (cvt == (iconv_t) (-1))
260 goto unsupported;
261 len = strlen (url);
262 maxlen = len * 4;
263 utf8len = maxlen;
264 utf8buf = malloc (maxlen);
265 pUtf8buf = utf8buf;
266 if (iconv (cvt, &pBuf, &len, &pUtf8buf, &utf8len) == (size_t) (-1))
267 goto error;
268 utf8buf[maxlen - utf8len] = '\0';
269 iconv_close (cvt);
270 return utf8buf;
271
272 error:
273 iconv_close (cvt);
274 free (utf8buf);
275 unsupported:
276 return NULL;
277 }
278
279 #else
280 GAIAAUX_DECLARE char *
gaiaConvertToUTF8(void * cvtCS,const char * buf,int buflen,int * err)281 gaiaConvertToUTF8 (void *cvtCS, const char *buf, int buflen, int *err)
282 {
283 if (cvtCS == NULL || buf == NULL || err == NULL || buflen == 0)
284 return NULL;
285 return NULL;
286 }
287 #endif /* ICONV enabled/disabled */
288