charset.c
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:12k
源码类别:

手机WAP编程

开发平台:

WINDOWS

  1. /*
  2.  * gwlib/charset.c - character set conversions
  3.  *
  4.  * This file implements the character set conversions declared in charset.h.
  5.  *
  6.  * Richard Braakman
  7.  */
  8. #include "gwlib/gwlib.h"
  9. /* Map GSM default alphabet characters to ISO-Latin-1 characters.
  10.  * The greek characters at positions 16 and 18 through 26 are not
  11.  * mappable.  They are mapped to '?' characters.
  12.  * The escape character, at position 27, is mapped to a space,
  13.  * though normally the function that indexes into this table will
  14.  * treat it specially. */
  15. static const unsigned char gsm_to_latin1[128] = {
  16.  '@', 0xa3,  '$', 0xa5, 0xe8, 0xe9, 0xf9, 0xec,   /* 0 - 7 */
  17. 0xf2, 0xc7,   10, 0xd8, 0xf8,   13, 0xc5, 0xe5,   /* 8 - 15 */
  18.  '?',  '_',  '?',  '?',  '?',  '?',  '?',  '?',   /* 16 - 23 */
  19.          '?',  '?',  '?',  ' ', 0xc6, 0xe6, 0xdf, 0xc9,   /* 24 - 31 */
  20.  ' ',  '!',  '"',  '#', 0xa4,  '%',  '&', ''',   /* 32 - 39 */
  21.  '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',   /* 40 - 47 */
  22.  '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',   /* 48 - 55 */
  23.  '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',   /* 56 - 63 */
  24.         0xa1,  'A',  'B',  'C',  'D',  'E',  'F',  'G',   /* 64 - 71 */
  25.          'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',   /* 73 - 79 */
  26.          'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',   /* 80 - 87 */
  27.          'X',  'Y',  'Z', 0xc4, 0xd6, 0xd1, 0xdc, 0xa7,   /* 88 - 95 */
  28.         0xbf,  'a',  'b',  'c',  'd',  'e',  'f',  'g',   /* 96 - 103 */
  29.          'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',   /* 104 - 111 */
  30.          'p',  'q',  'r',  's',  't',  'u',  'v',  'w',   /* 112 - 119 */
  31.          'x',  'y',  'z', 0xe4, 0xf6, 0xf1, 0xfc, 0xe0    /* 120 - 127 */
  32. };
  33. /* This is the extension table defined in GSM 03.38.  It is the mapping
  34.  * used for the character after a GSM 27 (Escape) character.  All characters
  35.  * not in the table, as well as characters we can't represent, will map
  36.  * to themselves.  We cannot represent the euro symbol, which is an escaped
  37.  * 'e', so we left it out of this table. */
  38. static const struct {
  39. int gsmesc;
  40. int latin1;
  41. } gsm_escapes[] = {
  42. {  10, 12 }, /* ASCII page break */
  43. {  20, '^' },
  44. {  40, '{' },
  45. {  41, '}' },
  46. {  47, '\' },
  47. {  60, '[' },
  48. {  61, '~' },
  49. {  62, ']' },
  50. {  64, '|' },
  51. { 101, 128 },
  52. { -1, -1 }
  53. };
  54. /* Code used for non-representable characters */
  55. #define NRP '?'
  56. /* Map ISO-Latin-1 characters to the GSM default alphabet.  Negative
  57.  * encoded as ESC (code 27) followed by the absolute value of the
  58.  * number. */
  59. static const int latin1_to_gsm[256] = {
  60. NRP, NRP, NRP, NRP, NRP, NRP, NRP, NRP,       /* 0 - 7 */
  61. /* TAB approximates to space */
  62. /* LF and CR map to self */
  63. /* Page break maps to escaped LF */
  64. NRP, ' ',  10, NRP, -10,  13, NRP, NRP,       /* 8 - 15 */
  65. /* 16, 18-26 are nonprintable in latin1, and in GSM are greek
  66.  * characters that are unrepresentable in latin1.  So we let them
  67.  * map to self, to create a way to specify them. */
  68.  16, NRP,  18,  19,  20,  21,  22,  23,       /* 16 - 23 */
  69.  24,  25,  26, NRP, NRP, NRP, NRP, NRP,       /* 24 - 31 */
  70. /* $ maps to 2 */
  71. ' ', '!', '"', '#',   2, '%', '&', ''',      /* 32 - 39 */
  72. '(', ')', '*', '+', ',', '-', '.', '/',       /* 40 - 47 */
  73. '0', '1', '2', '3', '4', '5', '6', '7',       /* 48 - 55 */
  74. '8', '9', ':', ';', '<', '=', '>', '?',       /* 56 - 63 */
  75. /* @ maps to 0 */
  76.   0, 'A', 'B', 'C', 'D', 'E', 'F', 'G',       /* 64 - 71 */
  77. 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',       /* 72 - 79 */
  78. 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',       /* 80 - 87 */
  79. /* [ is an escaped < */
  80. /*  is an escaped / */
  81. /* ] is an escaped > */
  82. /* ^ is an escaped Greek Lambda */
  83. /* _ maps to 17 */
  84. 'X', 'Y', 'Z', -60, -47, -62, -20,  17,       /* 88 - 95 */
  85. /* The backquote cannot be represented at all */
  86. NRP, 'a', 'b', 'c', 'd', 'e', 'f', 'g',       /* 96 - 103 */
  87. 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',       /* 104 - 111 */
  88. 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',       /* 112 - 119 */
  89. /* { is an escaped ( */
  90. /* | is an escaped inverted ! */
  91. /* } is an escaped ) */
  92. /* ~ is an escaped = */
  93. 'x', 'y', 'z', -40, -64, -41, -61, NRP,       /* 120 - 127 */
  94. -101, NRP, NRP, NRP, NRP, NRP, NRP, NRP,       /* 128 - 135 */
  95. NRP, NRP, NRP, NRP, NRP, NRP, NRP, NRP,       /* 136 - 143 */
  96. NRP, NRP, NRP, NRP, NRP, NRP, NRP, NRP,       /* 144 - 151 */
  97. NRP, NRP, NRP, NRP, NRP, NRP, NRP, NRP,       /* 152 - 159 */
  98. /* 160 - 167 */
  99. ' ',
  100.  64, /* Inverted ! */
  101. 'c', /* approximation of cent marker */
  102.   1, /* Pounds sterling */
  103.  36, /* International currency symbol */
  104.   3, /* Yen */
  105.  64, /* approximate broken bar as inverted ! */
  106.  95, /* Section marker */
  107. /* 168 - 175 */
  108. '"', /* approximate dieresis */
  109. 'C', /* approximate copyright marker */
  110. 'a', /* approximate ordfeminine */
  111. '<', /* approximate french << */
  112. '!', /* approximate logical not sign */
  113. '-', /* approximate hyphen */
  114. 'R', /* approximate registered marker */
  115. '-', /* approximate macron */
  116. /* 176 - 183 */
  117. 'o', /* approximate degree marker */
  118. NRP, /* plusminus */
  119. '2', /* approximate superscript 2 */
  120. '3', /* approximate superscript 3 */
  121. ''', /* approximate acute accent */
  122. 'u', /* approximate greek mu */
  123. NRP, /* paragraph marker */
  124. '.', /* approximate bullet */
  125. /* 184 - 191 */
  126. ',', /* approximate cedilla */
  127. 'i', /* approximate dotless i */
  128. 'o', /* approximate ordmasculine */
  129. '>', /* approximate french >> */
  130. NRP, /* onequarter */
  131. NRP, /* onehalf */
  132. NRP, /* threequarters */
  133.  96, /* Inverted ? */
  134. /* 192 - 199 */
  135. 'A', /* approximate A grave */
  136. 'A', /* approximate A acute */
  137. 'A', /* approximate A circumflex */
  138. 'A', /* approximate A tilde */
  139.  91, /* A dieresis */
  140.  14, /* A ring */
  141.  28, /* AE ligature */
  142.   9, /* C cedilla */
  143. /* 200 - 207 */
  144. 'E', /* approximate E grave */
  145.  31, /* E acute */
  146. 'E', /* approximate E circumflex */
  147. 'E', /* approximate E dieresis */
  148. 'I', /* approximate I grave */
  149. 'I', /* approximate I acute */
  150. 'I', /* approximate I circumflex */
  151. 'I', /* approximate I dieresis */
  152. /* 208 - 215 */
  153. NRP, /* Eth */
  154.  93, /* N tilde */
  155. 'O', /* approximate O grave */
  156. 'O', /* approximate O acute */
  157. 'O', /* approximate O circumflex */
  158. 'O', /* approximate O tilde */
  159.  92, /* O dieresis */
  160. 'x', /* approximate multiplication sign */
  161. /* 216 - 223 */
  162.  11, /* O slash */
  163. 'U', /* approximate U grave */
  164. 'U', /* approximate U acute */
  165. 'U', /* approximate U circumflex */
  166.  94, /* U dieresis */
  167. 'Y', /* approximate Y acute */
  168. NRP, /* approximate Thorn */
  169.  30, /* german double-s */
  170. /* 224 - 231 */
  171. 127, /* a grave */
  172. 'a', /* approximate a acute */
  173. 'a', /* approximate a circumflex */
  174. 'a', /* approximate a tilde */
  175. 123, /* a dieresis */
  176.  15, /* a ring */
  177.  29, /* ae ligature */
  178. 'c', /* approximate c cedilla as c */
  179. /* 232 - 239 */
  180.   4, /* e grave */
  181.   5, /* e acute */
  182. 'e', /* approximate e circumflex */
  183. 'e', /* approximate e dieresis */
  184.   7, /* i grave */
  185. 'i', /* approximate i acute */
  186. 'i', /* approximate i circumflex */
  187. 'i', /* approximate i dieresis */
  188. /* 240 - 247 */
  189. NRP, /* eth */
  190. 125, /* n tilde */
  191.   8, /* o grave */
  192. 'o', /* approximate o acute */
  193. 'o', /* approximate o circumflex */
  194. 'o', /* approximate o tilde */
  195. 124, /* o dieresis */
  196. NRP, /* division sign */
  197. /* 248 - 255 */
  198.  12, /* o slash */
  199.   6, /* u grave */
  200. 'u', /* approximate u acute */
  201. 'u', /* approximate u circumflex */
  202. 126, /* u dieresis */
  203. 'y', /* approximate y acute */
  204. NRP, /* thorn */
  205. 'y', /* approximate y dieresis */
  206. };
  207. /*
  208.  * Register alises for Windows character sets that the libxml/libiconv can 
  209.  * recoqnise them.
  210.  */
  211. struct alias_t {
  212.     char *real;
  213.     char *alias;
  214. }; 
  215. typedef struct alias_t alias_t;
  216. alias_t chars_aliases[] = {
  217.     { "CP1250", "WIN-1250" }, 
  218.     { "CP1250", "WINDOWS-1250" },
  219.     { "CP1251", "WIN-1251" }, 
  220.     { "CP1251", "WINDOWS-1251" },
  221.     { "CP1252", "WIN-1252" }, 
  222.     { "CP1252", "WINDOWS-1252" },
  223.     { "CP1253", "WIN-1253" }, 
  224.     { "CP1253", "WINDOWS-1253" },
  225.     { "CP1254", "WIN-1254" }, 
  226.     { "CP1254", "WINDOWS-1254" },
  227.     { "CP1257", "WIN-1257" },
  228.     { "CP1257", "WINDOWS-1257" },
  229.     { NULL }
  230. };
  231. void charset_init()
  232. {
  233.     int i;
  234.     for (i = 0; chars_aliases[i].real != NULL; i++) {
  235.       xmlAddEncodingAlias(chars_aliases[i].real,chars_aliases[i].alias);
  236.       /*debug("encoding",0,"Add encoding for %s",chars_aliases[i].alias);*/
  237.     }
  238. }
  239. void charset_shutdown()
  240. {
  241.     xmlCleanupEncodingAliases();
  242. }
  243. void charset_gsm_to_latin1(Octstr *ostr)
  244. {
  245.     long pos, len;
  246.     len = octstr_len(ostr);
  247.     for (pos = 0; pos < len; pos++) {
  248. int c, new, i;
  249. c = octstr_get_char(ostr, pos);
  250. if (c == 27 && pos + 1 < len) {
  251.     /* GSM escape code.  Delete it, then process the next
  252.              * character specially. */
  253.     octstr_delete(ostr, pos, 1);
  254.     len--;
  255.     c = octstr_get_char(ostr, pos);
  256.     for (i = 0; gsm_escapes[i].gsmesc >= 0; i++) {
  257. if (gsm_escapes[i].gsmesc == c)
  258.        break;
  259.     }
  260.     if (gsm_escapes[i].gsmesc == c)
  261. new = gsm_escapes[i].latin1;
  262.     else if (c < 128)
  263. new = gsm_to_latin1[c];
  264.     else
  265. continue;
  266. } else if (c < 128) {
  267.             new = gsm_to_latin1[c];
  268. } else {
  269.     continue;
  270. }
  271. if (new != c)
  272.     octstr_set_char(ostr, pos, new);
  273.     }
  274. }
  275. void charset_latin1_to_gsm(Octstr *ostr)
  276. {
  277.     long pos, len;
  278.     int c, new;
  279.     unsigned char esc = 27;
  280.     len = octstr_len(ostr);
  281.     for (pos = 0; pos < len; pos++) {
  282. c = octstr_get_char(ostr, pos);
  283. gw_assert(c >= 0);
  284. gw_assert(c <= 256);
  285. new = latin1_to_gsm[c];
  286. if (new < 0) {
  287.          /* Escaped GSM code */
  288.     octstr_insert_data(ostr, pos, &esc, 1);
  289.     pos++;
  290.     len++;
  291.     new = -new;
  292. }
  293. if (new != c)
  294.     octstr_set_char(ostr, pos, new);
  295.     }
  296. }
  297. int charset_gsm_truncate(Octstr *gsm, long max)
  298. {
  299.     if (octstr_len(gsm) > max) {
  300. /* If the last GSM character was an escaped character,
  301.  * then chop off the escape as well as the character. */
  302. if (octstr_get_char(gsm, max - 1) == 27)
  303.        octstr_truncate(gsm, max - 1);
  304. else
  305.     octstr_truncate(gsm, max);
  306. return 1;
  307.     }
  308.     return 0;
  309. }
  310. int charset_to_utf8(Octstr *from, Octstr **to, Octstr *charset_from)
  311. {
  312.     int ret;
  313.     xmlCharEncodingHandlerPtr handler = NULL;
  314.     xmlBufferPtr frombuffer = NULL;
  315.     xmlBufferPtr tobuffer = NULL;
  316.     if (octstr_compare(charset_from, octstr_imm("UTF-8")) == 0) {
  317.         *to = octstr_duplicate(from);
  318.         return 0;
  319.     }
  320.     handler = xmlFindCharEncodingHandler(octstr_get_cstr(charset_from));
  321.     if (handler == NULL)
  322. return -2;
  323.     /* Build the libxml buffers for the transcoding. */
  324.     tobuffer = xmlBufferCreate();
  325.     frombuffer = xmlBufferCreate();
  326.     xmlBufferAdd(frombuffer, octstr_get_cstr(from), octstr_len(from));
  327.     ret = xmlCharEncInFunc(handler, tobuffer, frombuffer);
  328.     *to = octstr_create_from_data(tobuffer->content, tobuffer->use);
  329.     /* Memory cleanup. */
  330.     xmlBufferFree(tobuffer);
  331.     xmlBufferFree(frombuffer);
  332.     return ret;
  333. }
  334. int charset_from_utf8(Octstr *utf8, Octstr **to, Octstr *charset_to)
  335. {
  336.     int ret;
  337.     xmlCharEncodingHandlerPtr handler = NULL;
  338.     xmlBufferPtr frombuffer = NULL;
  339.     xmlBufferPtr tobuffer = NULL;
  340.     handler = xmlFindCharEncodingHandler(octstr_get_cstr(charset_to));
  341.     if (handler == NULL)
  342. return -2;
  343.     /* Build the libxml buffers for the transcoding. */
  344.     tobuffer = xmlBufferCreate();
  345.     frombuffer = xmlBufferCreate();
  346.     xmlBufferAdd(frombuffer, octstr_get_cstr(utf8), octstr_len(utf8));
  347.     ret = xmlCharEncOutFunc(handler, tobuffer, frombuffer);
  348.     if (ret < -2)
  349. /* Libxml seems to be here a little uncertain what would be the 
  350.  * return code -3, so let's make it -1. Ugly thing, indeed. --tuo */
  351. ret = -1; 
  352.     *to = octstr_create_from_data(tobuffer->content, tobuffer->use);
  353.     /* Memory cleanup. */
  354.     xmlBufferFree(tobuffer);
  355.     xmlBufferFree(frombuffer);
  356.     return ret;
  357. }