Пример #1
0
void qq_process_search_uid( PurpleConnection *gc, guint8 *data, gint data_len, qq_buddy_opt_req *opt_req )
{
	gint bytes;
	guint32 uid;
	guint8 status;
	gchar * name;
	guint16 icon;

	g_return_if_fail(data != NULL && data_len != 0);
	g_return_if_fail(opt_req && opt_req->uid != 0);

	//qq_show_packet("qq_process_search_uid", data, data_len);
	bytes = 7;
	bytes += qq_get32(&uid, data + bytes);
	g_return_if_fail(uid == opt_req->uid);

	bytes ++;
	bytes += qq_get8(&status, data + bytes);

	bytes += 4;
	bytes += qq_get_vstr(&name, NULL, sizeof(guint8), data + bytes);
	bytes += qq_get16(&icon, data + bytes);

	bytes += 13;
	bytes += qq_get16(&opt_req->no_auth_len, data + bytes);
	if (opt_req->no_auth)
	{
		opt_req->no_auth = g_new0(guint8, opt_req->no_auth_len);
		bytes += qq_getdata(opt_req->no_auth, opt_req->no_auth_len, data + bytes);
	}

	qq_request_add_buddy_post(gc, opt_req, NULL);
}
Пример #2
0
static gint server_buddy_check_code(PurpleConnection *gc,
		gchar *from, guint8 *data, gint data_len)
{
	gint bytes;
	guint16 code_len;
	guint8 *code;

	g_return_val_if_fail(data != NULL && data_len > 0, 0);

	bytes = 0;
	bytes += qq_get16(&code_len, data + bytes);
	if (code_len <= 0) {
		purple_debug_info("QQ", "Server msg for buddy has no code\n");
		return bytes;
	}
	if (bytes + code_len < data_len) {
		purple_debug_error("QQ", "Code len error in server msg for buddy\n");
		qq_show_packet("server_buddy_check_code", data, data_len);
		code_len = data_len - bytes;
	}
	code = g_newa(guint8, code_len);
	bytes += qq_getdata(code, code_len, data + bytes);

	request_buddy_check_code(gc, from, code, code_len);
	return bytes;
}
Пример #3
0
/* data includes text msg and font attr*/
gint qq_get_im_tail(qq_im_format *fmt, guint8 *data, gint data_len)
{
	gint bytes, text_len;
	guint8 tail_len;
	guint8 font_len;

	g_return_val_if_fail(fmt != NULL && data != NULL, 0);
	g_return_val_if_fail(data_len > 1, 0);
	tail_len = data[data_len - 1];
	g_return_val_if_fail(tail_len > 2, 0);
	text_len = data_len - tail_len;
	g_return_val_if_fail(text_len >= 0, 0);

	bytes = text_len;
	/* qq_show_packet("IM tail", data + bytes, tail_len); */
	bytes += 1;		/* skip 0x00 */
	bytes += qq_get8(&fmt->attr, data + bytes);
	bytes += qq_getdata(fmt->rgb, sizeof(fmt->rgb), data + bytes);	/* red,green,blue */
 	bytes += 1;	/* skip 0x00 */
	bytes += qq_get16(&fmt->charset, data + bytes);

	font_len = data_len - bytes - 1;
	g_return_val_if_fail(font_len > 0, bytes + 1);

	fmt->font_len = font_len;
	if (fmt->font != NULL)	g_free(fmt->font);
	fmt->font = g_strndup((gchar *)data + bytes, fmt->font_len);
	return tail_len;
}
Пример #4
0
/* from QQ2010 on, extra info should be taken out */
static gint packet_get_header_ex(UID *uid, guint8 *header_ex_fixed, guint8 *buf)
{
	gint bytes = 0;
	bytes += qq_get32(uid, buf + bytes);
	bytes += qq_getdata(header_ex_fixed, 3, buf + bytes);
	qq_show_packet("packet_get_header_ex", header_ex_fixed, 3);
	purple_debug_info("QQ", "packet_get_header_ex - UID:%u\n", *uid);
	return bytes;
}
Пример #5
0
void qq_process_auth_token( PurpleConnection *gc, guint8 *data, gint data_len, guint32 dataptr, qq_buddy_opt_req *opt_req )
{
	gint bytes;
	guint8 cmd, reply;
	guint16 sub_cmd;
	guint8 *code = NULL;
	guint16 code_len = 0;

	g_return_if_fail(data != NULL && data_len != 0);
	g_return_if_fail(opt_req && opt_req->uid != 0);

	//qq_show_packet("qq_process_auth_token", data, data_len);
	bytes = 0;
	bytes += qq_get8(&cmd, data + bytes);
	bytes += qq_get16(&sub_cmd, data + bytes);
	bytes += qq_get8(&reply, data + bytes);

	/* if reply == 0x01, we need request captcha */
	if (reply)
	{
		/* if this is end, means you have submitted the wrong captcha  */
		if (bytes>=data_len)
		{
			qq_request_auth_token(gc, QQ_AUTH_INFO_BUDDY, QQ_AUTH_INFO_ADD_BUDDY, 0, opt_req);
			return;
		}

		bytes += qq_get_vstr(&code, NULL, sizeof(guint16), data + bytes);
		purple_util_fetch_url_request(
			(gchar *)code, TRUE, NULL, TRUE,  NULL, TRUE, auth_token_captcha_input_cb, opt_req);
		return;
	}
	
	bytes += qq_get16(&opt_req->auth_len, data + bytes);
	g_return_if_fail(opt_req->auth_len > 0);
	g_return_if_fail(bytes + opt_req->auth_len <= data_len);
	opt_req->auth = g_new0(guint8, opt_req->auth_len);
	bytes += qq_getdata(opt_req->auth, opt_req->auth_len, data + bytes);

	if (cmd == QQ_AUTH_INFO_BUDDY && sub_cmd == QQ_AUTH_INFO_REMOVE_BUDDY) {
		qq_request_remove_buddy(gc, opt_req);
		return;
	}
	if (sub_cmd == QQ_AUTH_INFO_ADD_BUDDY) {
		if (opt_req->auth_type == 0x01)
			add_buddy_authorize_input(gc, opt_req);
		else if (opt_req->auth_type == 0x00)
			qq_request_search_uid(gc, opt_req);
		return;
	}
	if (cmd == QQ_AUTH_INFO_BUDDY && sub_cmd == QQ_AUTH_INFO_UPDATE_BUDDY_INFO) {
		request_change_info(gc, (guint8 *)dataptr, code, code_len);
		return;
	}
	purple_debug_info("QQ", "Got auth info cmd 0x%x, sub 0x%x, reply 0x%x\n",
			cmd, sub_cmd, reply);
}
Пример #6
0
/* read the common parts of the normal_im,
 * returns the bytes read if succeed, or -1 if there is any error */
