00001
00023
00024
00025 #include "debug.h"
00026 #include "internal.h"
00027
00028
00029 #include "utils.h"
00030 #include "packet_parse.h"
00031 #include "char_conv.h"
00032 #include "qq.h"
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
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
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
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;
00118 else {
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 }
00125 }
00126
00127
00128
00129
00130
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 }
00142
00143
00144
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);
00158 color_code = g_strdup_printf("#%02x%02x%02x", color[0], color[1], color[2]);
00159
00160 read_packet_b(data, &cursor, len, &bar);
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
00171
00172
00173
00174
00175 msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT);
00176 encoded = g_string_new("");
00177
00178
00179
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 }
00211
00212
00213
00214 gchar *utf8_to_qq(const gchar * str, const gchar * to_charset)
00215 {
00216 return _my_convert(str, -1, to_charset, UTF8);
00217 }
00218
00219 gchar *qq_to_utf8(const gchar * str, const gchar * from_charset)
00220 {
00221 return _my_convert(str, -1, UTF8, from_charset);
00222 }
00223
00224
00225
00226
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 }
00249 }
00250
00251 ret = converted->str;
00252 g_string_free(converted, FALSE);
00253 return ret;
00254 }
00255
00256
00257
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 }
00274 }
00275 g_string_append_c(converted, 0x20);
00276
00277 ret = converted->str;
00278 g_string_free(converted, FALSE);
00279 return ret;
00280 }
00281
00282
00283