示例#1
0
static gint packet_encap(qq_data *qd, guint8 *buf, gint maxlen, guint16 cmd, guint16 seq,
	guint8 *data, gint data_len)
{
	gint bytes = 0;
	g_return_val_if_fail(qd != NULL && buf != NULL && maxlen > 0, -1);
	g_return_val_if_fail(data != NULL && data_len > 0, -1);

	/* QQ TCP packet has two bytes in the begining defines packet length
	 * so leave room here to store packet size */
	if (qd->use_tcp) {
		bytes += qq_put16(buf + bytes, 0x0000);
	}
	/* now comes the normal QQ packet as UDP */
	bytes += qq_put8(buf + bytes, QQ_PACKET_TAG);
	bytes += qq_put16(buf + bytes, qd->client_tag);
	bytes += qq_put16(buf + bytes, cmd);
	bytes += qq_put16(buf + bytes, seq);
	bytes += qq_put32(buf + bytes, qd->uid);
	if(qd->client_version == 2010)
	{
		bytes += qq_putdata(buf + bytes, qd->vd.sig1, VD_SIG1_LEN);
	}
	bytes += qq_putdata(buf + bytes, data, data_len);
	bytes += qq_put8(buf + bytes, QQ_PACKET_TAIL);

	/* set TCP packet length at begin of the packet */
	if (qd->use_tcp) {
		qq_put16(buf, bytes);
	}
#if 1
	qq_show_packet("packet_encap", buf, bytes);
#endif
	return bytes;
}
示例#2
0
/* this buddy needs authentication, text conversion is done at lowest level */
static void request_add_buddy_auth(PurpleConnection *gc, guint32 uid, const gchar response, const gchar *text)
{
	guint8 raw_data[MAX_PACKET_SIZE - 16];
	gint bytes;
	gchar *msg, uid_str[11];
	guint8 bar;

	g_return_if_fail(uid != 0);

	g_snprintf(uid_str, sizeof(uid_str), "%u", uid);
	bar = 0x1f;

	bytes = 0;
	bytes += qq_putdata(raw_data + bytes, (guint8 *) uid_str, strlen(uid_str));
	bytes += qq_put8(raw_data + bytes, bar);
	bytes += qq_put8(raw_data + bytes, response);

	if (text != NULL) {
		msg = utf8_to_qq(text, QQ_CHARSET_DEFAULT);
		bytes += qq_put8(raw_data + bytes, bar);
		bytes += qq_putdata(raw_data + bytes, (guint8 *) msg, strlen(msg));
		g_free(msg);
	}

	qq_send_cmd(gc, QQ_CMD_ADD_BUDDY_AUTH, raw_data, bytes);
}
示例#3
0
static void request_room_send_im_ex(PurpleConnection *gc, guint32 room_id,
	qq_im_format *fmt, gchar *msg, guint16 msg_id, guint8 frag_count, guint8 frag_index)
{
	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);			/* packet len */
	/* type 0x0001, text only; 0x0002, with custom emoticon */
	bytes += qq_put16(raw_data + bytes, 0x0001);
	bytes += qq_put8(raw_data + bytes, frag_count);
	bytes += qq_put8(raw_data + bytes, frag_index);
	bytes += qq_put16(raw_data + bytes, msg_id);
	bytes += qq_put32(raw_data + bytes, 0);			/* unknow 4 bytes */
	bytes += qq_putdata(raw_data + bytes, (guint8 *)msg, strlen(msg));
	if (frag_count == frag_index + 1) {
		bytes += qq_put8(raw_data + bytes, 0x20);	/* add extra SPACE */
		bytes += qq_put_im_tail(raw_data + bytes, fmt);
	}

	/* reset first two bytes as length */
	qq_put16(raw_data, bytes - 2);

	/*qq_show_packet("QQ_ROOM_CMD_SEND_IM_EX", raw_data, bytes); */
	qq_send_room_cmd(gc, QQ_ROOM_CMD_SEND_IM_EX, room_id, raw_data, bytes);
}
示例#4
0
static void request_change_memo(PurpleConnection *gc, guint32 bd_uid, gchar **segments)
{
	gint bytes;
	/* Attention, length of each segment must be guint8(0~255),
	 * so length of memo string is limited.
	 * convert it to guint8 first before putting data */
	guint seg_len;
	gint index;
	guint8 raw_data[MAX_PACKET_SIZE - 16] = {0};

	purple_debug_info( "QQ", "request_change_memo\n" );
	g_return_if_fail(NULL != gc && NULL != segments);

	bytes = 0;
	bytes += qq_put8(raw_data+bytes, QQ_BUDDY_MEMO_MODIFY);
	bytes += qq_put8(raw_data+bytes, 0x00);
	bytes += qq_put32(raw_data+bytes, (guint32)bd_uid);
	bytes += qq_put8(raw_data+bytes, 0x00);
	for (index = 0; index < QQ_MEMO_SIZE; index++) {
		seg_len = strlen(segments[index]);
		seg_len = seg_len & 0xff;
		bytes += qq_put8(raw_data+bytes, (guint8)seg_len);
		bytes += qq_putdata(raw_data+bytes, (const guint8 *)segments[index], (guint8)seg_len);
	}

	/* debug */
	/*
	   qq_show_packet("MEMO MODIFY", raw_data, bytes);
	   */

	qq_send_cmd(gc, QQ_CMD_BUDDY_MEMO, raw_data, bytes);
}
示例#5
0
static gint _qq_send_file(PurpleConnection *gc, guint8 *data, gint len, guint16 packet_type, guint32 to_uid)
{
	guint8 *raw_data;
	gint bytes = 0;
	guint32 file_key;
	qq_data *qd;

	qd = (qq_data *) gc->proto_data;

	raw_data = g_newa(guint8, MAX_PACKET_SIZE);
	file_key = _gen_file_key();

	bytes += qq_put8(raw_data + bytes, packet_type);
	bytes += qq_put16(raw_data + bytes, qd->client_tag);
	bytes += qq_put8(raw_data + bytes, file_key & 0xff);
	bytes += qq_put32(raw_data + bytes, _encrypt_qq_uid(qd->uid, file_key));
	bytes += qq_put32(raw_data + bytes, _encrypt_qq_uid(to_uid, file_key));
	bytes += qq_putdata(raw_data + bytes, data, len);

	if (bytes == len + 12) {
		_qq_xfer_write(raw_data, bytes, qd->xfer);
	} else
		purple_debug_info("QQ", "send_file: want %d but got %d\n", len + 12, bytes);
	return bytes;
}
示例#6
0
void qq_request_get_level_2007(PurpleConnection *gc, guint32 uid)
{
	guint8 buf[16] = {0};
	gint bytes = 0;

	bytes += qq_put8(buf + bytes, 0x08);
	bytes += qq_put32(buf + bytes, uid);
	bytes += qq_put8(buf + bytes, 0x00);
	qq_send_cmd(gc, QQ_CMD_GET_LEVEL, buf, bytes);
}
示例#7
0
void qq_request_get_level(PurpleConnection *gc, guint32 uid)
{
	qq_data *qd = (qq_data *) gc->proto_data;
	guint8 buf[16] = {0};
	gint bytes = 0;

	if (qd->client_version >= 2007) {
		bytes += qq_put8(buf + bytes, 0x02);
	} else {
		bytes += qq_put8(buf + bytes, 0x00);
	}
	bytes += qq_put32(buf + bytes, uid);
	qq_send_cmd(gc, QQ_CMD_GET_LEVEL, buf, bytes);
}
示例#8
0
文件: im.c 项目: Mons/libpurple-mini
/* send an IM to uid_to */
static void request_send_im(PurpleConnection *gc, guint32 uid_to, gint type,
	qq_im_format *fmt, gchar *msg, guint8 id, guint8 frag_count, guint8 frag_index)
{
	qq_data *qd;
	guint8 raw_data[MAX_PACKET_SIZE - 16];
	guint16 im_type;
	gint bytes;
	time_t now;

	qd = (qq_data *) gc->proto_data;
	im_type = QQ_NORMAL_IM_TEXT;

	/* purple_debug_info("QQ", "Send IM %d-%d\n", frag_count, frag_index); */
	bytes = 0;
	/* 000-003: receiver uid */
	bytes += qq_put32(raw_data + bytes, qd->uid);
	/* 004-007: sender uid */
	bytes += qq_put32(raw_data + bytes, uid_to);
	/* 008-009: sender client version */
	bytes += qq_put16(raw_data + bytes, qd->client_tag);
	/* 010-013: receiver uid */
	bytes += qq_put32(raw_data + bytes, qd->uid);
	/* 014-017: sender uid */
	bytes += qq_put32(raw_data + bytes, uid_to);
	/* 018-033: md5 of (uid+session_key) */
	bytes += qq_putdata(raw_data + bytes, qd->session_md5, 16);
	/* 034-035: message type */
	bytes += qq_put16(raw_data + bytes, QQ_NORMAL_IM_TEXT);
	/* 036-037: sequence number */
	bytes += qq_put16(raw_data + bytes, qd->send_seq);
	/* 038-041: send time */
	now = time(NULL);
	bytes += qq_put32(raw_data + bytes, (guint32) now);
	/* 042-043: sender icon */
	bytes += qq_put16(raw_data + bytes, qd->my_icon);
	/* 044-046: always 0x00 */
	bytes += qq_put16(raw_data + bytes, 0x0000);
	bytes += qq_put8(raw_data + bytes, 0x00);
	/* 047-047: always use font attr */
	bytes += qq_put8(raw_data + bytes, 0x01);
	/* 048-051: always 0x00 */
	/* Fixme: frag_count, frag_index not working now */
	bytes += qq_put8(raw_data + bytes, frag_count);
	bytes += qq_put8(raw_data + bytes, frag_index);
	bytes += qq_put8(raw_data + bytes, id);
	bytes += qq_put8(raw_data + bytes, 0);
	/* 052-052: text message type (normal/auto-reply) */
	bytes += qq_put8(raw_data + bytes, type);
	/* 053-   : msg ends with 0x00 */
	bytes += qq_putdata(raw_data + bytes, (guint8 *)msg, strlen(msg));
	if (frag_count == frag_index + 1) {
		bytes += qq_put8(raw_data + bytes, 0x20);	/* add extra SPACE */
	}
	bytes += qq_put_im_tail(raw_data + bytes, fmt);

	/* qq_show_packet("QQ_CMD_SEND_IM", raw_data, bytes); */
	qq_send_cmd(gc, QQ_CMD_SEND_IM, raw_data, bytes);
}
示例#9
0
void qq_request_get_buddies_level(PurpleConnection *gc, guint32 update_class)
{
	qq_data *qd = (qq_data *) gc->proto_data;
	PurpleBuddy *buddy;
	qq_buddy_data *bd;
	guint8 *buf;
	GSList *buddies, *it;
	gint bytes;

	/* server only reply levels for online buddies */
	buf = g_newa(guint8, MAX_PACKET_SIZE);

	bytes = 0;
	bytes += qq_put8(buf + bytes, 0x00);
	buddies = purple_find_buddies(purple_connection_get_account(gc), NULL);
	for (it = buddies; it; it = it->next) {
		buddy = it->data;
		if (buddy == NULL) continue;
		if (buddy->proto_data == NULL) continue;
		bd = (qq_buddy_data *)buddy->proto_data;
		if (bd->uid == 0) continue;	/* keep me as end of packet*/
		if (bd->uid == qd->uid) continue;
		bytes += qq_put32(buf + bytes, bd->uid);
	}
	bytes += qq_put32(buf + bytes, qd->uid);
	qq_send_cmd_mess(gc, QQ_CMD_GET_LEVEL, buf, bytes, update_class, 0);
}
示例#10
0
static void request_buddy_check_code(PurpleConnection *gc,
		gchar *from, guint8 *code, gint code_len)
{
	guint8 *raw_data;
	gint bytes;
	guint32 uid;

	g_return_if_fail(code != NULL && code_len > 0 && from != NULL);

	uid = strtoul(from, NULL, 10);
	raw_data = g_newa(guint8, code_len + 16);
	bytes = 0;
	bytes += qq_put8(raw_data + bytes, 0x03);
	bytes += qq_put8(raw_data + bytes, 0x01);
	bytes += qq_put32(raw_data + bytes, uid);
	bytes += qq_put16(raw_data + bytes, code_len);
	bytes += qq_putdata(raw_data + bytes, code, code_len);

	qq_send_cmd(gc, QQ_CMD_BUDDY_CHECK_CODE, raw_data, bytes);
}
示例#11
0
文件: im.c 项目: Mons/libpurple-mini
gint qq_put_im_tail(guint8 *buf, qq_im_format *fmt)
{
	gint bytes;

	g_return_val_if_fail(buf != NULL && fmt != NULL, 0);

	bytes = 0;
	bytes += qq_put8(buf + bytes, 0);
	bytes += qq_put8(buf + bytes, fmt->attr);
	bytes += qq_putdata(buf + bytes, fmt->rgb, sizeof(fmt->rgb));
	bytes += qq_put8(buf + bytes, 0);
	bytes += qq_put16(buf + bytes, fmt->charset);
	if (fmt->font != NULL && fmt->font_len > 0) {
		bytes += qq_putdata(buf + bytes, (guint8 *)fmt->font, fmt->font_len);
	} else {
		purple_debug_warning("QQ", "Font name is empty\n");
	}
	bytes += qq_put8(buf + bytes, bytes + 1);
	/* qq_show_packet("IM tail", buf, bytes); */
	return bytes;
}
示例#12
0
static gint send_room_cmd(PurpleConnection *gc, guint8 room_cmd, guint32 room_id,
		guint8 *data, gint data_len, UPDCLS update_class, guint32 ship32)
{
	qq_data *qd;
	guint8 *buf;
	gint buf_len;
	guint8 *encrypted;
	gint encrypted_len;
	gint bytes_sent;
	guint16 seq;

	g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1);
	qd = (qq_data *) gc->proto_data;

	buf = g_newa(guint8, MAX_PACKET_SIZE);
	memset(buf, 0, MAX_PACKET_SIZE);

	/* encap room_cmd and room id to buf*/
	buf_len = 0;
	buf_len += qq_put8(buf + buf_len, room_cmd);
	if (room_id != 0) {
		/* id 0 is for QQ Demo Group, now they are closed*/
		buf_len += qq_put32(buf + buf_len, room_id);
	}
	if (data != NULL && data_len > 0) {
		buf_len += qq_putdata(buf + buf_len, data, data_len);
	}

	qd->send_seq++;
	seq = qd->send_seq;

	/* Encrypt to encrypted with session_key */
	/* at most 17 bytes more */
	encrypted = g_newa(guint8, buf_len + 17);
	encrypted_len = qq_encrypt(encrypted, buf, buf_len, qd->session_key);
	if (encrypted_len < 16) {
		purple_debug_error("QQ_ENCRYPT", "Error len %d: [%05d] %s (0x%02X)\n",
				encrypted_len, seq, qq_get_room_cmd_desc(room_cmd), room_cmd);
		return -1;
	}

	bytes_sent = packet_send_out(gc, QQ_CMD_ROOM, seq, encrypted, encrypted_len);
