首页 | 数据结构 | 文件列表 | 数据字段 | 全局定义

char_conv.c

浏览该文件的文档。
00001 
00023 // START OF FILE
00024 /*****************************************************************************/
00025 #include "debug.h"              // gaim_debug
00026 #include "internal.h"           // strlen
00027 //      #include <regex.h>
00028 
00029 #include "utils.h"              // hex_dump_to_str
00030 #include "packet_parse.h"       // read_packet
00031 #include "char_conv.h"
00032 #include "qq.h"                 // QQ_CHARSET_DEFAULT
00033 
00034 #define QQ_SMILEY_AMOUNT      96
00035 
00036 #define UTF8                  "UTF-8"
00037 #define QQ_CHARSET_ZH_CN      "GBK"
00038 #define QQ_CHARSET_ENG        "ISO-8859-1"
00039 
00040 #define QQ_NULL_MSG           "(NULL)"  // return this if conversion fail
00041 #define QQ_NULL_SMILEY        "(SM)"    // return this if smiley conversion fails
00042 
00043 // a debug function
00044 void _qq_show_packet(gchar * desc, gchar * buf, gint len);
00045 
00046 const gchar qq_smiley_map[QQ_SMILEY_AMOUNT] = {
00047         0x41, 0x43, 0x42, 0x44, 0x45, 0x46, 0x47, 0x48,
00048         0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x73,
00049         0x74, 0x75, 0x76, 0x77, 0x8a, 0x8b, 0x8c, 0x8d,
00050         0x8e, 0x8f, 0x78, 0x79, 0x7a, 0x7b, 0x90, 0x91,
00051         0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
00052         0x59, 0x5a, 0x5c, 0x58, 0x57, 0x55, 0x7c, 0x7d,
00053         0x7e, 0x7f, 0x9a, 0x9b, 0x60, 0x67, 0x9c, 0x9d,
00054         0x9e, 0x5e, 0x9f, 0x89, 0x80, 0x81, 0x82, 0x62,
00055         0x63, 0x64, 0x65, 0x66, 0x83, 0x68, 0x84, 0x85,
00056         0x86, 0x87, 0x6b, 0x6e, 0x6f, 0x70, 0x88, 0xa0,
00057         0x50, 0x51, 0x52, 0x53, 0x54, 0x56, 0x5b, 0x5d,
00058         0x5f, 0x61, 0x69, 0x6a, 0x6c, 0x6d, 0x71, 0x72,
00059 };
00060 
00061 const gchar *gaim_smiley_map[QQ_SMILEY_AMOUNT] = {
00062         "\\jy", "\\pz", "\\se", "\\fd", "\\dy", "\\ll", "\\hx", "\\bz",
00063         "\\shui", "\\dk ", "\\gg", "\\fn", "\\tp", "\\cy", "\\wx", "\\ng",
00064         "\\kuk", "\\feid", "\\zk", "\\tu", "\\tx", "\\ka", "\\by", "\\am",
00065         "\\jie", "\\kun", "\\jk", "\\lh", "\\hanx", "\\db", "\\fendou",
00066         "\\zhm",
00067         "\\yiw", "\\xu", "\\yun", "\\zhem", "\\shuai", "\\kl", "\\qiao",
00068         "\\zj",
00069         "\\shan", "\\fad", "\\aiq", "\\tiao", "\\zhao", "\\mm", "\\zt",
00070         "\\maom",
00071         "\\xg", "\\yb", "\\qianc", "\\dp", "\\bei", "\\dg", "\\shd",
00072         "\\zhd",
00073         "\\dao", "\\zq", "\\yy", "\\bb", "\\gf", "\\fan", "\\yw", "\\mg",
00074         "\\dx", "\\wen", "\\xin", "\\xs", "\\hy", "\\lw", "\\dh", "\\sj",
00075         "\\yj", "\\ds", "\\ty", "\\yl", "\\qiang", "\\ruo", "\\ws",
00076         "\\shl",
00077         "\\dd", "\\mn", "\\hl", "\\mamao", "\\qz", "\\fw", "\\oh", "\\bj",
00078         "\\qsh", "\\xig", "\\xy", "\\duoy", "\\xr", "\\xixing", "\\nv",
00079         "\\nan"
00080 };
00081 
00082 /*****************************************************************************/
00083 // these functions parses font-attr
00084 gchar _get_size(gchar font_attr)
00085 {
00086         return font_attr & 0x1f;
00087 }
00088 
00089 gboolean _check_bold(gchar font_attr)
00090 {
00091         return (font_attr & 0x20) ? TRUE : FALSE;
00092 }
00093 
00094 gboolean _check_italic(gchar font_attr)
00095 {
00096         return (font_attr & 0x40) ? TRUE : FALSE;
00097 }
00098 
00099 gboolean _check_underline(gchar font_attr)
00100 {
00101         return (font_attr & 0x80) ? TRUE : FALSE;
00102 }
00103 
00104 /*****************************************************************************/
00105 // convert a string from from_charset to to_charset, using g_convert
00106 gchar *_my_convert(const gchar * str, gssize len, const gchar * to_charset, const gchar * from_charset) {
00107 
00108         GError *error = NULL;
00109         gchar *ret;
00110         gsize byte_read, byte_write;
00111 
00112         g_return_val_if_fail(str != NULL && to_charset != NULL && from_charset != NULL, g_strdup(QQ_NULL_MSG));
00113 
00114         ret = g_convert(str, len, to_charset, from_charset, &byte_read, &byte_write, &error);
00115 
00116         if (error == NULL)
00117                 return ret;     // conversion is OK
00118         else {                  // conversion error
00119                 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "%s\n", error->message);
00120                 gaim_debug(GAIM_DEBUG_WARNING, "QQ",
00121                            "Dump failed text\n%s", hex_dump_to_str(str, (len == -1) ? strlen(str) : len));
00122                 g_error_free(error);
00123                 return g_strdup(QQ_NULL_MSG);
00124         }                       // if error
00125 }                               // _my_convert
00126 
00127 /*****************************************************************************/
00128 // take the input as a pascal string and return a converted c-string in UTF-8
00129 // returns the number of bytes read, return -1 if fatal error
00130 // the converted UTF-8 will be save in ret, 
00131 gint convert_as_pascal_string(guint8 * data, gchar ** ret, const gchar * from_charset) {
00132 
00133         guint8 len;
00134 
00135         g_return_val_if_fail(data != NULL && from_charset != NULL, -1);
00136 
00137         len = data[0];
00138         *ret = _my_convert(data + 1, (gssize) len, UTF8, from_charset);
00139 
00140         return len + 1;
00141 }                               // convert_as_pascal_string
00142 
00143 /*****************************************************************************/
00144 // convert QQ formatted msg to GAIM formatted msg (and UTF-8)
00145 gchar *qq_encode_to_gaim(guint8 * data, gint len, const gchar * msg)
00146 {
00147         GString *encoded;
00148         guint8 font_attr, font_size, color[3], bar, *cursor;
00149         gboolean is_bold, is_italic, is_underline;
00150         guint16 charset_code;
00151         gchar *font_name, *color_code, *msg_utf8, *ret;
00152 
00153         cursor = data;
00154         _qq_show_packet("QQ_MESG recv", data, len);
00155 
00156         read_packet_b(data, &cursor, len, &font_attr);
00157         read_packet_data(data, &cursor, len, color, 3); // red,green,blue
00158         color_code = g_strdup_printf("#%02x%02x%02x", color[0], color[1], color[2]);
00159 
00160         read_packet_b(data, &cursor, len, &bar);        // skip, not sure of its use
00161         read_packet_w(data, &cursor, len, &charset_code);
00162 
00163         font_name = g_strndup(cursor, data + len - cursor);
00164 
00165         font_size = _get_size(font_attr);
00166         is_bold = _check_bold(font_attr);
00167         is_italic = _check_italic(font_attr);
00168         is_underline = _check_underline(font_attr);
00169 
00170         // although there is charset returned from QQ msg, it is can not be used
00171         // for example, if a user send a Chinese message from English windows
00172         // the charset_code in QQ msg is 0x0000, not 0x8602
00173         // therefore, it is better to use uniform conversion.
00174         // by default, we use GBK, which includes all character of SC, TC, and EN
00175         msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT);
00176         encoded = g_string_new("");
00177 
00178         // Henry: The range QQ sends rounds from 8 to 22, where a font size
00179         // of 10 is equal to 3 in html font tag
00180         g_string_append_printf(encoded,
00181                                "<font color=\"%s\"><font face=\"%s\"><font size=\"%d\">",
00182                                color_code, font_name, font_size / 3);
00183         gaim_debug(GAIM_DEBUG_INFO, "QQ_MESG",
00184                    "recv <font color=\"%s\"><font face=\"%s\"><font size=\"%d\">\n",
00185                    color_code, font_name, font_size / 3);
00186         g_string_append(encoded, msg_utf8);
00187 
00188         if (is_bold) {
00189                 g_string_prepend(encoded, "<b>");
00190                 g_string_append(encoded, "</b>");
00191         }
00192         if (is_italic) {
00193                 g_string_prepend(encoded, "<i>");
00194                 g_string_append(encoded, "</i>");
00195         }
00196         if (is_underline) {
00197                 g_string_prepend(encoded, "<u>");
00198                 g_string_append(encoded, "</u>");
00199         }
00200 
00201         g_string_append(encoded, "</font></font></font>");
00202         ret = encoded->str;
00203 
00204         g_free(msg_utf8);
00205         g_free(font_name);
00206         g_free(color_code);
00207         g_string_free(encoded, FALSE);
00208 
00209         return ret;
00210 }                               // qq_encode_to_gaim
00211 
00212 /*****************************************************************************/
00213 // two convenient methods, using _my_convert
00214 gchar *utf8_to_qq(const gchar * str, const gchar * to_charset)
00215 {
00216         return _my_convert(str, -1, to_charset, UTF8);
00217 }                               // utf8_to_qq
00218 
00219 gchar *qq_to_utf8(const gchar * str, const gchar * from_charset)
00220 {
00221         return _my_convert(str, -1, UTF8, from_charset);
00222 }                               // qq_to_utf8
00223 
00224 /*****************************************************************************/
00225 // QQ uses binary code for smiley, while gaim uses strings. 
00226 // there is a mapping relations between these two.
00227 gchar *qq_smiley_to_gaim(gchar * text)
00228 {
00229         gint index;
00230         gchar qq_smiley, *cur_seg, **segments, *ret;
00231         GString *converted;
00232 
00233         converted = g_string_new("");
00234         segments = split_data(text, strlen(text), "\x14", 0);
00235         g_string_append(converted, segments[0]);
00236 
00237         while ((*(++segments)) != NULL) {
00238                 cur_seg = *segments;
00239                 qq_smiley = cur_seg[0];
00240                 for (index = 0; index < QQ_SMILEY_AMOUNT; index++)
00241                         if (qq_smiley_map[index] == qq_smiley)
00242                                 break;
00243                 if (index >= QQ_SMILEY_AMOUNT)
00244                         g_string_append(converted, QQ_NULL_SMILEY);
00245                 else {
00246                         g_string_append(converted, gaim_smiley_map[index]);
00247                         g_string_append(converted, (cur_seg + 1));
00248                 }               // if index
00249         }                       // while
00250 
00251         ret = converted->str;
00252         g_string_free(converted, FALSE);
00253         return ret;
00254 }                               // qq_smiley_to_gaim
00255 
00256 /*****************************************************************************/
00257 // convert smiley from gaim style to qq binary code
00258 gchar *gaim_smiley_to_qq(gchar * text)
00259 {
00260         gchar *begin, *cursor, *ret;
00261         gint index;
00262         GString *converted;
00263 
00264         converted = g_string_new(text);
00265 
00266         for (index = 0; index < QQ_SMILEY_AMOUNT; index++) {
00267                 begin = cursor = converted->str;
00268                 while ((cursor = g_strstr_len(cursor, -1, gaim_smiley_map[index]))) {
00269                         g_string_erase(converted, (cursor - begin), strlen(gaim_smiley_map[index]));
00270                         g_string_insert_c(converted, (cursor - begin), 0x14);
00271                         g_string_insert_c(converted, (cursor - begin + 1), qq_smiley_map[index]);
00272                         cursor++;
00273                 }               // while
00274         }                       // for
00275         g_string_append_c(converted, 0x20);     // important for last smiiley
00276 
00277         ret = converted->str;
00278         g_string_free(converted, FALSE);
00279         return ret;
00280 }                               // gaim_smiley_to_qq
00281 
00282 /*****************************************************************************/
00283 // END OF FILE

Generated at Mon May 8 15:41:23 2006 for OpenQ by  doxygen 1.4.4