1 :
2 : /* gdkanji.c (Kanji code converter) */
3 : /* written by Masahito Yamaga (ma@yama-ga.com) */
4 :
5 : #include <stdio.h>
6 : #include <stdlib.h>
7 : #include <string.h>
8 : #include "gd.h"
9 : #include "gdhelpers.h"
10 :
11 : #include <stdarg.h>
12 : #if defined(HAVE_ICONV_H) || defined(HAVE_ICONV)
13 : #include <iconv.h>
14 : #ifdef HAVE_ERRNO_H
15 : #include <errno.h>
16 : #endif
17 : #endif
18 :
19 : #if defined(HAVE_ICONV_H) && !defined(HAVE_ICONV)
20 : #define HAVE_ICONV 1
21 : #endif
22 :
23 : #define LIBNAME "any2eucjp()"
24 :
25 : #if defined(__MSC__) || defined(__BORLANDC__) || defined(__TURBOC__) || defined(_Windows) || defined(MSDOS)
26 : #ifndef SJISPRE
27 : #define SJISPRE 1
28 : #endif
29 : #endif
30 :
31 : #ifdef TRUE
32 : #undef TRUE
33 : #endif
34 : #ifdef FALSE
35 : #undef FALSE
36 : #endif
37 :
38 : #define TRUE 1
39 : #define FALSE 0
40 :
41 : #define NEW 1
42 : #define OLD 2
43 : #define ESCI 3
44 : #define NEC 4
45 : #define EUC 5
46 : #define SJIS 6
47 : #define EUCORSJIS 7
48 : #define ASCII 8
49 :
50 : #define NEWJISSTR "JIS7"
51 : #define OLDJISSTR "jis"
52 : #define EUCSTR "eucJP"
53 : #define SJISSTR "SJIS"
54 :
55 : #define ESC 27
56 : #define SS2 142
57 :
58 : static void
59 : debug (const char *format,...)
60 0 : {
61 : #ifdef DEBUG
62 : va_list args;
63 :
64 : va_start (args, format);
65 : fprintf (stdout, "%s: ", LIBNAME);
66 : vfprintf (stdout, format, args);
67 : fprintf (stdout, "\n");
68 : va_end (args);
69 : #endif
70 0 : }
71 :
72 : static void
73 : error (const char *format,...)
74 0 : {
75 : va_list args;
76 : char *tmp;
77 : TSRMLS_FETCH();
78 :
79 0 : va_start(args, format);
80 0 : vspprintf(&tmp, 0, format, args);
81 0 : va_end(args);
82 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: %s", LIBNAME, tmp);
83 0 : efree(tmp);
84 0 : }
85 :
86 : /* DetectKanjiCode() derived from DetectCodeType() by Ken Lunde. */
87 :
88 : static int
89 : DetectKanjiCode (unsigned char *str)
90 0 : {
91 : static int whatcode = ASCII;
92 0 : int oldcode = ASCII;
93 : int c, i;
94 0 : char *lang = NULL;
95 :
96 0 : c = '\1';
97 0 : i = 0;
98 :
99 0 : if (whatcode != EUCORSJIS && whatcode != ASCII)
100 : {
101 0 : oldcode = whatcode;
102 0 : whatcode = ASCII;
103 : }
104 :
105 0 : while ((whatcode == EUCORSJIS || whatcode == ASCII) && c != '\0')
106 : {
107 0 : if ((c = str[i++]) != '\0')
108 : {
109 0 : if (c == ESC)
110 : {
111 0 : c = str[i++];
112 0 : if (c == '$')
113 : {
114 0 : c = str[i++];
115 0 : if (c == 'B')
116 0 : whatcode = NEW;
117 0 : else if (c == '@')
118 0 : whatcode = OLD;
119 : }
120 0 : else if (c == '(')
121 : {
122 0 : c = str[i++];
123 0 : if (c == 'I')
124 0 : whatcode = ESCI;
125 : }
126 0 : else if (c == 'K')
127 0 : whatcode = NEC;
128 : }
129 0 : else if ((c >= 129 && c <= 141) || (c >= 143 && c <= 159))
130 0 : whatcode = SJIS;
131 0 : else if (c == SS2)
132 : {
133 0 : c = str[i++];
134 0 : if ((c >= 64 && c <= 126) || (c >= 128 && c <= 160) || (c >= 224 && c <= 252))
135 0 : whatcode = SJIS;
136 0 : else if (c >= 161 && c <= 223)
137 0 : whatcode = EUCORSJIS;
138 : }
139 0 : else if (c >= 161 && c <= 223)
140 : {
141 0 : c = str[i++];
142 0 : if (c >= 240 && c <= 254)
143 0 : whatcode = EUC;
144 0 : else if (c >= 161 && c <= 223)
145 0 : whatcode = EUCORSJIS;
146 0 : else if (c >= 224 && c <= 239)
147 : {
148 0 : whatcode = EUCORSJIS;
149 0 : while (c >= 64 && c != '\0' && whatcode == EUCORSJIS)
150 : {
151 0 : if (c >= 129)
152 : {
153 0 : if (c <= 141 || (c >= 143 && c <= 159))
154 0 : whatcode = SJIS;
155 0 : else if (c >= 253 && c <= 254)
156 0 : whatcode = EUC;
157 : }
158 0 : c = str[i++];
159 : }
160 : }
161 0 : else if (c <= 159)
162 0 : whatcode = SJIS;
163 : }
164 0 : else if (c >= 240 && c <= 254)
165 0 : whatcode = EUC;
166 0 : else if (c >= 224 && c <= 239)
167 : {
168 0 : c = str[i++];
169 0 : if ((c >= 64 && c <= 126) || (c >= 128 && c <= 160))
170 0 : whatcode = SJIS;
171 0 : else if (c >= 253 && c <= 254)
172 0 : whatcode = EUC;
173 0 : else if (c >= 161 && c <= 252)
174 0 : whatcode = EUCORSJIS;
175 : }
176 : }
177 : }
178 :
179 : #ifdef DEBUG
180 : if (whatcode == ASCII)
181 : debug ("Kanji code not included.");
182 : else if (whatcode == EUCORSJIS)
183 : debug ("Kanji code not detected.");
184 : else
185 : debug ("Kanji code detected at %d byte.", i);
186 : #endif
187 :
188 0 : if (whatcode == EUCORSJIS && oldcode != ASCII)
189 0 : whatcode = oldcode;
190 :
191 0 : if (whatcode == EUCORSJIS)
192 : {
193 0 : if (getenv ("LC_ALL"))
194 0 : lang = getenv ("LC_ALL");
195 0 : else if (getenv ("LC_CTYPE"))
196 0 : lang = getenv ("LC_CTYPE");
197 0 : else if (getenv ("LANG"))
198 0 : lang = getenv ("LANG");
199 :
200 0 : if (lang)
201 : {
202 0 : if (strcmp (lang, "ja_JP.SJIS") == 0 ||
203 : #ifdef hpux
204 : strcmp (lang, "japanese") == 0 ||
205 : #endif
206 : strcmp (lang, "ja_JP.mscode") == 0 ||
207 : strcmp (lang, "ja_JP.PCK") == 0)
208 0 : whatcode = SJIS;
209 0 : else if (strncmp (lang, "ja", 2) == 0)
210 : #ifdef SJISPRE
211 : whatcode = SJIS;
212 : #else
213 0 : whatcode = EUC;
214 : #endif
215 : }
216 : }
217 :
218 0 : if (whatcode == EUCORSJIS)
219 : #ifdef SJISPRE
220 : whatcode = SJIS;
221 : #else
222 0 : whatcode = EUC;
223 : #endif
224 :
225 0 : return whatcode;
226 : }
227 :
228 : /* SJIStoJIS() is sjis2jis() by Ken Lunde. */
229 :
230 : static void
231 : SJIStoJIS (int *p1, int *p2)
232 0 : {
233 0 : register unsigned char c1 = *p1;
234 0 : register unsigned char c2 = *p2;
235 0 : register int adjust = c2 < 159;
236 0 : register int rowOffset = c1 < 160 ? 112 : 176;
237 0 : register int cellOffset = adjust ? (31 + (c2 > 127)) : 126;
238 :
239 0 : *p1 = ((c1 - rowOffset) << 1) - adjust;
240 0 : *p2 -= cellOffset;
241 0 : }
242 :
243 : /* han2zen() was derived from han2zen() written by Ken Lunde. */
244 :
245 : #define IS_DAKU(c) ((c >= 182 && c <= 196) || (c >= 202 && c <= 206) || (c == 179))
246 : #define IS_HANDAKU(c) (c >= 202 && c <= 206)
247 :
248 : static void
249 : han2zen (int *p1, int *p2)
250 0 : {
251 0 : int c = *p1;
252 0 : int daku = FALSE;
253 0 : int handaku = FALSE;
254 : int mtable[][2] =
255 : {
256 : {129, 66},
257 : {129, 117},
258 : {129, 118},
259 : {129, 65},
260 : {129, 69},
261 : {131, 146},
262 : {131, 64},
263 : {131, 66},
264 : {131, 68},
265 : {131, 70},
266 : {131, 72},
267 : {131, 131},
268 : {131, 133},
269 : {131, 135},
270 : {131, 98},
271 : {129, 91},
272 : {131, 65},
273 : {131, 67},
274 : {131, 69},
275 : {131, 71},
276 : {131, 73},
277 : {131, 74},
278 : {131, 76},
279 : {131, 78},
280 : {131, 80},
281 : {131, 82},
282 : {131, 84},
283 : {131, 86},
284 : {131, 88},
285 : {131, 90},
286 : {131, 92},
287 : {131, 94},
288 : {131, 96},
289 : {131, 99},
290 : {131, 101},
291 : {131, 103},
292 : {131, 105},
293 : {131, 106},
294 : {131, 107},
295 : {131, 108},
296 : {131, 109},
297 : {131, 110},
298 : {131, 113},
299 : {131, 116},
300 : {131, 119},
301 : {131, 122},
302 : {131, 125},
303 : {131, 126},
304 : {131, 128},
305 : {131, 129},
306 : {131, 130},
307 : {131, 132},
308 : {131, 134},
309 : {131, 136},
310 : {131, 137},
311 : {131, 138},
312 : {131, 139},
313 : {131, 140},
314 : {131, 141},
315 : {131, 143},
316 : {131, 147},
317 : {129, 74},
318 : {129, 75}
319 0 : };
320 :
321 0 : if (*p2 == 222 && IS_DAKU (*p1))
322 0 : daku = TRUE; /* Daku-ten */
323 0 : else if (*p2 == 223 && IS_HANDAKU (*p1))
324 0 : handaku = TRUE; /* Han-daku-ten */
325 :
326 0 : *p1 = mtable[c - 161][0];
327 0 : *p2 = mtable[c - 161][1];
328 :
329 0 : if (daku)
330 : {
331 0 : if ((*p2 >= 74 && *p2 <= 103) || (*p2 >= 110 && *p2 <= 122))
332 0 : (*p2)++;
333 0 : else if (*p2 == 131 && *p2 == 69)
334 0 : *p2 = 148;
335 : }
336 0 : else if (handaku && *p2 >= 110 && *p2 <= 122)
337 0 : (*p2) += 2;
338 0 : }
339 :
340 : /* Recast strcpy to handle unsigned chars used below. */
341 : #define ustrcpy(A,B) (strcpy((char*)(A),(const char*)(B)))
342 :
343 : static void
344 : do_convert (unsigned char *to, unsigned char *from, const char *code)
345 0 : {
346 : #ifdef HAVE_ICONV
347 : iconv_t cd;
348 : size_t from_len, to_len;
349 :
350 0 : if ((cd = iconv_open (EUCSTR, code)) == (iconv_t) - 1)
351 : {
352 0 : error ("iconv_open() error");
353 : #ifdef HAVE_ERRNO_H
354 0 : if (errno == EINVAL)
355 0 : error ("invalid code specification: \"%s\" or \"%s\"",
356 : EUCSTR, code);
357 : #endif
358 0 : strcpy ((char *) to, (const char *) from);
359 0 : return;
360 : }
361 :
362 0 : from_len = strlen ((const char *) from) + 1;
363 0 : to_len = BUFSIZ;
364 :
365 0 : if ((int) iconv(cd, (char **) &from, &from_len, (char **) &to, &to_len) == -1)
366 : {
367 : #ifdef HAVE_ERRNO_H
368 0 : if (errno == EINVAL)
369 0 : error ("invalid end of input string");
370 0 : else if (errno == EILSEQ)
371 0 : error ("invalid code in input string");
372 0 : else if (errno == E2BIG)
373 0 : error ("output buffer overflow at do_convert()");
374 : else
375 : #endif
376 0 : error ("something happen");
377 0 : strcpy ((char *) to, (const char *) from);
378 0 : return;
379 : }
380 :
381 0 : if (iconv_close (cd) != 0)
382 : {
383 0 : error ("iconv_close() error");
384 : }
385 : #else
386 : int p1, p2, i, j;
387 : int jisx0208 = FALSE;
388 : int hankaku = FALSE;
389 :
390 : j = 0;
391 : if (strcmp (code, NEWJISSTR) == 0 || strcmp (code, OLDJISSTR) == 0)
392 : {
393 : for (i = 0; from[i] != '\0' && j < BUFSIZ; i++)
394 : {
395 : if (from[i] == ESC)
396 : {
397 : i++;
398 : if (from[i] == '$')
399 : {
400 : jisx0208 = TRUE;
401 : hankaku = FALSE;
402 : i++;
403 : }
404 : else if (from[i] == '(')
405 : {
406 : jisx0208 = FALSE;
407 : i++;
408 : if (from[i] == 'I') /* Hankaku Kana */
409 : hankaku = TRUE;
410 : else
411 : hankaku = FALSE;
412 : }
413 : }
414 : else
415 : {
416 : if (jisx0208)
417 : to[j++] = from[i] + 128;
418 : else if (hankaku)
419 : {
420 : to[j++] = SS2;
421 : to[j++] = from[i] + 128;
422 : }
423 : else
424 : to[j++] = from[i];
425 : }
426 : }
427 : }
428 : else if (strcmp (code, SJISSTR) == 0)
429 : {
430 : for (i = 0; from[i] != '\0' && j < BUFSIZ; i++)
431 : {
432 : p1 = from[i];
433 : if (p1 < 127)
434 : to[j++] = p1;
435 : else if ((p1 >= 161) && (p1 <= 223))
436 : { /* Hankaku Kana */
437 : to[j++] = SS2;
438 : to[j++] = p1;
439 : }
440 : else
441 : {
442 : p2 = from[++i];
443 : SJIStoJIS (&p1, &p2);
444 : to[j++] = p1 + 128;
445 : to[j++] = p2 + 128;
446 : }
447 : }
448 : }
449 : else
450 : {
451 : error ("invalid code specification: \"%s\"", code);
452 : return;
453 : }
454 :
455 : if (j >= BUFSIZ)
456 : {
457 : error ("output buffer overflow at do_convert()");
458 : ustrcpy (to, from);
459 : }
460 : else
461 : to[j] = '\0';
462 : #endif /* HAVE_ICONV */
463 : }
464 :
465 : static int
466 : do_check_and_conv (unsigned char *to, unsigned char *from)
467 0 : {
468 : static unsigned char tmp[BUFSIZ];
469 : int p1, p2, i, j;
470 0 : int kanji = TRUE;
471 :
472 0 : switch (DetectKanjiCode (from))
473 : {
474 : case NEW:
475 0 : debug ("Kanji code is New JIS.");
476 0 : do_convert (tmp, from, NEWJISSTR);
477 0 : break;
478 : case OLD:
479 0 : debug ("Kanji code is Old JIS.");
480 0 : do_convert (tmp, from, OLDJISSTR);
481 0 : break;
482 : case ESCI:
483 0 : debug ("This string includes Hankaku-Kana (jisx0201) escape sequence [ESC] + ( + I.");
484 0 : do_convert (tmp, from, NEWJISSTR);
485 0 : break;
486 : case NEC:
487 0 : debug ("Kanji code is NEC Kanji.");
488 0 : error ("cannot convert NEC Kanji.");
489 0 : ustrcpy (tmp, from);
490 0 : kanji = FALSE;
491 0 : break;
492 : case EUC:
493 0 : debug ("Kanji code is EUC.");
494 0 : ustrcpy (tmp, from);
495 0 : break;
496 : case SJIS:
497 0 : debug ("Kanji code is SJIS.");
498 0 : do_convert (tmp, from, SJISSTR);
499 0 : break;
500 : case EUCORSJIS:
501 0 : debug ("Kanji code is EUC or SJIS.");
502 0 : ustrcpy (tmp, from);
503 0 : kanji = FALSE;
504 0 : break;
505 : case ASCII:
506 0 : debug ("This is ASCII string.");
507 0 : ustrcpy (tmp, from);
508 0 : kanji = FALSE;
509 0 : break;
510 : default:
511 0 : debug ("This string includes unknown code.");
512 0 : ustrcpy (tmp, from);
513 0 : kanji = FALSE;
514 : break;
515 : }
516 :
517 : /* Hankaku Kana ---> Zenkaku Kana */
518 0 : if (kanji)
519 : {
520 0 : j = 0;
521 0 : for (i = 0; tmp[i] != '\0' && j < BUFSIZ; i++)
522 : {
523 0 : if (tmp[i] == SS2)
524 : {
525 0 : p1 = tmp[++i];
526 0 : if (tmp[i + 1] == SS2)
527 : {
528 0 : p2 = tmp[i + 2];
529 0 : if (p2 == 222 || p2 == 223)
530 0 : i += 2;
531 : else
532 0 : p2 = 0;
533 : }
534 : else
535 0 : p2 = 0;
536 0 : han2zen (&p1, &p2);
537 0 : SJIStoJIS (&p1, &p2);
538 0 : to[j++] = p1 + 128;
539 0 : to[j++] = p2 + 128;
540 : }
541 : else
542 0 : to[j++] = tmp[i];
543 : }
544 :
545 0 : if (j >= BUFSIZ)
546 : {
547 0 : error ("output buffer overflow at Hankaku --> Zenkaku");
548 0 : ustrcpy (to, tmp);
549 : }
550 : else
551 0 : to[j] = '\0';
552 : }
553 : else
554 0 : ustrcpy (to, tmp);
555 :
556 0 : return kanji;
557 : }
558 :
559 : int
560 : any2eucjp (unsigned char *dest, unsigned char *src, unsigned int dest_max)
561 0 : {
562 : static unsigned char tmp_dest[BUFSIZ];
563 : int ret;
564 :
565 0 : if (strlen ((const char *) src) >= BUFSIZ)
566 : {
567 0 : error ("input string too large");
568 0 : return -1;
569 : }
570 0 : if (dest_max > BUFSIZ)
571 : {
572 0 : error ("invalid maximum size of destination\nit should be less than %d.", BUFSIZ);
573 0 : return -1;
574 : }
575 0 : ret = do_check_and_conv (tmp_dest, src);
576 0 : if (strlen ((const char *) tmp_dest) >= dest_max)
577 : {
578 0 : error ("output buffer overflow");
579 0 : ustrcpy (dest, src);
580 0 : return -1;
581 : }
582 0 : ustrcpy (dest, tmp_dest);
583 0 : return ret;
584 : }
585 :
586 : #if 0
587 : unsigned int
588 : strwidth (unsigned char *s)
589 : {
590 : unsigned char *t;
591 : unsigned int i;
592 :
593 : t = (unsigned char *) gdMalloc (BUFSIZ);
594 : any2eucjp (t, s, BUFSIZ);
595 : i = strlen (t);
596 : gdFree (t);
597 : return i;
598 : }
599 :
600 : #ifdef DEBUG
601 : int
602 : main ()
603 : {
604 : unsigned char input[BUFSIZ];
605 : unsigned char *output;
606 : unsigned char *str;
607 : int c, i = 0;
608 :
609 : while ((c = fgetc (stdin)) != '\n' && i < BUFSIZ)
610 : input[i++] = c;
611 : input[i] = '\0';
612 :
613 : printf ("input : %d bytes\n", strlen ((const char *) input));
614 : printf ("output: %d bytes\n", strwidth (input));
615 :
616 : output = (unsigned char *) gdMalloc (BUFSIZ);
617 : any2eucjp (output, input, BUFSIZ);
618 : str = output;
619 : while (*str != '\0')
620 : putchar (*(str++));
621 : putchar ('\n');
622 : gdFree (output);
623 :
624 : return 0;
625 : }
626 : #endif
627 : #endif
|