#if 1
		/* qq_show_packet("send_room_cmd", buf, buf_len); */
		purple_debug_info("QQ",
				"<== [%05d] %s (0x%02X) to room %d, datalen %d\n",
				seq, qq_get_room_cmd_desc(room_cmd), room_cmd, room_id, buf_len);
#endif

	qq_trans_add_room_cmd(gc, seq, room_cmd, room_id, encrypted, encrypted_len,
			update_class, ship32);
	return bytes_sent;
}
示例#13
0
void qq_request_question(PurpleConnection *gc,
		guint8 cmd, guint32 uid, const gchar *question_utf8, const gchar *answer_utf8)
{
	guint8 raw_data[MAX_PACKET_SIZE - 16];
	gint bytes;

	g_return_if_fail(uid > 0);
	bytes = 0;
	bytes += qq_put8(raw_data + bytes, cmd);
	if (cmd == QQ_QUESTION_GET) {
		bytes += qq_put8(raw_data + bytes, 0);
		qq_send_cmd_mess(gc, QQ_CMD_BUDDY_QUESTION, raw_data, bytes, 0, uid);
		return;
	}
	if (cmd == QQ_QUESTION_SET) {
		bytes += qq_put_vstr(raw_data + bytes, question_utf8, QQ_CHARSET_DEFAULT);
		bytes += qq_put_vstr(raw_data + bytes, answer_utf8, QQ_CHARSET_DEFAULT);
		bytes += qq_put8(raw_data + bytes, 0);
		qq_send_cmd_mess(gc, QQ_CMD_BUDDY_QUESTION, raw_data, bytes, 0, uid);
		return;
	}
	/* Unknow 2 bytes, 0x(00 01) */
	bytes += qq_put8(raw_data + bytes, 0x00);
	bytes += qq_put8(raw_data + bytes, 0x01);
	g_return_if_fail(uid != 0);
	bytes += qq_put32(raw_data + bytes, uid);
	if (cmd == QQ_QUESTION_REQUEST) {
		qq_send_cmd_mess(gc, QQ_CMD_BUDDY_QUESTION, raw_data, bytes, 0, uid);
		return;
	}
	bytes += qq_put_vstr(raw_data + bytes, answer_utf8, QQ_CHARSET_DEFAULT);
	bytes += qq_put8(raw_data + bytes, 0);
	qq_send_cmd_mess(gc, QQ_CMD_BUDDY_QUESTION, raw_data, bytes, 0, uid);
	return;
}
示例#14
0
static void request_add_buddy_auth_ex(PurpleConnection *gc, guint32 uid,
	const gchar *text, guint8 *auth, guint8 auth_len)
{
	guint8 raw_data[MAX_PACKET_SIZE - 16];
	gint bytes = 0;

	g_return_if_fail(uid != 0);

	bytes = 0;
	bytes += qq_put8(raw_data + bytes, 0x02);
	bytes += qq_put32(raw_data + bytes, uid);
	bytes += qq_put16(raw_data + bytes, 0);

	bytes += qq_put8(raw_data + bytes, 0);
	if (auth == NULL || auth_len <= 0) {
		bytes += qq_put8(raw_data + bytes, 0);
	} else {
		bytes += qq_put8(raw_data + bytes, auth_len);
		bytes += qq_putdata(raw_data + bytes, auth, auth_len);
	}
	bytes += qq_put8(raw_data + bytes, 1);	/* ALLOW ADD ME FLAG */
	bytes += qq_put8(raw_data + bytes, 0);	/* group number? */
	bytes += qq_put_vstr(raw_data + bytes, text, QQ_CHARSET_DEFAULT);
	qq_send_cmd(gc, QQ_CMD_ADD_BUDDY_AUTH_EX, raw_data, bytes);
}
示例#15
0
void qq_request_auth_code(PurpleConnection *gc, guint8 cmd, guint16 sub_cmd, guint32 uid)
{
	guint8 raw_data[16];
	gint bytes;

	g_return_if_fail(uid > 0);
	bytes = 0;
	bytes += qq_put8(raw_data + bytes, cmd);
	bytes += qq_put16(raw_data + bytes, sub_cmd);
	bytes += qq_put32(raw_data + bytes, uid);

	qq_send_cmd_mess(gc, QQ_CMD_AUTH_CODE, raw_data, bytes, 0, uid);
}
示例#16
0
void qq_request_search_uid(PurpleConnection *gc, qq_buddy_opt_req *opt_req)
{
	guint8 raw_data[8];
	gint bytes;

	g_return_if_fail(opt_req && opt_req->uid > 0);
	
	bytes = 0;
	bytes += qq_put8(raw_data + bytes, 0x03);
	bytes += qq_put32(raw_data + bytes, opt_req->uid);

	qq_send_cmd_mess(gc, QQ_CMD_SEARCH_UID, raw_data, bytes, 0, (guintptr)opt_req);
}
示例#17
0
static void request_add_buddy_by_question(PurpleConnection *gc, guint32 uid,
	guint8 *code, guint16 code_len)
{
	guint8 raw_data[MAX_PACKET_SIZE - 16];
	gint bytes = 0;

	g_return_if_fail(uid != 0 && code_len > 0);

	bytes = 0;
	bytes += qq_put8(raw_data + bytes, 0x10);
	bytes += qq_put32(raw_data + bytes, uid);
	bytes += qq_put16(raw_data + bytes, 0);

	bytes += qq_put8(raw_data + bytes, 0);
	bytes += qq_put8(raw_data + bytes, 0);	/* no auth code */

	bytes += qq_put16(raw_data + bytes, code_len);
	bytes += qq_putdata(raw_data + bytes, code, code_len);

	bytes += qq_put8(raw_data + bytes, 1);	/* ALLOW ADD ME FLAG */
	bytes += qq_put8(raw_data + bytes, 0);	/* group number? */
	qq_send_cmd(gc, QQ_CMD_ADD_BUDDY_AUTH_EX, raw_data, bytes);
}
示例#18
0
/* send packet to search for qq_group */
void qq_request_room_search(PurpleConnection *gc, guint32 ext_id, int action)
{
	guint8 raw_data[16] = {0};
	gint bytes = 0;
	guint8 type;

	purple_debug_info("QQ", "Search QQ Qun %u\n", ext_id);
	type = (ext_id == 0x00000000) ? QQ_ROOM_SEARCH_TYPE_DEMO : QQ_ROOM_SEARCH_TYPE_BY_ID;

	bytes = 0;
	bytes += qq_put8(raw_data + bytes, type);
	bytes += qq_put32(raw_data + bytes, ext_id);

	qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_SEARCH, 0, raw_data, bytes, 0, action);
}
示例#19
0
/* send packet to modify personal information */
static void request_change_info(PurpleConnection *gc, gchar **segments)
{
	gint bytes = 0;
	guint8 raw_data[MAX_PACKET_SIZE - 128] = {0};
	guint8 bar;
	gchar *join;

	g_return_if_fail(segments != NULL);

	bar = 0x1f;

	bytes += qq_put8(raw_data + bytes, bar);
	bytes += qq_put8(raw_data + bytes, bar);

	/* important! skip the first uid entry */
	join = g_strjoinv("\x1f", segments + 1);
	bytes += qq_putdata(raw_data + bytes, (guint8 *)join, strlen(join));
	g_free(join);

	bytes += qq_put8(raw_data + bytes, bar);

	/* qq_show_packet("request_modify_info", raw_data, bytes); */
	qq_send_cmd(gc, QQ_CMD_UPDATE_INFO, raw_data, bytes);
}
示例#20
0
void qq_request_auth_token( PurpleConnection *gc, guint8 cmd, guint16 sub_cmd, guint32 dataptr2ship, qq_buddy_opt_req *opt_req )
{
	guint8 raw_data[128];
	gint bytes;

	g_return_if_fail(opt_req && opt_req->uid > 0);
	bytes = 0;
	bytes += qq_put8(raw_data + bytes, cmd);
	bytes += qq_put16(raw_data + bytes, sub_cmd);
	bytes += qq_put32(raw_data + bytes, opt_req->uid);

	if (opt_req->captcha_input && opt_req->session)
	{	
		bytes += qq_put_vstr(raw_data+bytes, opt_req->captcha_input, sizeof(guint16), NULL);
		bytes += qq_put16(raw_data+bytes, opt_req->session_len);
		bytes += qq_putdata(raw_data+bytes, opt_req->session, opt_req->session_len);
	}
	
	qq_send_cmd_mess(gc, QQ_CMD_AUTH_TOKEN, raw_data, bytes, dataptr2ship, (guintptr)opt_req);
}
示例#21
0
/* request buddy memo */
void qq_request_buddy_memo(PurpleConnection *gc, guint32 bd_uid, guint32 update_class, guint32 action)
{
	guint8 raw_data[16] = {0};
	gint bytes;

	purple_debug_info("QQ", "qq_request_buddy_memo, buddy uid=%u, update_class=%u\n",
			bd_uid, update_class);
	g_return_if_fail(NULL != gc);
	/* '0' is ok
	   g_return_if_fail(uid != 0);
	   */
	bytes = 0;
	bytes += qq_put8(raw_data+bytes, QQ_BUDDY_MEMO_GET);
	bytes += qq_put32(raw_data+bytes, bd_uid);
	/*
	   qq_show_packet("MEMO REQUEST", raw_data, bytes);
	   */

	qq_send_cmd_mess(gc, QQ_CMD_BUDDY_MEMO, (guint8*)raw_data, bytes, update_class, action);
}
示例#22
0
void qq_send_cmd_group_auth(PurpleConnection *gc, qq_room_data *rmd,
		guint8 opt, guint32 uid, const gchar *reason_utf8)
{
	guint8 raw_data[MAX_PACKET_SIZE - 16];
	gint bytes;

	g_return_if_fail(rmd != NULL);

	if (opt == QQ_ROOM_AUTH_REQUEST_APPLY) {
		rmd->my_role = QQ_ROOM_ROLE_REQUESTING;
		uid = 0;
	}

	bytes = 0;
	bytes += qq_put8(raw_data + bytes, opt);
	bytes += qq_put32(raw_data + bytes, uid);
	bytes += qq_put_vstr(raw_data + bytes, reason_utf8, QQ_CHARSET_DEFAULT);

	qq_send_room_cmd(gc, QQ_ROOM_CMD_AUTH, rmd->id, raw_data, bytes);
}
示例#23
0
static void request_remove_buddy_ex(PurpleConnection *gc,
		guint32 uid, guint8 *auth, guint8 auth_len)
{
	gint bytes;
	guint8 *raw_data;
	gchar uid_str[16];

	g_return_if_fail(uid != 0);
	g_return_if_fail(auth != NULL && auth_len > 0);

	raw_data = g_newa(guint8, auth_len + sizeof(uid_str) );
	bytes = 0;
	bytes += qq_put8(raw_data + bytes, auth_len);
	bytes += qq_putdata(raw_data + bytes, auth, auth_len);

	g_snprintf(uid_str, sizeof(uid_str), "%u", uid);
	bytes += qq_putdata(raw_data + bytes, (guint8 *)uid_str, strlen(uid_str));

	qq_send_cmd_mess(gc, QQ_CMD_REMOVE_BUDDY, raw_data, bytes, 0, uid);
}
示例#24
0
/* send packet to remove a buddy from my buddy list */
static void qq_request_remove_buddy(PurpleConnection *gc, qq_buddy_opt_req *opt_req)
{
	gint bytes;
	guint8 *raw_data;
	gchar * uid_str;

	g_return_if_fail(opt_req && opt_req->uid != 0);
	g_return_if_fail(opt_req->auth != NULL && opt_req->auth_len > 0);

	raw_data = g_newa(guint8, opt_req->auth_len + sizeof(uid_str));
	bytes = 0;
	bytes += qq_put8(raw_data + bytes, opt_req->auth_len);
	bytes += qq_putdata(raw_data + bytes, opt_req->auth, opt_req->auth_len);

	uid_str = uid_to_purple_name(opt_req->uid);
	bytes += qq_putdata(raw_data + bytes, (guint8 *)uid_str, strlen(uid_str));
	g_free(uid_str);

	qq_send_cmd_mess(gc, QQ_CMD_REMOVE_BUDDY, raw_data, bytes, 0, opt_req->uid);
	
	buddy_opt_req_free(opt_req);
}
示例#25
0
/* send a file to udp channel with QQ_FILE_DATA_PACKET_TAG */
static void _qq_send_file_data_packet(PurpleConnection *gc, guint16 packet_type, guint8 sub_type,
		guint32 fragment_index, guint16 seq, guint8 *data, gint len)
{
	guint8 *raw_data, filename_md5[QQ_KEY_LENGTH], file_md5[QQ_KEY_LENGTH];
	gint bytes;
	guint32 fragment_size = 1000;
	const char *filename;
	gint filename_len, filesize;
	qq_data *qd;
	ft_info *info;

	qd = (qq_data *) gc->proto_data;
	info = (ft_info *) qd->xfer->data;

	filename = purple_xfer_get_filename(qd->xfer);
	filesize = purple_xfer_get_size(qd->xfer);

	raw_data = g_newa(guint8, MAX_PACKET_SIZE);
	bytes = 0;

	bytes += qq_put8(raw_data + bytes, 0x00);
	bytes += qq_put16(raw_data + bytes, packet_type);
	switch (packet_type) {
		case QQ_FILE_BASIC_INFO:
		case QQ_FILE_DATA_INFO:
		case QQ_FILE_EOF:
			bytes += qq_put16(raw_data + bytes, 0x0000);
			bytes += qq_put8(raw_data + bytes, 0x00);
			break;
		case QQ_FILE_CMD_FILE_OP:
			switch(sub_type)
			{
				case QQ_FILE_BASIC_INFO:
					filename_len = strlen(filename);
					qq_get_md5(filename_md5, sizeof(filename_md5), (guint8 *)filename, filename_len);
					_fill_file_md5(purple_xfer_get_local_filename(qd->xfer),
							purple_xfer_get_size(qd->xfer),
							file_md5);

					info->fragment_num = (filesize - 1) / QQ_FILE_FRAGMENT_MAXLEN + 1;
					info->fragment_len = QQ_FILE_FRAGMENT_MAXLEN;

					purple_debug_info("QQ",
							"start transfering data, %d fragments with %d length each\n",
							info->fragment_num, info->fragment_len);
					/* Unknown */
					bytes += qq_put16(raw_data  + bytes, 0x0000);
					/* Sub-operation type */
					bytes += qq_put8(raw_data + bytes, sub_type);
					/* Length of file */
					bytes += qq_put32(raw_data + bytes, filesize);
					/* Number of fragments */
					bytes += qq_put32(raw_data + bytes, info->fragment_num);
					/* Length of a single fragment */
					bytes += qq_put32(raw_data + bytes, info->fragment_len);
					bytes += qq_putdata(raw_data + bytes, file_md5, 16);
					bytes += qq_putdata(raw_data + bytes, filename_md5, 16);
					/* Length of filename */
					bytes += qq_put16(raw_data + bytes, filename_len);
					/* 8 unknown bytes */
					bytes += qq_put32(raw_data + bytes, 0x00000000);
					bytes += qq_put32(raw_data + bytes, 0x00000000);
					/* filename */
					bytes += qq_putdata(raw_data + bytes, (guint8 *) filename,
							filename_len);
					break;
				case QQ_FILE_DATA_INFO:
					purple_debug_info("QQ",
							"sending %dth fragment with length %d, offset %d\n",
							fragment_index, len, (fragment_index-1)*fragment_size);
					/* bytes += qq_put16(raw_data + bytes, ++(qd->send_seq)); */
					bytes += qq_put16(raw_data + bytes, info->send_seq);
					bytes += qq_put8(raw_data + bytes, sub_type);
					/* bytes += qq_put32(raw_data + bytes, fragment_index); */
					bytes += qq_put32(raw_data + bytes, fragment_index - 1);
					bytes += qq_put32(raw_data + bytes, (fragment_index - 1) * fragment_size);
					bytes += qq_put16(raw_data + bytes, len);
					bytes += qq_putdata(raw_data + bytes, data, len);
					break;
				case QQ_FILE_EOF:
					purple_debug_info("QQ", "end of sending data\n");
					/* bytes += qq_put16(raw_data + bytes, info->fragment_num + 1); */
					bytes += qq_put16(raw_data + bytes, info->fragment_num);
					bytes += qq_put8(raw_data + bytes, sub_type);
					/* purple_xfer_set_completed(qd->xfer, TRUE); */
			}
			break;
		case QQ_FILE_CMD_FILE_OP_ACK:
			switch (sub_type)
			{
				case QQ_FILE_BASIC_INFO:
					bytes += qq_put16(raw_data + bytes, 0x0000);
					bytes += qq_put8(raw_data + bytes, sub_type);
					bytes += qq_put32(raw_data + bytes, 0x00000000);
					break;
				case QQ_FILE_DATA_INFO:
					bytes += qq_put16(raw_data + bytes, seq);
					bytes += qq_put8(raw_data + bytes, sub_type);
					bytes += qq_put32(raw_data + bytes, fragment_index);
					break;
				case QQ_FILE_EOF:
					bytes += qq_put16(raw_data + bytes, filesize / QQ_FILE_FRAGMENT_MAXLEN + 2);
					bytes += qq_put8(raw_data + bytes, sub_type);
					break;
			}
	}
	purple_debug_info("QQ", "<== send %s packet\n", qq_get_file_cmd_desc(packet_type));
	_qq_send_file(gc, raw_data, bytes, QQ_FILE_DATA_PACKET_TAG, info->to_uid);
}
示例#26
0
/* send a file to udp channel with QQ_FILE_CONTROL_PACKET_TAG */
void qq_send_file_ctl_packet(PurpleConnection *gc, guint16 packet_type, guint32 to_uid, guint8 hellobyte)
{
	qq_data *qd;
	gint bytes, bytes_expected, encrypted_len;
	guint8 *raw_data, *encrypted;
	time_t now;
	ft_info *info;

	qd = (qq_data *) gc->proto_data;
	info = (ft_info *) qd->xfer->data;

	raw_data = g_newa (guint8, 61);
	bytes = 0;

	now = time(NULL);

	bytes += qq_putdata(raw_data + bytes, qd->session_md5, 16);
	bytes += qq_put16(raw_data + bytes, packet_type);
	switch (packet_type) {
		case QQ_FILE_CMD_SENDER_SAY_HELLO:
		case QQ_FILE_CMD_SENDER_SAY_HELLO_ACK:
		case QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK:
		case QQ_FILE_CMD_NOTIFY_IP_ACK:
		case QQ_FILE_CMD_RECEIVER_SAY_HELLO:
			bytes += qq_put16(raw_data + bytes, info->send_seq);
			break;
		default:
			bytes += qq_put16(raw_data + bytes, ++qd->send_seq);
	}
	bytes += qq_put32(raw_data + bytes, (guint32) now);
	bytes += qq_put8(raw_data + bytes, 0x00);
	bytes += qq_put8(raw_data + bytes, qd->my_icon);
	bytes += qq_put32(raw_data + bytes, 0x00000000);
	bytes += qq_put32(raw_data + bytes, 0x00000000);
	bytes += qq_put32(raw_data + bytes, 0x00000000);
	bytes += qq_put32(raw_data + bytes, 0x00000000);
	bytes += qq_put16(raw_data + bytes, 0x0000);
	bytes += qq_put8(raw_data + bytes, 0x00);
	/* 0x65: send a file, 0x6b: send a custom face */
	bytes += qq_put8(raw_data + bytes, QQ_FILE_TRANSFER_FILE); /* FIXME temp by gfhuang */
	switch (packet_type)
	{
		case QQ_FILE_CMD_SENDER_SAY_HELLO:
		case QQ_FILE_CMD_RECEIVER_SAY_HELLO:
		case QQ_FILE_CMD_SENDER_SAY_HELLO_ACK:
		case QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK:
			bytes += qq_put8(raw_data + bytes, 0x00);
			bytes += qq_put8(raw_data + bytes, hellobyte);
			bytes_expected = 48;
			break;
		case QQ_FILE_CMD_PING:
		case QQ_FILE_CMD_PONG:
		case QQ_FILE_CMD_NOTIFY_IP_ACK:
			bytes += qq_fill_conn_info(raw_data, info);
			bytes_expected = 61;
			break;
		default:
			purple_debug_info("QQ", "qq_send_file_ctl_packet: Unknown packet type[%d]\n",
					packet_type);
			bytes_expected = 0;
	}

	if (bytes != bytes_expected) {
		purple_debug_error("QQ", "qq_send_file_ctl_packet: Expected to get %d bytes, but get %d\n",
				bytes_expected, bytes);
		return;
	}

	qq_hex_dump(PURPLE_DEBUG_INFO, "QQ",
		raw_data, bytes,
		"sending packet[%s]:", qq_get_file_cmd_desc(packet_type));

	encrypted = g_newa(guint8, bytes + 17);
	encrypted_len = qq_encrypt(encrypted, raw_data, bytes, info->file_session_key);
	/*debug: try to decrypt it */

#if 0
	guint8 *buf;
	int buflen;
	hex_dump = hex_dump_to_str(encrypted, encrypted_len);
	purple_debug_info("QQ", "encrypted packet: \n%s\n", hex_dump);
	g_free(hex_dump);
	buf = g_newa(guint8, MAX_PACKET_SIZE);
	buflen = encrypted_len;
	if (qq_crypt(DECRYPT, encrypted, encrypted_len, info->file_session_key, buf, &buflen)) {
		purple_debug_info("QQ", "decrypt success\n");
	   if (buflen == bytes && memcmp(raw_data, buf, buflen) == 0)
			purple_debug_info("QQ", "checksum ok\n");

		hex_dump = hex_dump_to_str(buf, buflen);
		purple_debug_info("QQ", "decrypted packet: \n%s\n", hex_dump);
		g_free(hex_dump);
	 } else {
		purple_debug_info("QQ", "decrypt fail\n");
	}
#endif

	purple_debug_info("QQ", "<== send %s packet\n", qq_get_file_cmd_desc(packet_type));
	_qq_send_file(gc, encrypted, encrypted_len, QQ_FILE_CONTROL_PACKET_TAG, info->to_uid);
}
示例#27
0
void qq_request_add_buddy_post(PurpleConnection *gc, qq_buddy_opt_req *opt_req, const gchar *text)
{
	static guint8 fill1[] = {
		0x00, 0x0A, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
	};
	static guint8 fill2[] = {
		0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
	};
	guint8 raw_data[256];
	gint bytes = 0;
	guint8 cmd;

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

	switch (opt_req->auth_type)
	{
	case 0x01:	//auth
		cmd = 0x02;
		break;
	case 0x02:	//question
		cmd = 0x10;
		break;
	case 0x00:	//no_auth
	case 0x03:	//approve and add
	case 0x04:	//approve
	case 0x05:	//reject
		cmd = opt_req->auth_type;
		break;
	}
	
	bytes = 0;
	bytes += qq_put8(raw_data + bytes, cmd);
	bytes += qq_put32(raw_data + bytes, opt_req->uid);

	if (cmd == 0x03 || cmd == 0x04 || cmd == 0x05)
	{
		bytes += qq_put16(raw_data + bytes, 0);
	} else {
		if (opt_req->no_auth && opt_req->no_auth_len > 0) {
			bytes += qq_put16(raw_data + bytes, opt_req->no_auth_len);
			bytes += qq_putdata(raw_data + bytes, opt_req->no_auth, opt_req->no_auth_len);
		} else	bytes += qq_put16(raw_data + bytes, 0);

		if (opt_req->auth == NULL || opt_req->auth_len <= 0) {
			bytes += qq_put16(raw_data + bytes, 0);
		} else {
			bytes += qq_put16(raw_data + bytes, opt_req->auth_len);
			bytes += qq_putdata(raw_data + bytes, opt_req->auth, opt_req->auth_len);
		}
		bytes += qq_put8(raw_data + bytes, 1);	/* ALLOW ADD ME FLAG */
	}

	bytes += qq_put8(raw_data + bytes, opt_req->group_id);	/* group number */

	if (text) {
		bytes += qq_put8(raw_data + bytes, strlen(text));
		bytes += qq_putdata(raw_data + bytes, (guint8 *)text, strlen(text));
	}

	if (cmd == 0x03 || cmd == 0x04 || cmd == 0x05)
		bytes += qq_putdata(raw_data + bytes, fill2, sizeof(fill2));
	else
		bytes += qq_putdata(raw_data + bytes, fill1, sizeof(fill1));

	qq_send_cmd_mess(gc, QQ_CMD_ADD_BUDDY_POST, raw_data, bytes, 0, opt_req->auth_type);

	buddy_opt_req_free(opt_req);
}