# HG changeset patch # User Hu Yong # Date 1226387234 0 # Node ID 6607ebd410534fae7b92973ab93526c5a25c17fb # Parent 45772d1c579aa8bd045b480a16a0ca6c398b890b Change Qun number to unsigned long Use new smiley function Use new im_format Support long IM message diff -r 45772d1c579a -r 6607ebd41053 libpurple/protocols/qq/group_im.c --- a/libpurple/protocols/qq/group_im.c Tue Nov 11 07:04:04 2008 +0000 +++ b/libpurple/protocols/qq/group_im.c Tue Nov 11 07:07:14 2008 +0000 @@ -64,7 +64,11 @@ serv_got_joined_chat(gc, rmd->id, rmd->title_utf8); conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, rmd->title_utf8, purple_connection_get_account(gc)); if (conv != NULL) { - topic_utf8 = g_strdup_printf("%d %s", rmd->ext_id, rmd->notice_utf8); + if (rmd->notice_utf8 != NULL) { + topic_utf8 = g_strdup_printf("%u %s", rmd->ext_id, rmd->notice_utf8); + } else { + topic_utf8 = g_strdup_printf("%u", rmd->ext_id); + } purple_debug_info("QQ", "Set chat topic to %s\n", topic_utf8); purple_conv_chat_set_topic(PURPLE_CONV_CHAT(conv), NULL, topic_utf8); g_free(topic_utf8); @@ -157,48 +161,6 @@ g_list_free(flags); } -/* send IM to a group */ -void qq_request_room_send_im(PurpleConnection *gc, guint32 room_id, const gchar *msg) -{ - gint data_len, bytes; - guint8 *raw_data, *send_im_tail; - guint16 msg_len; - gchar *msg_filtered; - - g_return_if_fail(room_id != 0 && msg != NULL); - - msg_filtered = purple_markup_strip_html(msg); - /* purple_debug_info("QQ", "Send qun mesg filterd: %s\n", msg_filtered); */ - msg_len = strlen(msg_filtered); - - data_len = 2 + msg_len + QQ_SEND_IM_AFTER_MSG_LEN; - raw_data = g_newa(guint8, data_len); - - bytes = 0; - bytes += qq_put16(raw_data + bytes, msg_len + QQ_SEND_IM_AFTER_MSG_LEN); - bytes += qq_putdata(raw_data + bytes, (guint8 *) msg_filtered, msg_len); - send_im_tail = qq_get_send_im_tail(NULL, NULL, NULL, - FALSE, FALSE, FALSE, - QQ_SEND_IM_AFTER_MSG_LEN); - bytes += qq_putdata(raw_data + bytes, send_im_tail, QQ_SEND_IM_AFTER_MSG_LEN); - g_free(send_im_tail); - g_free(msg_filtered); - - if (bytes == data_len) /* create OK */ - qq_send_room_cmd(gc, QQ_ROOM_CMD_SEND_MSG, room_id, raw_data, data_len); - else - purple_debug_error("QQ", - "Fail creating group_im packet, expect %d bytes, build %d bytes\n", data_len, bytes); -} - -/* this is the ACK */ -void qq_process_room_send_im(PurpleConnection *gc, guint8 *data, gint len) -{ - /* return should be the internal group id - * but we have nothing to do with it */ - return; -} - void qq_room_got_chat_in(PurpleConnection *gc, guint32 room_id, guint32 uid_from, const gchar *msg, time_t in_time) { @@ -208,6 +170,7 @@ gchar *from; g_return_if_fail(gc != NULL && room_id != 0); + g_return_if_fail(msg != NULL); conv = purple_find_chat(gc, room_id); rmd = qq_room_data_find(gc, room_id); @@ -218,7 +181,7 @@ } if (conv == NULL) { - purple_debug_info("QQ", "Conversion of %d is not open, missing from %d:/n%s/v", + purple_debug_info("QQ", "Conversion of %u is not open, missing from %d:/n%s/v", room_id, uid_from, msg); return; } @@ -227,7 +190,7 @@ bd = qq_room_buddy_find(rmd, uid_from); if (bd == NULL || bd->nickname == NULL) - from = g_strdup_printf("%d", uid_from); + from = g_strdup_printf("%u", uid_from); else from = g_strdup(bd->nickname); } else { @@ -240,8 +203,8 @@ /* recv an IM from a group chat */ void qq_process_room_im(guint8 *data, gint data_len, guint32 id, PurpleConnection *gc, guint16 msg_type) { - gchar *msg_with_purple_smiley, *msg_utf8_encoded; qq_data *qd; + gchar *msg_smiley, *msg_fmt, *msg_utf8; gint skip_len; gint bytes ; struct { @@ -256,7 +219,7 @@ gchar *msg; guint8 *font_attr; gint font_attr_len; - } packet; + } im_text; g_return_if_fail(data != NULL && data_len > 0); @@ -266,20 +229,20 @@ /* qq_show_packet("ROOM_IM", data, data_len); */ - memset(&packet, 0, sizeof(packet)); + memset(&im_text, 0, sizeof(im_text)); bytes = 0; - bytes += qq_get32(&(packet.ext_id), data + bytes); - bytes += qq_get8(&(packet.type8), data + bytes); + bytes += qq_get32(&(im_text.ext_id), data + bytes); + bytes += qq_get8(&(im_text.type8), data + bytes); if(QQ_MSG_TEMP_QUN_IM == msg_type) { bytes += qq_get32(&(id), data + bytes); } - bytes += qq_get32(&(packet.member_uid), bytes + data); - bytes += qq_get16(&packet.unknown, data + bytes); /* 0x0001? */ - bytes += qq_get16(&(packet.msg_seq), data + bytes); - bytes += qq_getime(&packet.send_time, data + bytes); - bytes += qq_get32(&packet.unknown4, data + bytes); /* versionID */ + bytes += qq_get32(&(im_text.member_uid), bytes + data); + bytes += qq_get16(&im_text.unknown, data + bytes); /* 0x0001? */ + bytes += qq_get16(&(im_text.msg_seq), data + bytes); + bytes += qq_getime(&im_text.send_time, data + bytes); + bytes += qq_get32(&im_text.unknown4, data + bytes); /* versionID */ /* * length includes font_attr * this msg_len includes msg and font_attr @@ -290,8 +253,8 @@ * 3. font_attr */ - bytes += qq_get16(&(packet.msg_len), data + bytes); - g_return_if_fail(packet.msg_len > 0); + bytes += qq_get16(&(im_text.msg_len), data + bytes); + g_return_if_fail(im_text.msg_len > 0); /* * 10 bytes from lumaqq * contentType = buf.getChar(); @@ -309,29 +272,120 @@ /* qq_show_packet("Message", data + bytes, data_len - bytes); */ - packet.msg = g_strdup((gchar *) data + bytes); - bytes += strlen(packet.msg) + 1; + im_text.msg = g_strdup((gchar *) data + bytes); + bytes += strlen(im_text.msg) + 1; /* there might not be any font_attr, check it */ - packet.font_attr_len = data_len - bytes; - if (packet.font_attr_len > 0) { - packet.font_attr = g_memdup(data + bytes, packet.font_attr_len); + im_text.font_attr_len = data_len - bytes; + if (im_text.font_attr_len > 0) { + im_text.font_attr = g_memdup(data + bytes, im_text.font_attr_len); /* qq_show_packet("font_attr", packet.font_attr, packet.font_attr_len); */ } else { - packet.font_attr = NULL; + im_text.font_attr = NULL; } /* group im_group has no flag to indicate whether it has font_attr or not */ - msg_with_purple_smiley = qq_smiley_to_purple(packet.msg); - if (packet.font_attr_len > 0) { - msg_utf8_encoded = qq_encode_to_purple(packet.font_attr, - packet.font_attr_len, msg_with_purple_smiley, qd->client_version); + msg_smiley = qq_emoticon_to_purple(im_text.msg); + if (im_text.font_attr != NULL) { + msg_fmt = qq_format_to_purple(im_text.font_attr, im_text.font_attr_len, + msg_smiley); + msg_utf8 = qq_to_utf8(msg_fmt, QQ_CHARSET_DEFAULT); + g_free(msg_fmt); } else { - msg_utf8_encoded = qq_to_utf8(msg_with_purple_smiley, QQ_CHARSET_DEFAULT); + msg_utf8 = qq_to_utf8(msg_smiley, QQ_CHARSET_DEFAULT); } - qq_room_got_chat_in(gc, id, packet.member_uid, msg_utf8_encoded, packet.send_time); + g_free(msg_smiley); + + + qq_room_got_chat_in(gc, id, im_text.member_uid, msg_utf8, im_text.send_time); + + g_free(msg_utf8); + g_free(im_text.msg); + if (im_text.font_attr) g_free(im_text.font_attr); +} + +/* send IM to a group */ +static void request_room_send_im(PurpleConnection *gc, guint32 room_id, qq_im_format *fmt, const gchar *msg) +{ + guint8 raw_data[MAX_PACKET_SIZE - 16]; + gint bytes; + + g_return_if_fail(room_id != 0 && msg != NULL); + + bytes = 0; + bytes += qq_put16(raw_data + bytes, 0); + bytes += qq_putdata(raw_data + bytes, (guint8 *)msg, strlen(msg)); + bytes += qq_put8(raw_data + bytes, 0); + bytes += qq_put_im_tail(raw_data + bytes, fmt); + + /* reset first two bytes */ + qq_put16(raw_data, bytes - 2); + + qq_send_room_cmd(gc, QQ_ROOM_CMD_SEND_MSG, room_id, raw_data, bytes); +} + +/* this is the ACK */ +void qq_process_room_send_im(PurpleConnection *gc, guint8 *data, gint len) +{ + /* return should be the internal group id + * but we have nothing to do with it */ + return; +} - g_free(msg_with_purple_smiley); - g_free(msg_utf8_encoded); - g_free(packet.msg); - g_free(packet.font_attr); +/* send a chat msg to a QQ Qun + * called by purple */ +int qq_chat_send(PurpleConnection *gc, int id, const char *what, PurpleMessageFlags flags) +{ + qq_data *qd; + qq_im_format *fmt; + gchar *msg_stripped, *tmp; + GSList *segments, *it; + gint msg_len; + const gchar *start_invalid; + gboolean is_smiley_none; + + g_return_val_if_fail(NULL != gc && NULL != gc->proto_data, -1); + g_return_val_if_fail(id != 0 && what != NULL, -1); + + qd = (qq_data *) gc->proto_data; + purple_debug_info("QQ", "Send chat IM to %u, len %d:\n%s\n", id, strlen(what), what); + + /* qq_show_packet("chat IM UTF8", (guint8 *)what, strlen(what)); */ + + fmt = qq_im_fmt_new_by_purple(what); + is_smiley_none = qq_im_smiley_none(what); + + msg_stripped = purple_markup_strip_html(what); + g_return_val_if_fail(msg_stripped != NULL, -1); + /* qq_show_packet("IM Stripped", (guint8 *)what, strlen(what)); */ + + /* Check and valid utf8 string */ + msg_len = strlen(msg_stripped); + if (!g_utf8_validate(msg_stripped, msg_len, &start_invalid)) { + if (start_invalid > msg_stripped) { + tmp = g_strndup(msg_stripped, start_invalid - msg_stripped); + g_free(msg_stripped); + msg_stripped = g_strconcat(tmp, _("(Invalid UTF-8 string)"), NULL); + g_free(tmp); + } else { + g_free(msg_stripped); + msg_stripped = g_strdup(_("(Invalid UTF-8 string)")); + } + } + + is_smiley_none = qq_im_smiley_none(what); + segments = qq_im_get_segments(msg_stripped, is_smiley_none); + g_free(msg_stripped); + + if (segments == NULL) { + return -1; + } + + fmt = qq_im_fmt_new_by_purple(what); + for (it = segments; it; it = it->next) { + request_room_send_im(gc, id, fmt, (gchar *)it->data); + g_free(it->data); + } + qq_im_fmt_free(fmt); + g_slist_free(segments); + return 1; }