コード例 #1
0
ファイル: group_im.c プロジェクト: Mons/libpurple-mini
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);
}
コード例 #2
0
ファイル: qq_network.c プロジェクト: cysfek/openq-ng
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;
}
コード例 #3
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);
}
コード例 #4
0
ファイル: file_trans.c プロジェクト: 1dot75cm/pidgin-libqq
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;
}
コード例 #5
0
ファイル: buddy_opt.c プロジェクト: wosigh/messaging-plugins
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);
}
コード例 #6
0
ファイル: group_im.c プロジェクト: Mons/libpurple-mini
/* 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_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_IM, room_id, raw_data, bytes);
}
コード例 #7
0
ファイル: buddy_opt.c プロジェクト: chrisballinger/AdiumQQ
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);
}
コード例 #8
0
ファイル: buddy_opt.c プロジェクト: wosigh/messaging-plugins
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);
}
コード例 #9
0
ファイル: buddy_opt.c プロジェクト: wosigh/messaging-plugins
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);
}
コード例 #10
0
ファイル: buddy_opt.c プロジェクト: wosigh/messaging-plugins
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
ファイル: file_trans.c プロジェクト: 1dot75cm/pidgin-libqq
/* 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);
}
コード例 #13
0
ファイル: file_trans.c プロジェクト: 1dot75cm/pidgin-libqq
/* 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);
}
コード例 #14
0
ファイル: buddy_opt.c プロジェクト: chrisballinger/AdiumQQ
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);
}