1 /** 2 *** Transcoding support and wrappers. 3 *** 4 *** See Copyright for the status of this software. 5 *** 6 *** Author: Patrick Monnerat <pm (at) datasphere.ch>, DATASPHERE S.A. 7 **/ 8 9 #define IN_LIBXML 10 #include "libxml.h" 11 12 #include <sys/types.h> 13 #include <iconv.h> 14 #include "libxml/xmlmemory.h" 15 #include "libxml/dict.h" 16 #include "transcode.h" 17 18 19 /** 20 *** Destroy a dictionary and mark as destroyed. 21 **/ 22 23 void 24 xmlZapDict(xmlDictPtr * dict) 25 26 { 27 if (dict && *dict) { 28 xmlDictFree(*dict); 29 *dict = (xmlDictPtr) NULL; 30 } 31 } 32 33 34 /** 35 *** Support for inline conversion from/to UTF-8. 36 *** This is targetted to function parameter encoding conversion. 37 *** Method is: 38 *** - Convert string from/to UTF-8. 39 *** - Keep it in a dictionary. 40 *** - Free original string if a release procedure is provided. 41 *** Can also be called without dictionary to convert a string from/to UTF-8 42 *** into xmlMalloc'ed dynamic storage. 43 **/ 44 45 const char * 46 xmlTranscodeResult(const xmlChar * s, const char * encoding, 47 xmlDictPtr * dict, void (*freeproc)(const void *)) 48 49 { 50 size_t l; 51 iconv_t cd; 52 char * srcp; 53 char * dstp; 54 size_t srcc; 55 size_t dstc; 56 char * ts; 57 const char * ret; 58 int err; 59 static const int nullstring[] = { 0 }; 60 61 /* Convert from UTF-8. */ 62 63 if (!s) 64 return (const char *) NULL; 65 66 ret = (const char *) NULL; 67 ts = (char *) NULL; 68 err = 0; 69 l = xmlStrlen(s); 70 71 if (!l && dict) 72 ret = (const char *) nullstring; 73 else { 74 if (dict && !*dict) 75 err = !(*dict = xmlDictCreate()); 76 77 if (!err) 78 err = !(ts = xmlMalloc(4 * l + 4)); 79 80 dstp = ts; 81 dstc = 4 * l; 82 83 if (!err && l) { 84 if (!encoding) 85 encoding = "ibm-0"; /* Job's encoding. */ 86 87 cd = iconv_open(encoding, "UTF-8"); 88 89 if (cd == (iconv_t) -1) 90 err = 1; 91 else { 92 srcp = (char *) s; 93 srcc = l; 94 srcc = iconv(cd, &srcp, &srcc, &dstp, &dstc); 95 iconv_close(cd); 96 err = srcc == (size_t) -1; 97 } 98 } 99 100 if (!err) { 101 dstp[0] = dstp[1] = dstp[2] = dstp[3] = '\0'; 102 103 if (!dict) { 104 if (dstc) 105 ts = xmlRealloc(ts, (dstp - ts) + 4); 106 107 ret = (const char *) ts; 108 ts = (char *) NULL; 109 } 110 else 111 ret = (char *) xmlDictLookup(*dict, 112 (xmlChar *) ts, dstp - ts + 1); 113 } 114 } 115 116 if (ts) 117 xmlFree(ts); 118 119 if (freeproc) 120 (*freeproc)(s); 121 122 return ret; 123 } 124 125 126 /** 127 *** Support for inline conversion to UTF-8. 128 *** Method is: 129 *** - Convert string to UTF-8. 130 *** - Keep it in a dictionary. 131 *** Can also be called without dictionary to convert a string to UTF-8 into 132 *** xmlMalloc'ed dynamic storage. 133 **/ 134 135 static const xmlChar * 136 inTranscode(const char * s, size_t l, const char * encoding, xmlDictPtr * dict) 137 138 { 139 iconv_t cd; 140 char * srcp; 141 char * dstp; 142 size_t srcc; 143 size_t dstc; 144 xmlChar * ts; 145 const xmlChar * ret; 146 static const xmlChar nullstring[] = { 0 }; 147 148 if (!l && dict) 149 return nullstring; 150 151 if (dict && !*dict) 152 if (!(*dict = xmlDictCreate())) 153 return (const xmlChar *) NULL; 154 155 ts = (xmlChar *) xmlMalloc(6 * l + 1); 156 157 if (!ts) 158 return (const xmlChar *) NULL; 159 160 dstp = (char *) ts; 161 dstc = 6 * l; 162 163 if (l) { 164 if (!encoding) 165 encoding = "ibm-0"; /* Use job's encoding. */ 166 167 cd = iconv_open("UTF-8", encoding); 168 169 if (cd == (iconv_t) -1) { 170 xmlFree((char *) ts); 171 return (const xmlChar *) NULL; 172 } 173 174 srcp = (char *) s; 175 srcc = l; 176 srcc = iconv(cd, &srcp, &srcc, &dstp, &dstc); 177 iconv_close(cd); 178 179 if (srcc == (size_t) -1) { 180 xmlFree((char *) ts); 181 return (const xmlChar *) NULL; 182 } 183 } 184 185 *dstp = '\0'; 186 187 if (!dict) { 188 if (dstc) 189 ts = xmlRealloc(ts, (dstp - ts) + 1); 190 191 return ts; 192 } 193 194 ret = xmlDictLookup(*dict, ts, dstp - ts + 1); 195 xmlFree((char *) ts); 196 return ret; 197 } 198 199 200 /** 201 *** Input 8-bit character string parameter. 202 **/ 203 204 const xmlChar * 205 xmlTranscodeString(const char * s, const char * encoding, xmlDictPtr * dict) 206 207 { 208 if (!s) 209 return (const xmlChar *) NULL; 210 211 return inTranscode(s, xmlStrlen(s), encoding, dict); 212 } 213 214 215 /** 216 *** Input 16-bit character string parameter. 217 **/ 218 219 const xmlChar * 220 xmlTranscodeWString(const char * s, const char * encoding, xmlDictPtr * dict) 221 222 { 223 size_t i; 224 225 if (!s) 226 return (const xmlChar *) NULL; 227 228 for (i = 0; s[i] && s[i + 1]; i += 2) 229 ; 230 231 return inTranscode(s, i, encoding, dict); 232 } 233 234 235 /** 236 *** Input 32-bit character string parameter. 237 **/ 238 239 const xmlChar * 240 xmlTranscodeHString(const char * s, const char * encoding, xmlDictPtr * dict) 241 242 { 243 size_t i; 244 245 if (!s) 246 return (const xmlChar *) NULL; 247 248 for (i = 0; s[i] && s[i + 1] && s[i + 2] && s[i + 3]; i += 4) 249 ; 250 251 return inTranscode(s, i, encoding, dict); 252 } 253 254 255 /** 256 *** vasprintf() implementation with result transcoding. 257 **/ 258 259 const char * 260 xmlVasprintf(xmlDictPtr * dict, const char * encoding, 261 const xmlChar * fmt, va_list args) 262 263 { 264 char * s = NULL; 265 266 vasprintf(&s, fmt, args); 267 return xmlTranscodeResult((const xmlChar *) s, encoding, dict, free); 268 } 269