OSDN Git Service

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