OSDN Git Service

a3ce8119418e856d986689a71f42a37630acfe29
[modchxj/mod_chxj.git] / src / chxj_encoding.c
1 /*
2  * Copyright (C) 2005-2008 Atsushi Konno All rights reserved.
3  * Copyright (C) 2005 QSDN,Inc. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 #include "mod_chxj.h"
18 #include "chxj_encoding.h"
19 #include "chxj_apply_convrule.h"
20 #include "chxj_url_encode.h"
21 #include <errno.h>
22 #include <iconv.h>
23
24
25 char *
26 chxj_encoding(request_rec *r, const char *src, apr_size_t *len)
27 {
28   char                *obuf;
29   char                *ibuf;
30   char                *spos;
31   
32   iconv_t             cd;
33   size_t              result;
34   apr_size_t          ilen;
35   apr_size_t          olen;
36   mod_chxj_config     *dconf;
37   chxjconvrule_entry  *entryp;
38   apr_pool_t          *pool;
39
40
41   DBG(r,"start chxj_encoding()");
42
43   dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
44
45   if (dconf == NULL) {
46     DBG(r,"none encoding.");
47     return (char*)src;
48   }
49   if ((int)*len < 0) {
50     ERR(r, "runtime exception: chxj_encoding(): invalid string size.[%d]", (int)*len);
51     return (char *)apr_pstrdup(r->pool, "");
52   }
53
54   entryp = chxj_apply_convrule(r, dconf->convrules);
55   if (entryp->encoding == NULL) {
56     DBG(r,"none encoding.");
57     return (char *)src;
58   }
59
60   if (STRCASEEQ('n','N',"none", entryp->encoding)) {
61     DBG(r,"none encoding.");
62     return (char*)src;
63   }
64
65   apr_pool_create(&pool, r->pool);
66   ilen = *len;
67   ibuf = apr_palloc(pool, ilen+1);
68   if (ibuf == NULL) {
69     ERR(r, "runtime exception: chxj_encoding(): Out of memory.");
70     return (char *)src;
71   }
72   memset(ibuf, 0, ilen+1);
73   memcpy(ibuf, src, ilen);
74
75   olen = ilen * 4 + 1;
76   spos = obuf = apr_palloc(pool, olen);
77   if (obuf == NULL) {
78     DBG(r,"end   chxj_encoding()");
79     return ibuf;
80   }
81   DBG(r,"encode convert [%s] -> [%s]", entryp->encoding, "CP932");
82
83   memset(obuf, 0, olen);
84   cd = iconv_open("CP932", entryp->encoding);
85   if (cd == (iconv_t)-1) {
86     if (EINVAL == errno) {
87       ERR(r, "The conversion from %s to %s is not supported by the implementation.", entryp->encoding, "CP932");
88     }
89     else {
90       ERR(r, "iconv open failed. from:[%s] to:[%s] errno:[%d]", entryp->encoding, "CP932", errno);
91     }
92     DBG(r,"end   chxj_encoding()");
93     return ibuf;
94   }
95   while (ilen > 0) {
96     result = iconv(cd, &ibuf, &ilen, &obuf, &olen);
97     if (result == (size_t)(-1)) {
98       if (E2BIG == errno) {
99         ERR(r, "There is not sufficient room at *outbuf.");
100       }
101       else if (EILSEQ == errno) {
102         ERR(r, "An invalid multibyte sequence has been encountered in the input. input:[%s]", ibuf);
103       }
104       else if (EINVAL == errno) {
105         ERR(r, "An incomplete multibyte sequence has been encountered in the input. input:[%s]", ibuf);
106       }
107       break;
108     }
109   }
110   *len = strlen(spos);
111   iconv_close(cd);
112
113   DBG(r,"end   chxj_encoding() len=[%d] obuf=[%.*s]", (int)*len, (int)*len, spos);
114   return spos;
115 }
116
117
118 char *
119 chxj_rencoding(request_rec *r, const char *src, apr_size_t *len)
120 {
121   char                *obuf;
122   char                *ibuf;
123   char                *spos;
124   
125   iconv_t             cd;
126   size_t              result;
127   apr_size_t          ilen;
128   apr_size_t          olen;
129   mod_chxj_config     *dconf;
130   chxjconvrule_entry  *entryp;
131
132   DBG(r,"start chxj_rencoding()");
133
134   if ((int)*len < 0) {
135     ERR(r, "runtime exception: chxj_rencoding(): invalid string size.[%d]", (int)*len);
136     return (char *)apr_pstrdup(r->pool, "");
137   }
138
139   dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
140   if (! dconf) {
141     DBG(r,"none encoding.");
142     DBG(r,"end   chxj_rencoding()");
143     return (char*)src;
144   }
145
146   entryp = chxj_apply_convrule(r, dconf->convrules);
147   if (! entryp->encoding) {
148     DBG(r,"none encoding.");
149     DBG(r,"end   chxj_rencoding()");
150     return (char*)src;
151   }
152
153   if (STRCASEEQ('n','N',"none", entryp->encoding)) {
154     DBG(r,"none encoding.");
155     DBG(r,"end   chxj_rencoding()");
156     return (char*)src;
157   }
158
159   ilen = *len;
160   ibuf = apr_palloc(r->pool, ilen+1);
161   if (! ibuf) {
162     DBG(r,"end   chxj_rencoding()");
163     return (char*)src;
164   }
165
166   memset(ibuf, 0,   ilen+1);
167   memcpy(ibuf, src, ilen+0);
168
169   olen = ilen * 4 + 1;
170   spos = obuf = apr_palloc(r->pool, olen);
171   if (! obuf) {
172     DBG(r,"end   chxj_rencoding()");
173     return ibuf;
174   }
175   DBG(r,"encode convert [%s] -> [%s]", "CP932", entryp->encoding);
176
177   memset(obuf, 0, olen);
178
179   cd = iconv_open(entryp->encoding, "CP932");
180   if (cd == (iconv_t)-1) {
181     if (EINVAL == errno) {
182       ERR(r, "The conversion from %s to %s is not supported by the implementation.", "CP932", entryp->encoding);
183     }
184     DBG(r,"end   chxj_rencoding()");
185     return ibuf;
186   }
187
188   while (ilen > 0) {
189     result = iconv(cd, &ibuf, &ilen, &obuf, &olen);
190     if (result == (size_t)(-1)) {
191       if (E2BIG == errno) {
192         ERR(r, "There is not sufficient room at *outbuf");
193       }
194       else if (EILSEQ == errno) {
195         ERR(r, "An invalid multibyte sequence has been encountered in the input. input:[%s]", ibuf);
196       }
197       else if (EINVAL == errno) {
198         ERR(r, "An incomplete multibyte sequence has been encountered in the input. input:[%s]", ibuf);
199       }
200       break;
201     }
202   }
203
204   *len = strlen(spos);
205   iconv_close(cd);
206
207   DBG(r,"end   chxj_rencoding() len=[%d] obuf=[%.*s]", (int)*len, (int)*len, spos);
208
209   return spos;
210 }
211
212
213 char *
214 chxj_encoding_parameter(request_rec *r, const char *value)
215 {
216   char *src;
217   char *src_sv;
218   char *pstat;
219   char *spos;
220   char *pair;
221   char *key;
222   char *val;
223   char *vstat;
224   char *param;
225
226   int   use_amp_flag;
227   
228   DBG(r, "start chxj_encoding_parameter()");
229
230   src = apr_pstrdup(r->pool, value);
231
232   spos = strchr(src, '?');
233   if (!spos) {
234     DBG(r, "end   chxj_encoding_parameter()");
235     return src;
236   }
237   *spos++ = 0;
238
239   src_sv = apr_pstrdup(r->pool, src);
240   param  = apr_palloc(r->pool, 1);
241   param[0] = 0;
242
243   for (;;) {
244     apr_size_t len;
245     char *sep_pos;
246
247     use_amp_flag = 0;
248
249     pair = apr_strtok(spos, "&", &pstat);
250     spos = NULL;
251     if (!pair) break;
252     if (strncasecmp(pair, "amp;", 4) == 0) {
253       pair += 4;
254       use_amp_flag = 1;
255     }
256     sep_pos = strchr(pair, '=');
257     if (pair == sep_pos) {
258       key = apr_pstrdup(r->pool, "");
259     }
260     else {
261       key = apr_strtok(pair, "=", &vstat);
262       pair = NULL;
263     }
264     if (key) {
265       key = chxj_url_decode(r->pool, key);
266       len = (apr_size_t)strlen(key);
267       key = chxj_encoding(r, key, &len);
268       key = chxj_url_encode(r->pool, key);
269     }
270     val = apr_strtok(pair, "=", &vstat);
271     if (! val && sep_pos) {
272       val = apr_pstrdup(r->pool, "");
273     }
274     if (val) {
275       val = chxj_url_decode(r->pool, val);
276       len = (apr_size_t)strlen(val);
277       val = chxj_encoding(r, val, &len);
278       val = chxj_url_encode(r->pool, val);
279       if (strlen(param) == 0) {
280         param = apr_pstrcat(r->pool, param, key, "=", val, NULL);
281       }
282       else {
283         if (use_amp_flag) {
284           param = apr_pstrcat(r->pool, param, "&amp;", key, "=", val, NULL);
285         }
286         else {
287           param = apr_pstrcat(r->pool, param, "&", key, "=", val, NULL);
288         }
289       }
290     }
291     else {
292       if (strlen(param) == 0) {
293         param = apr_pstrcat(r->pool, param, key,  NULL);
294       }
295       else {
296         if (use_amp_flag) {
297           param = apr_pstrcat(r->pool, param, "&amp;", key, NULL);
298         }
299         else {
300           param = apr_pstrcat(r->pool, param, "&", key, NULL);
301         }
302       }
303     }
304   }
305   DBG(r, "end   chxj_encoding_parameter()");
306
307   return apr_pstrcat(r->pool, src_sv, "?", param, NULL);
308 }
309
310
311 char *
312 chxj_iconv(request_rec *r, apr_pool_t *pool, const char *src, apr_size_t *len, const char *from, const char *to)
313 {
314   char                *obuf;
315   char                *ibuf;
316   char                *spos;
317   
318   iconv_t             cd;
319   size_t              result;
320   apr_size_t          ilen;
321   apr_size_t          olen;
322
323
324   if ((int)*len < 0) {
325     ERR(r, "runtime exception: chxj_iconv(): invalid string size.[%d]", (int)*len);
326     return (char *)apr_pstrdup(pool, "");
327   }
328
329   ilen = *len;
330   ibuf = apr_palloc(pool, ilen+1);
331   if (ibuf == NULL) {
332     ERR(r, "runtime exception: chxj_iconv(): Out of memory.");
333     return (char *)src;
334   }
335   memset(ibuf, 0, ilen+1);
336   memcpy(ibuf, src, ilen);
337
338   olen = ilen * 4 + 1;
339   spos = obuf = apr_palloc(pool, olen);
340   if (obuf == NULL) {
341     ERR(r, "%s:%d runtime exception: chxj_iconv(): Out of memory", APLOG_MARK);
342     return ibuf;
343   }
344   memset(obuf, 0, olen);
345   cd = iconv_open(to, from);
346   if (cd == (iconv_t)-1) {
347     if (EINVAL == errno) {
348       ERR(r, "The conversion from %s to %s is not supported by the implementation.", from, to);
349     }
350     else {
351       ERR(r, "iconv open failed. from:[%s] to:[%s] errno:[%d]", from, to, errno);
352     }
353     return ibuf;
354   }
355   while (ilen > 0) {
356     result = iconv(cd, &ibuf, &ilen, &obuf, &olen);
357     if (result == (size_t)(-1)) {
358       if (E2BIG == errno) {
359         ERR(r, "There is not sufficient room at *outbuf.");
360       }
361       else if (EILSEQ == errno) {
362         ERR(r, "An invalid multibyte sequence has been encountered in the input. input:[%s]", ibuf);
363       }
364       else if (EINVAL == errno) {
365         ERR(r, "An incomplete multibyte sequence has been encountered in the input. input:[%s]", ibuf);
366       }
367       break;
368     }
369   }
370   *len = strlen(spos);
371   iconv_close(cd);
372
373   return spos;
374 }
375 /*
376  * vim:ts=2 et
377  */