static gint get_im_header(qq_im_header *im_header, guint8 *data, gint len)
{
	gint bytes;
	g_return_val_if_fail(data != NULL && len > 0, -1);

	bytes = 0;
	bytes += qq_get16(&(im_header->version_from), data + bytes);
	bytes += qq_get32(&(im_header->uid_from), data + bytes);
	bytes += qq_get32(&(im_header->uid_to), data + bytes);
	bytes += qq_getdata(im_header->session_md5, QQ_KEY_LENGTH, data + bytes);
	bytes += qq_get16(&(im_header->im_type), data + bytes);
	return bytes;
}
Пример #7
0
void qq_process_auth_code(PurpleConnection *gc, guint8 *data, gint data_len, guint32 uid)
{
	qq_data *qd;
	gint bytes;
	guint8 cmd, reply;
	guint16 sub_cmd;
	guint8 *code = NULL;
	guint16 code_len = 0;

	g_return_if_fail(data != NULL && data_len != 0);
	g_return_if_fail(uid != 0);

	qd = (qq_data *) gc->proto_data;

	qq_show_packet("qq_process_auth_code", data, data_len);
	bytes = 0;
	bytes += qq_get8(&cmd, data + bytes);
	bytes += qq_get16(&sub_cmd, data + bytes);
	bytes += qq_get8(&reply, data + bytes);
	g_return_if_fail(bytes + 2 <= data_len);

	bytes += qq_get16(&code_len, data + bytes);
	g_return_if_fail(code_len > 0);
	g_return_if_fail(bytes + code_len <= data_len);
	code = g_newa(guint8, code_len);
	bytes += qq_getdata(code, code_len, data + bytes);

	if (cmd == QQ_AUTH_INFO_BUDDY && sub_cmd == QQ_AUTH_INFO_REMOVE_BUDDY) {
		request_remove_buddy_ex(gc, uid, code, code_len);
		return;
	}
	if (cmd == QQ_AUTH_INFO_BUDDY && sub_cmd == QQ_AUTH_INFO_ADD_BUDDY) {
		add_buddy_authorize_input(gc, uid, code, code_len);
		return;
	}
	purple_debug_info("QQ", "Got auth info cmd 0x%x, sub 0x%x, reply 0x%x\n",
			cmd, sub_cmd, reply);
}
Пример #8
0
void qq_process_question(PurpleConnection *gc, guint8 *data, gint data_len, guint32 uid)
{
	qq_data *qd;
	gint bytes;
	guint8 cmd, reply;
	gchar *question, *answer;
	guint16 code_len;
	guint8 *code;

	g_return_if_fail(data != NULL && data_len != 0);

	qd = (qq_data *) gc->proto_data;

	qq_show_packet("qq_process_question", data, data_len);
	bytes = 0;
	bytes += qq_get8(&cmd, data + bytes);
	if (cmd == QQ_QUESTION_GET) {
		bytes += qq_get_vstr(&question, QQ_CHARSET_DEFAULT, data + bytes);
		bytes += qq_get_vstr(&answer, QQ_CHARSET_DEFAULT, data + bytes);
		purple_debug_info("QQ", "Get buddy adding Q&A:\n%s\n%s\n", question, answer);
		g_free(question);
		g_free(answer);
		return;
	}
	if (cmd == QQ_QUESTION_SET) {
		bytes += qq_get8(&reply, data + bytes);
		if (reply == 0) {
			purple_debug_info("QQ", "Successed setting Q&A\n");
		} else {
			purple_debug_warning("QQ", "Failed setting Q&A, reply %d\n", reply);
		}
		return;
	}

	g_return_if_fail(uid != 0);
	bytes += 2; /* skip 2 bytes, 0x(00 01)*/
	if (cmd == QQ_QUESTION_REQUEST) {
		bytes += qq_get8(&reply, data + bytes);
		if (reply == 0x01) {
			purple_debug_warning("QQ", "Failed getting question, reply %d\n", reply);
			return;
		}
		bytes += qq_get_vstr(&question, QQ_CHARSET_DEFAULT, data + bytes);
		purple_debug_info("QQ", "Get buddy question:\n%s\n", question);
		add_buddy_question_input(gc, uid, question);
		g_free(question);
		return;
	}

	if (cmd == QQ_QUESTION_ANSWER) {
		bytes += qq_get8(&reply, data + bytes);
		if (reply == 0x01) {
			purple_notify_error(gc, _("Add Buddy"), _("Invalid answer."), NULL);
			return;
		}
		bytes += qq_get16(&code_len, data + bytes);
		g_return_if_fail(code_len > 0);
		g_return_if_fail(bytes + code_len <= data_len);

		code = g_newa(guint8, code_len);
		bytes += qq_getdata(code, code_len, data + bytes);
		request_add_buddy_by_question(gc, uid, code, code_len);
		return;
	}

	g_return_if_reached();
}
Пример #9
0
/* process received extended (2007) text IM */
static void process_extend_im_text(PurpleConnection *gc, guint8 *data, gint len, qq_im_header *im_header)
{
	qq_data *qd;
	guint16 purple_msg_type;
	gchar *who;
	gchar *msg_smiley, *msg_fmt, *msg_utf8;
	PurpleBuddy *buddy;
	qq_buddy_data *bd;
	gint bytes, tail_len;
	qq_im_format *fmt = NULL;

	struct {
		/* now comes the part for text only */
		guint16 msg_seq;
		guint32 send_time;
		guint16 sender_icon;
		guint32 has_font_attr;
		guint8 unknown1[8];
		guint8 fragment_count;
		guint8 fragment_index;
		guint8 msg_id;
		guint8 unknown2;
		guint8 msg_type;
		gchar *msg;		/* no fixed length, ends with 0x00 */
		guint8 fromMobileQQ;
	} im_text;

	g_return_if_fail (data != NULL && len > 0);
	g_return_if_fail(im_header != NULL);

	qd = (qq_data *) gc->proto_data;
	memset(&im_text, 0, sizeof(im_text));

	/* qq_show_packet("Extend IM text", data, len); */
	bytes = 0;
	bytes += qq_get16(&(im_text.msg_seq), data + bytes);
	bytes += qq_get32(&(im_text.send_time), data + bytes);
	bytes += qq_get16(&(im_text.sender_icon), data + bytes);
	bytes += qq_get32(&(im_text.has_font_attr), data + bytes);
	bytes += qq_getdata(im_text.unknown1, sizeof(im_text.unknown1), data + bytes);
	bytes += qq_get8(&(im_text.fragment_count), data + bytes);
	bytes += qq_get8(&(im_text.fragment_index), data + bytes);
	bytes += qq_get8(&(im_text.msg_id), data + bytes);
	bytes += 1; 	/* skip 0x00 */
	bytes += qq_get8(&(im_text.msg_type), data + bytes);
	purple_debug_info("QQ", "IM Seq %u, id %04X, fragment %d-%d, type %d, %s\n",
			im_text.msg_seq, im_text.msg_id,
			im_text.fragment_count, im_text.fragment_index,
			im_text.msg_type,
			im_text.has_font_attr ? "exist font atrr" : "");

	if (im_text.has_font_attr) {
		fmt = qq_im_fmt_new();
		tail_len = qq_get_im_tail(fmt, data + bytes, len - bytes);
		im_text.msg = g_strndup((gchar *)(data + bytes), len - tail_len);
	} else	{
		im_text.msg = g_strndup((gchar *)(data + bytes), len - bytes);
	}
	/* qq_show_packet("IM text", (guint8 *)im_text.msg , strlen(im_text.msg)); */

	if(im_text.fragment_count == 0) 	im_text.fragment_count = 1;

	who = uid_to_purple_name(im_header->uid_from);
	buddy = purple_find_buddy(gc->account, who);
	if (buddy == NULL) {
		/* create no-auth buddy */
		buddy = qq_buddy_new(gc, im_header->uid_from);
	}
	bd = (buddy == NULL) ? NULL : purple_buddy_get_protocol_data(buddy);
	if (bd != NULL) {
		bd->client_tag = im_header->version_from;
		bd->face = im_text.sender_icon;
		qq_update_buddy_icon(gc->account, who, bd->face);
	}

	purple_msg_type = 0;

	msg_smiley = qq_emoticon_to_purple(im_text.msg);
	if (fmt != NULL) {
		msg_fmt = qq_im_fmt_to_purple(fmt, msg_smiley);
		msg_utf8 =  qq_to_utf8(msg_fmt, QQ_CHARSET_DEFAULT);
		g_free(msg_fmt);
		qq_im_fmt_free(fmt);
	} else {
		msg_utf8 =  qq_to_utf8(msg_smiley, QQ_CHARSET_DEFAULT);
	}
	g_free(msg_smiley);

	/* send encoded to purple, note that we use im_text.send_time,
	 * not the time we receive the message
	 * as it may have been delayed when I am not online. */
	serv_got_im(gc, who, msg_utf8, purple_msg_type, (time_t) im_text.send_time);

	g_free(msg_utf8);
	g_free(who);
	g_free(im_text.msg);
}