OSDN Git Service

* Added features.
[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   apr_pool_create(&pool, r->pool);
44
45   dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
46
47   if (dconf == NULL) {
48     DBG(r,"none encoding.");
49     return (char*)src;
50   }
51
52   entryp = chxj_apply_convrule(r, dconf->convrules);
53   if (entryp->encoding == NULL) {
54     DBG(r,"none encoding.");
55     return (char*)src;
56   }
57
58   if (STRCASEEQ('n','N',"none", entryp->encoding)) {
59     DBG(r,"none encoding.");
60     return (char*)src;
61   }
62   ilen = *len;
63   ibuf = apr_palloc(pool, ilen+1);
64   if (ibuf == NULL) {
65     DBG(r,"end   chxj_encoding()");
66     return (char*)src;
67   }
68   memset(ibuf, 0, ilen+1);
69   memcpy(ibuf, src, ilen);
70
71   olen = ilen * 4 + 1;
72   spos = obuf = apr_palloc(pool, olen);
73   if (obuf == NULL) {
74     DBG(r,"end   chxj_encoding()");
75     return ibuf;
76   }
77   DBG(r,"encode convert [%s] -> [%s]", entryp->encoding, "CP932");
78
79   memset(obuf, 0, olen);
80   cd = iconv_open("CP932", entryp->encoding);
81   if (cd == (iconv_t)-1) {
82     if (EINVAL == errno) {
83       ERR(r, "The conversion from %s to %s is not supported by the implementation.", entryp->encoding, "CP932");
84     }
85     else {
86       ERR(r, "iconv open failed. from:[%s] to:[%s] errno:[%d]", entryp->encoding, "CP932", errno);
87     }
88     DBG(r,"end   chxj_encoding()");
89     return ibuf;
90   }
91   while (ilen > 0) {
92     result = iconv(cd, &ibuf, &ilen, &obuf, &olen);
93     if (result == (size_t)(-1)) {
94       if (E2BIG == errno) {
95         ERR(r, "There is not sufficient room at *outbuf.");
96       }
97       else if (EILSEQ == errno) {
98         ERR(r, "An invalid multibyte sequence has been encountered in the input. input:[%s]", ibuf);
99       }
100       else if (EINVAL == errno) {
101         ERR(r, "An incomplete multibyte sequence has been encountered in the input. input:[%s]", ibuf);
102       }
103       break;
104     }
105   }
106   *len = strlen(spos);
107   iconv_close(cd);
108
109   DBG(r,"end   chxj_encoding() len=[%d] obuf=[%.*s]", (int)*len, (int)*len, spos);
110   return spos;
111 }
112
113
114 char*
115 chxj_rencoding(request_rec *r, const char* src, apr_size_t* len)
116 {
117   char*               obuf;
118   char*               ibuf;
119   char*               spos;
120   
121   iconv_t             cd;
122   size_t              result;
123   apr_size_t          ilen;
124   apr_size_t          olen;
125   mod_chxj_config*    dconf;
126   chxjconvrule_entry* entryp;
127
128   DBG(r,"start chxj_rencoding()");
129
130   dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
131   if (! dconf) {
132     DBG(r,"none encoding.");
133     DBG(r,"end   chxj_rencoding()");
134     return (char*)src;
135   }
136
137   entryp = chxj_apply_convrule(r, dconf->convrules);
138   if (! entryp->encoding) {
139     DBG(r,"none encoding.");
140     DBG(r,"end   chxj_rencoding()");
141     return (char*)src;
142   }
143
144   if (STRCASEEQ('n','N',"none", entryp->encoding)) {
145     DBG(r,"none encoding.");
146     DBG(r,"end   chxj_rencoding()");
147     return (char*)src;
148   }
149
150   ilen = *len;
151   ibuf = apr_palloc(r->pool, ilen+1);
152   if (! ibuf) {
153     DBG(r,"end   chxj_rencoding()");
154     return (char*)src;
155   }
156
157   memset(ibuf, 0,   ilen+1);
158   memcpy(ibuf, src, ilen+0);
159
160   olen = ilen * 4 + 1;
161   spos = obuf = apr_palloc(r->pool, olen);
162   if (! obuf) {
163     DBG(r,"end   chxj_rencoding()");
164     return ibuf;
165   }
166   DBG(r,"encode convert [%s] -> [%s]", "CP932", entryp->encoding);
167
168   memset(obuf, 0, olen);
169
170   cd = iconv_open(entryp->encoding, "CP932");
171   if (cd == (iconv_t)-1) {
172     if (EINVAL == errno) {
173       ERR(r, "The conversion from %s to %s is not supported by the implementation.", "CP932", entryp->encoding);
174     }
175     DBG(r,"end   chxj_rencoding()");
176     return ibuf;
177   }
178
179   while (ilen > 0) {
180     result = iconv(cd, &ibuf, &ilen, &obuf, &olen);
181     if (result == (size_t)(-1)) {
182       if (E2BIG == errno) {
183         ERR(r, "There is not sufficient room at *outbuf");
184       }
185       else if (EILSEQ == errno) {
186         ERR(r, "An invalid multibyte sequence has been encountered in the input. input:[%s]", ibuf);
187       }
188       else if (EINVAL == errno) {
189         ERR(r, "An incomplete multibyte sequence has been encountered in the input. input:[%s]", ibuf);
190       }
191       break;
192     }
193   }
194
195   *len = strlen(spos);
196   iconv_close(cd);
197
198   DBG(r,"end   chxj_rencoding() len=[%d] obuf=[%.*s]", (int)*len, (int)*len, spos);
199
200   return spos;
201 }
202
203
204 char*
205 chxj_encoding_parameter(request_rec *r, const char *value)
206 {
207   char *src;
208   char *src_sv;
209   char *pstat;
210   char *spos;
211   char *pair;
212   char *key;
213   char *val;
214   char *vstat;
215   char *param;
216
217   int   use_amp_flag;
218   
219   DBG(r, "start chxj_encoding_parameter()");
220
221   src = apr_pstrdup(r->pool, value);
222
223   spos = strchr(src, '?');
224   if (!spos) {
225     DBG(r, "end   chxj_encoding_parameter()");
226     return src;
227   }
228   *spos++ = 0;
229
230   src_sv = apr_pstrdup(r->pool, src);
231   param  = apr_palloc(r->pool, 1);
232   param[0] = 0;
233
234   for (;;) {
235     apr_size_t len;
236
237     use_amp_flag = 0;
238
239     pair = apr_strtok(spos, "&", &pstat);
240     spos = NULL;
241     if (!pair) break;
242     if (strncasecmp(pair, "amp;", 4) == 0) {
243       pair += 4;
244       use_amp_flag = 1;
245     }
246     key = apr_strtok(pair, "=", &vstat);
247     val = apr_strtok(NULL, "=", &vstat);
248     if (val) {
249       val = chxj_url_decode(r, val);
250       len = (apr_size_t)strlen(val);
251       val = chxj_encoding(r, val, &len);
252       val = chxj_url_encode(r, val);
253       if (strlen(param) == 0) {
254         param = apr_pstrcat(r->pool, param, key, "=", val, NULL);
255       }
256       else {
257         if (use_amp_flag) {
258           param = apr_pstrcat(r->pool, param, "&amp;", key, "=", val, NULL);
259         }
260         else {
261           param = apr_pstrcat(r->pool, param, "&", key, "=", val, NULL);
262         }
263       }
264     }
265     else {
266       if (strlen(param) == 0) {
267         param = apr_pstrcat(r->pool, param, key,  NULL);
268       }
269       else {
270         if (use_amp_flag) {
271           param = apr_pstrcat(r->pool, param, "&amp;", key, NULL);
272         }
273         else {
274           param = apr_pstrcat(r->pool, param, "&", key, NULL);
275         }
276       }
277     }
278   }
279   DBG(r, "end   chxj_encoding_parameter()");
280
281   return apr_pstrcat(r->pool, src_sv, "?", param, NULL);
282 }
283 /*
284  * vim:ts=2 et
285  */