OSDN Git Service

3049c6e3b040365fac526a1db2fdea2bbc244c85
[bbk/bchan.git] / src / sjisstring.c
1 /*
2  * sjisstring.c
3  *
4  * Copyright (c) 2009-2010 project bchan
5  *
6  * This software is provided 'as-is', without any express or implied
7  * warranty. In no event will the authors be held liable for any damages
8  * arising from the use of this software.
9  *
10  * Permission is granted to anyone to use this software for any purpose,
11  * including commercial applications, and to alter it and redistribute it
12  * freely, subject to the following restrictions:
13  *
14  * 1. The origin of this software must not be misrepresented; you must not
15  *    claim that you wrote the original software. If you use this software
16  *    in a product, an acknowledgment in the product documentation would be
17  *    appreciated but is not required.
18  *
19  * 2. Altered source versions must be plainly marked as such, and must not be
20  *    misrepresented as being the original software.
21  *
22  * 3. This notice may not be removed or altered from any source
23  *    distribution.
24  *
25  */
26
27 #include        <basic.h>
28 #include        <bstdlib.h>
29 #include        <bstdio.h>
30 #include        <bstring.h>
31 #include        <bctype.h>
32 #include        <tstring.h>
33
34 #include    "sjisstring.h"
35
36 EXPORT W sjstring_appendasciistring(UB **dest, W *dest_len, UB *str, W len)
37 {
38         if (len <= 0) {
39                 return 0;
40         }
41
42         *dest = realloc(*dest, *dest_len + len + 1);
43         if (*dest == NULL) {
44                 *dest_len = 0;
45                 return -1;
46         }
47         memcpy((*dest)+*dest_len, str, len);
48         *dest_len += len;
49         (*dest)[*dest_len] = '\0';
50
51         return 0;
52 }
53
54 LOCAL UB dec[] = "0123456789";
55
56 EXPORT W sjstring_appendUWstring(UB **dest, W *dlen, UW n)
57 {
58         W i = 0,digit,draw = 0;
59         UB str[10];
60
61         digit = n / 1000000000 % 10;
62         if ((digit != 0)||(draw != 0)) {
63                 str[i++] = dec[digit];
64                 draw = 1;
65         }
66         digit = n / 100000000 % 10;
67         if ((digit != 0)||(draw != 0)) {
68                 str[i++] = dec[digit];
69                 draw = 1;
70         }
71         digit = n / 10000000 % 10;
72         if ((digit != 0)||(draw != 0)) {
73                 str[i++] = dec[digit];
74                 draw = 1;
75         }
76         digit = n / 1000000 % 10;
77         if ((digit != 0)||(draw != 0)) {
78                 str[i++] = dec[digit];
79                 draw = 1;
80         }
81         digit = n / 100000 % 10;
82         if ((digit != 0)||(draw != 0)) {
83                 str[i++] = dec[digit];
84                 draw = 1;
85         }
86         digit = n / 10000 % 10;
87         if ((digit != 0)||(draw != 0)) {
88                 str[i++] = dec[digit];
89                 draw = 1;
90         }
91         digit = n / 1000 % 10;
92         if ((digit != 0)||(draw != 0)) {
93                 str[i++] = dec[digit];
94                 draw = 1;
95         }
96         digit = n / 100 % 10;
97         if ((digit != 0)||(draw != 0)) {
98                 str[i++] = dec[digit];
99                 draw = 1;
100         }
101         digit = n / 10 % 10;
102         if ((digit != 0)||(draw != 0)) {
103                 str[i++] = dec[digit];
104                 draw = 1;
105         }
106         digit = n % 10;
107         str[i++] = dec[digit];
108
109         return sjstring_appendasciistring(dest, dlen, str, i);
110 }
111
112 /* rfc2396.txt */
113 LOCAL W urlencode_needlength(UB *bin, W len)
114 {
115         W i, ret = 0;
116
117         for (i=0;i<len;i++) {
118                 if (bin[i] == 0x2E) { /* '.' */
119                         ret++;
120                 } else if (bin[i] == 0x2D) { /* '-' */
121                         ret++;
122                 } else if (bin[i] == 0x5F) { /* '_' */
123                         ret++;
124                 } else if (bin[i] == 0x20) { /* ' ' */
125                         ret++;
126                 } else if (isalnum(bin[i])) {
127                         ret++;
128                 } else {
129                         ret+=3;
130                 }
131         }
132
133         return ret;
134 }
135
136 LOCAL W urlencode_convert(UB *dest, W dest_len, UB *src, W src_len)
137 {
138         W i,j = 0;
139         static UB num[] = "0123456789ABCDEF";
140
141         for (i=0;i<src_len;i++) {
142                 if (src[i] == 0x2E) { /* '.' */
143                         dest[j++] = src[i];
144                 } else if (src[i] == 0x2D) { /* '-' */
145                         dest[j++] = src[i];
146                 } else if (src[i] == 0x5F) { /* '_' */
147                         dest[j++] = src[i];
148                 } else if (src[i] == 0x20) { /* ' ' */
149                         dest[j++] = 0x2B; /* '+' */
150                 } else if (isalnum(src[i])) {
151                         dest[j++] = src[i];
152                 } else {
153                         dest[j++] = 0x25; /* '%' */
154                         if (j == dest_len) {
155                                 break;
156                         }
157                         dest[j++] = num[(src[i] >> 4)];
158                         if (j == dest_len) {
159                                 break;
160                         }
161                         dest[j++] = num[(src[i] & 0xF)];
162                 }
163                 if (j == dest_len) {
164                         break;
165                 }
166         }
167
168         return j;
169 }
170
171 EXPORT W sjstring_appendurlencodestring(UB **dest, W *dest_len, UB *str, W len)
172 {
173         W encoded_len;
174
175         if (len == 0) {
176                 return 0;
177         }
178
179         encoded_len = urlencode_needlength(str, len);
180
181         *dest = realloc(*dest, *dest_len + encoded_len + 1);
182         if (*dest == NULL) {
183                 return -1; /* TODO */
184         }
185
186         urlencode_convert(*dest + *dest_len, encoded_len, str, len);
187
188         *dest_len += encoded_len;
189         (*dest)[*dest_len] = '\0';
190
191         return 0;
192 }
193
194 EXPORT W sjstring_appendconvartingTCstring(UB **dest, W *dest_len, TC *str, W len)
195 {
196         W i,j,converted_len = 0, ret;
197         UB conv[2];
198
199         for (i = 0; i < len; i++) {
200                 ret = tctosj(NULL, str[i]);
201                 if (ret == -1) {
202                         return -1; /* TODO */
203                 }
204                 converted_len += ret;
205         }
206
207         *dest = realloc(*dest, *dest_len + converted_len + 1);
208         if (*dest == NULL) {
209                 return -1; /* TODO */
210         }
211
212         j = 0;
213         for (i = 0; i < len; i++) {
214                 ret = tctosj(conv, str[i]);
215                 if (ret == -1) {
216                         return -1; /* TODO */
217                 }
218                 memcpy(*(dest)+*dest_len+j, conv, ret);
219                 j += ret;
220         }
221
222         *dest_len += converted_len;
223         (*dest)[*dest_len] = '\0';
224
225         return 0;
226 }
227
228 EXPORT W sjstring_appendformpoststring(UB **dest, W *dest_len, UB *str, W len)
229 {
230         UB ch0,si;
231         W i,err;
232  
233         si = 0;
234         for (i = 0; i < len; i++) {
235                 ch0 = str[i];
236                 if (((0x81 <= ch0)&&(ch0 <= 0x9f))
237                         ||((0xe0 <= ch0)&&(ch0 <= 0xef))) {
238                         i++;
239                         continue;
240                 }
241
242                 if (ch0 == '<') {
243                         err = sjstring_appendurlencodestring(dest, dest_len, str+si, i-si);
244                         if (err < 0) {
245                                 return err;
246                         }
247                         err = sjstring_appendurlencodestring(dest, dest_len, "&lt;", 4);
248                         if (err < 0) {
249                                 return err;
250                         }
251                         si = i+1;
252                 } else if (ch0 == '>') {
253                         err = sjstring_appendurlencodestring(dest, dest_len, str+si, i-si);
254                         if (err < 0) {
255                                 return err;
256                         }
257                         err = sjstring_appendurlencodestring(dest, dest_len, "&gt;", 4);
258                         if (err < 0) {
259                                 return err;
260                         }
261                         si = i+1;
262                 } else if (ch0 == '"') {
263                         err = sjstring_appendurlencodestring(dest, dest_len, str+si, i-si);
264                         if (err < 0) {
265                                 return err;
266                         }
267                         err = sjstring_appendurlencodestring(dest, dest_len, "&quot;", 6);
268                         if (err < 0) {
269                                 return err;
270                         }
271                         si = i+1;
272                 }
273         }
274
275         return sjstring_appendurlencodestring(dest, dest_len, str+si, i-si);
276 }
277
278 EXPORT UB* sjstring_searchchar(UB *str, W len, UB ch)
279 {
280         UB ch0;
281         W i;
282
283         /* not lower byte of 2 bytes character in Shift_JIS. */
284         if (!(((0x40 <= ch)&&(ch <= 0x7e))||((0x80 < ch)&&(ch < 0xfc)))) {
285                 for (i = 0; i < len; i++) {
286                         if (str[i] == ch) {
287                                 return str + i;
288                         }
289                         if (str[i] == '\0') {
290                                 return NULL;
291                         }
292                 }
293                 return NULL;
294         }
295
296         for (i = 0; i < len; i++) {
297                 ch0 = str[i];
298                 if (((0x81 <= ch0)&&(ch0 <= 0x9f))
299                         ||((0xe0 <= ch0)&&(ch0 <= 0xef))) {
300                         i++;
301                         continue;
302                 }
303                 if (ch0 == ch) {
304                         return str + i;
305                 }
306                 if (ch0 == '\0') {
307                         return NULL;
308                 }
309         }
310
311         return NULL;
312 }
313
314 EXPORT W sjstring_totcs(UB *sjstr, UB sjstr_len, TC *tcstr)
315 {
316         W i, ret, tclen = 0;
317
318         if (tcstr == NULL) {
319                 for (i = 0; i < sjstr_len; i++) {
320                         ret = sjtotc(NULL, sjstr + i);
321                         switch (ret) {
322                         case -1:
323                                 return -1;
324                         case 0:
325                                 break;
326                         case 1:
327                                 tclen++;
328                                 break;
329                         case 2:
330                                 tclen++;
331                                 i++;
332                                 break;
333                         }
334                 }
335                 return tclen;
336         }
337
338         for (i = 0; i < sjstr_len; i++) {
339                 ret = sjtotc(tcstr + tclen, sjstr + i);
340                 switch (ret) {
341                 case -1:
342                         return -1;
343                 case 0:
344                         break;
345                 case 1:
346                         tclen++;
347                         break;
348                 case 2:
349                         tclen++;
350                         i++;
351                         break;
352                 }
353         }
354
355         return tclen;
356 }
357
358 /* from rfc1738. 2.2. URL Character Encoding Issues */
359 /* should be more speed up. */
360 EXPORT Bool sjstring_isurlusablecharacter(UB ch)
361 {
362         /* No corresponding graphic US-ASCII */
363         if ((0x00 <= ch)&&(ch <= 0x1F)) {
364                 return False;
365         }
366         if (ch == 0x7F) {
367                 return False;
368         }
369         if ((0x80 <= ch)&&(ch <= 0xFF)) {
370                 return False;
371         }
372
373         /* Unsafe */
374         if (ch == '<') {
375                 return False;
376         }
377         if (ch == '>') {
378                 return False;
379         }
380         if (ch == '"') {
381                 return False;
382         }
383         if (ch == '{') {
384                 return False;
385         }
386         if (ch == '}') {
387                 return False;
388         }
389         if (ch == '|') {
390                 return False;
391         }
392         if (ch == '\\') {
393                 return False;
394         }
395         if (ch == '^') {
396                 return False;
397         }
398         if (ch == '~') {
399                 return False;
400         }
401         if (ch == '[') {
402                 return False;
403         }
404         if (ch == ']') {
405                 return False;
406         }
407         if (ch == '`') {
408                 return False;
409         }
410
411         /* whitespace */
412         /*  should be ignore? */
413         /*   by "APPENDIX: Recommendations for URLs in Context" */
414         /*  to handling these, need parsing. */
415         if (ch == ' ') {
416                 return False;
417         }
418         if (ch == '\t') {
419                 return False;
420         }
421         if (ch == '\n') {
422                 return False;
423         }
424         if (ch == '\r') {
425                 return False;
426         }
427
428         return True;
429 }
430
431 #ifdef BCHAN_CONFIG_DEBUG
432 #include        <tstring.h>
433
434 EXPORT VOID SJSTRING_DP(UB *str, W len)
435 {
436         W i, print_len;
437         TC *print;
438
439         print_len = sjstotcs(NULL, str);
440         print = malloc(sizeof(TC)*(print_len + 1));
441         if (print == NULL) {
442                 return;
443         }
444
445         sjstotcs(print, str);
446         print[print_len] = TNULL;
447
448         for (i=0;i<print_len;i++) {
449                 printf("%C", print[i]);
450         }
451
452         free(print);
453 }
454 #endif