OSDN Git Service

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