Mercurial > pidgin
comparison libpurple/protocols/qq/group_im.c @ 24640:2cfdcaf6b5f3
Support long qun im
author | Hu Yong <ccpaging@gmail.com> |
---|---|
date | Wed, 19 Nov 2008 08:31:45 +0000 |
parents | 2df8b8f3c3f6 |
children | 2df1d0449ba6 |
comparison
equal
deleted
inserted
replaced
24639:9f2149adcac2 | 24640:2cfdcaf6b5f3 |
---|---|
203 /* recv an IM from a group chat */ | 203 /* recv an IM from a group chat */ |
204 void qq_process_room_im(guint8 *data, gint data_len, guint32 id, PurpleConnection *gc, guint16 msg_type) | 204 void qq_process_room_im(guint8 *data, gint data_len, guint32 id, PurpleConnection *gc, guint16 msg_type) |
205 { | 205 { |
206 qq_data *qd; | 206 qq_data *qd; |
207 gchar *msg_smiley, *msg_fmt, *msg_utf8; | 207 gchar *msg_smiley, *msg_fmt, *msg_utf8; |
208 gint skip_len; | 208 gint bytes, tail_len; |
209 gint bytes ; | |
210 struct { | 209 struct { |
211 guint32 ext_id; | 210 guint32 ext_id; |
212 guint8 type8; | 211 guint8 type8; |
213 guint32 member_uid; | 212 guint32 member_uid; |
214 guint16 unknown; | 213 guint16 unknown; |
215 guint16 msg_seq; | 214 guint16 msg_seq; |
216 time_t send_time; | 215 time_t send_time; |
217 guint32 unknown4; | 216 guint32 version; |
218 guint16 msg_len; | 217 guint16 msg_len; |
219 gchar *msg; | 218 gchar *msg; |
220 guint8 *font_attr; | |
221 gint font_attr_len; | |
222 } im_text; | 219 } im_text; |
223 | 220 guint32 temp_id; |
224 g_return_if_fail(data != NULL && data_len > 0); | 221 guint16 content_type; |
225 | 222 guint8 frag_count, frag_index; |
226 /* FIXME: check length here */ | 223 guint16 msg_id; |
227 | 224 qq_im_format *fmt = NULL; |
225 | |
226 /* at least include im_text.msg_len */ | |
227 g_return_if_fail(data != NULL && data_len > 23); | |
228 qd = (qq_data *) gc->proto_data; | 228 qd = (qq_data *) gc->proto_data; |
229 | 229 |
230 /* qq_show_packet("ROOM_IM", data, data_len); */ | 230 /* qq_show_packet("ROOM_IM", data, data_len); */ |
231 | |
232 memset(&im_text, 0, sizeof(im_text)); | 231 memset(&im_text, 0, sizeof(im_text)); |
233 bytes = 0; | 232 bytes = 0; |
234 bytes += qq_get32(&(im_text.ext_id), data + bytes); | 233 bytes += qq_get32(&(im_text.ext_id), data + bytes); |
235 bytes += qq_get8(&(im_text.type8), data + bytes); | 234 bytes += qq_get8(&(im_text.type8), data + bytes); |
236 | 235 |
237 if(QQ_MSG_TEMP_QUN_IM == msg_type) { | 236 if(QQ_MSG_TEMP_QUN_IM == msg_type) { |
238 bytes += qq_get32(&(id), data + bytes); | 237 bytes += qq_get32(&temp_id, data + bytes); |
239 } | 238 } |
240 | 239 |
241 bytes += qq_get32(&(im_text.member_uid), bytes + data); | 240 bytes += qq_get32(&(im_text.member_uid), bytes + data); |
242 bytes += qq_get16(&im_text.unknown, data + bytes); /* 0x0001? */ | 241 bytes += qq_get16(&im_text.unknown, data + bytes); /* 0x0001? */ |
243 bytes += qq_get16(&(im_text.msg_seq), data + bytes); | 242 bytes += qq_get16(&(im_text.msg_seq), data + bytes); |
244 bytes += qq_getime(&im_text.send_time, data + bytes); | 243 bytes += qq_getime(&im_text.send_time, data + bytes); |
245 bytes += qq_get32(&im_text.unknown4, data + bytes); /* versionID */ | 244 bytes += qq_get32(&im_text.version, data + bytes); |
246 /* | |
247 * length includes font_attr | |
248 * this msg_len includes msg and font_attr | |
249 **** the format is **** | |
250 * length of all | |
251 * 1. unknown 10 bytes | |
252 * 2. 0-ended string | |
253 * 3. font_attr | |
254 */ | |
255 | |
256 bytes += qq_get16(&(im_text.msg_len), data + bytes); | 245 bytes += qq_get16(&(im_text.msg_len), data + bytes); |
246 purple_debug_info("QQ", "Room IM, ext id %u, seq %u, version 0x%04X, len %u\n", | |
247 im_text.ext_id, im_text.msg_seq, im_text.version, im_text.msg_len); | |
248 | |
249 if (im_text.msg_len != data_len - bytes) { | |
250 purple_debug_warning("QQ", "Room IM length %d should be %d\n", | |
251 im_text.msg_len, data_len - bytes); | |
252 im_text.msg_len = data_len - bytes; | |
253 } | |
254 | |
255 g_return_if_fail(im_text.msg_len > 0 && bytes + im_text.msg_len <= data_len); | |
256 if(msg_type != QQ_MSG_QUN_IM_UNKNOWN) { | |
257 g_return_if_fail(im_text.msg_len >= 10); | |
258 | |
259 bytes += qq_get16(&content_type, data + bytes); | |
260 bytes += qq_get8(&frag_count, data + bytes); | |
261 bytes += qq_get8(&frag_index, data + bytes); | |
262 bytes += qq_get16(&msg_id, data + bytes); | |
263 bytes += 4; /* skip 0x(00 00 00 00) */ | |
264 purple_debug_info("QQ", "Room IM, content %d, frag %d-%d, msg id %u\n", | |
265 content_type, frag_count, frag_index, msg_id); | |
266 im_text.msg_len -= 10; | |
267 } | |
257 g_return_if_fail(im_text.msg_len > 0); | 268 g_return_if_fail(im_text.msg_len > 0); |
258 /* | |
259 * 10 bytes from lumaqq | |
260 * contentType = buf.getChar(); | |
261 * totalFragments = buf.get() & 255; | |
262 * fragmentSequence = buf.get() & 255; | |
263 * messageId = buf.getChar(); | |
264 * buf.getInt(); | |
265 */ | |
266 | |
267 if(msg_type != QQ_MSG_UNKNOWN_QUN_IM) | |
268 skip_len = 10; | |
269 else | |
270 skip_len = 0; | |
271 bytes += skip_len; | |
272 | 269 |
273 /* qq_show_packet("Message", data + bytes, data_len - bytes); */ | 270 /* qq_show_packet("Message", data + bytes, data_len - bytes); */ |
274 | 271 if (frag_count <= 1 || frag_count == frag_index + 1) { |
275 im_text.msg = g_strdup((gchar *) data + bytes); | 272 fmt = qq_im_fmt_new(); |
276 bytes += strlen(im_text.msg) + 1; | 273 tail_len = qq_get_im_tail(fmt, data + bytes, data_len - bytes); |
277 /* there might not be any font_attr, check it */ | 274 im_text.msg = g_strndup((gchar *)(data + bytes), data_len - tail_len); |
278 im_text.font_attr_len = data_len - bytes; | |
279 if (im_text.font_attr_len > 0) { | |
280 im_text.font_attr = g_memdup(data + bytes, im_text.font_attr_len); | |
281 /* qq_show_packet("font_attr", packet.font_attr, packet.font_attr_len); */ | |
282 } else { | 275 } else { |
283 im_text.font_attr = NULL; | 276 im_text.msg = g_strndup((gchar *)(data + bytes), data_len - bytes); |
284 } | 277 } |
285 | 278 |
286 /* group im_group has no flag to indicate whether it has font_attr or not */ | 279 /* group im_group has no flag to indicate whether it has font_attr or not */ |
287 msg_smiley = qq_emoticon_to_purple(im_text.msg); | 280 msg_smiley = qq_emoticon_to_purple(im_text.msg); |
288 if (im_text.font_attr != NULL) { | 281 if (fmt != NULL) { |
289 msg_fmt = qq_format_to_purple(im_text.font_attr, im_text.font_attr_len, | 282 msg_fmt = qq_im_fmt_to_purple(fmt, msg_smiley); |
290 msg_smiley); | |
291 msg_utf8 = qq_to_utf8(msg_fmt, QQ_CHARSET_DEFAULT); | 283 msg_utf8 = qq_to_utf8(msg_fmt, QQ_CHARSET_DEFAULT); |
292 g_free(msg_fmt); | 284 g_free(msg_fmt); |
285 qq_im_fmt_free(fmt); | |
293 } else { | 286 } else { |
294 msg_utf8 = qq_to_utf8(msg_smiley, QQ_CHARSET_DEFAULT); | 287 msg_utf8 = qq_to_utf8(msg_smiley, QQ_CHARSET_DEFAULT); |
295 } | 288 } |
296 g_free(msg_smiley); | 289 g_free(msg_smiley); |
297 | 290 |
298 | 291 purple_debug_info("QQ", "Room (%u) IM from %u: %s\n", |
292 im_text.ext_id, im_text.member_uid, msg_utf8); | |
299 qq_room_got_chat_in(gc, id, im_text.member_uid, msg_utf8, im_text.send_time); | 293 qq_room_got_chat_in(gc, id, im_text.member_uid, msg_utf8, im_text.send_time); |
300 | 294 |
301 g_free(msg_utf8); | 295 g_free(msg_utf8); |
302 g_free(im_text.msg); | 296 g_free(im_text.msg); |
303 if (im_text.font_attr) g_free(im_text.font_attr); | |
304 } | 297 } |
305 | 298 |
306 /* send IM to a group */ | 299 /* send IM to a group */ |
307 static void request_room_send_im(PurpleConnection *gc, guint32 room_id, qq_im_format *fmt, const gchar *msg) | 300 static void request_room_send_im(PurpleConnection *gc, guint32 room_id, qq_im_format *fmt, const gchar *msg) |
308 { | 301 { |
312 g_return_if_fail(room_id != 0 && msg != NULL); | 305 g_return_if_fail(room_id != 0 && msg != NULL); |
313 | 306 |
314 bytes = 0; | 307 bytes = 0; |
315 bytes += qq_put16(raw_data + bytes, 0); | 308 bytes += qq_put16(raw_data + bytes, 0); |
316 bytes += qq_putdata(raw_data + bytes, (guint8 *)msg, strlen(msg)); | 309 bytes += qq_putdata(raw_data + bytes, (guint8 *)msg, strlen(msg)); |
317 bytes += qq_put8(raw_data + bytes, 0); | |
318 bytes += qq_put_im_tail(raw_data + bytes, fmt); | 310 bytes += qq_put_im_tail(raw_data + bytes, fmt); |
311 bytes += qq_put32(raw_data + bytes, 0); /* unknown 4 bytes */ | |
319 | 312 |
320 /* reset first two bytes */ | 313 /* reset first two bytes */ |
321 qq_put16(raw_data, bytes - 2); | 314 qq_put16(raw_data, bytes - 2); |
322 | 315 |
323 qq_send_room_cmd(gc, QQ_ROOM_CMD_SEND_MSG, room_id, raw_data, bytes); | 316 qq_send_room_cmd(gc, QQ_ROOM_CMD_SEND_IM, room_id, raw_data, bytes); |
324 } | 317 } |
325 | 318 |
326 /* this is the ACK */ | 319 /* this is the ACK */ |
327 void qq_process_room_send_im(PurpleConnection *gc, guint8 *data, gint len) | 320 void qq_process_room_send_im(PurpleConnection *gc, guint8 *data, gint len) |
328 { | 321 { |
329 /* return should be the internal group id | 322 /* return should be the internal group id |
330 * but we have nothing to do with it */ | 323 * but we have nothing to do with it */ |
331 return; | 324 return; |
325 } | |
326 | |
327 void qq_process_room_send_im_ex(PurpleConnection *gc, guint8 *data, gint len) | |
328 { | |
329 /* return should be the internal group id | |
330 * but we have nothing to do with it */ | |
331 return; | |
332 } | |
333 | |
334 static void request_room_send_im_ex(PurpleConnection *gc, guint32 room_id, | |
335 qq_im_format *fmt, gchar *msg, guint16 msg_id, guint8 frag_count, guint8 frag_index) | |
336 { | |
337 guint8 raw_data[MAX_PACKET_SIZE - 16]; | |
338 gint bytes; | |
339 | |
340 | |
341 g_return_if_fail(room_id != 0 && msg != NULL); | |
342 | |
343 bytes = 0; | |
344 bytes += qq_put16(raw_data + bytes, 0); /* packet len */ | |
345 /* type 0x0001, text only; 0x0002, with custom emoticon */ | |
346 bytes += qq_put16(raw_data + bytes, 0x0001); | |
347 bytes += qq_put8(raw_data + bytes, frag_count); | |
348 bytes += qq_put8(raw_data + bytes, frag_index); | |
349 bytes += qq_put16(raw_data + bytes, msg_id); | |
350 bytes += qq_put32(raw_data + bytes, 0); /* unknow 4 bytes */ | |
351 bytes += qq_putdata(raw_data + bytes, (guint8 *)msg, strlen(msg)); | |
352 if (frag_count == frag_index + 1) { | |
353 bytes += qq_put8(raw_data + bytes, 0x20); /* add extra SPACE */ | |
354 bytes += qq_put_im_tail(raw_data + bytes, fmt); | |
355 } | |
356 | |
357 /* reset first two bytes as length */ | |
358 qq_put16(raw_data, bytes - 2); | |
359 | |
360 /*qq_show_packet("QQ_ROOM_CMD_SEND_IM_EX", raw_data, bytes); */ | |
361 qq_send_room_cmd(gc, QQ_ROOM_CMD_SEND_IM_EX, room_id, raw_data, bytes); | |
332 } | 362 } |
333 | 363 |
334 /* send a chat msg to a QQ Qun | 364 /* send a chat msg to a QQ Qun |
335 * called by purple */ | 365 * called by purple */ |
336 int qq_chat_send(PurpleConnection *gc, int id, const char *what, PurpleMessageFlags flags) | 366 int qq_chat_send(PurpleConnection *gc, int id, const char *what, PurpleMessageFlags flags) |
340 gchar *msg_stripped, *tmp; | 370 gchar *msg_stripped, *tmp; |
341 GSList *segments, *it; | 371 GSList *segments, *it; |
342 gint msg_len; | 372 gint msg_len; |
343 const gchar *start_invalid; | 373 const gchar *start_invalid; |
344 gboolean is_smiley_none; | 374 gboolean is_smiley_none; |
375 guint8 frag_count, frag_index; | |
345 | 376 |
346 g_return_val_if_fail(NULL != gc && NULL != gc->proto_data, -1); | 377 g_return_val_if_fail(NULL != gc && NULL != gc->proto_data, -1); |
347 g_return_val_if_fail(id != 0 && what != NULL, -1); | 378 g_return_val_if_fail(id != 0 && what != NULL, -1); |
348 | 379 |
349 qd = (qq_data *) gc->proto_data; | 380 qd = (qq_data *) gc->proto_data; |
378 | 409 |
379 if (segments == NULL) { | 410 if (segments == NULL) { |
380 return -1; | 411 return -1; |
381 } | 412 } |
382 | 413 |
414 qd->send_im_id++; | |
383 fmt = qq_im_fmt_new_by_purple(what); | 415 fmt = qq_im_fmt_new_by_purple(what); |
384 for (it = segments; it; it = it->next) { | 416 frag_count = g_slist_length(segments); |
385 request_room_send_im(gc, id, fmt, (gchar *)it->data); | 417 frag_index = 0; |
386 g_free(it->data); | 418 /* |
387 } | 419 if (frag_count <= 1) { |
420 */ | |
421 for (it = segments; it; it = it->next) { | |
422 request_room_send_im(gc, id, fmt, (gchar *)it->data); | |
423 g_free(it->data); | |
424 } | |
425 /* | |
426 } else { | |
427 for (it = segments; it; it = it->next) { | |
428 request_room_send_im_ex(gc, id, fmt, (gchar *)it->data, | |
429 qd->send_im_id, frag_count, frag_index); | |
430 g_free(it->data); | |
431 frag_index++; | |
432 } | |
433 } | |
434 */ | |
388 qq_im_fmt_free(fmt); | 435 qq_im_fmt_free(fmt); |
389 g_slist_free(segments); | 436 g_slist_free(segments); |
390 return 1; | 437 return 1; |
391 } | 438 } |