Example #1
0
static void do_server_news(PurpleConnection *gc, guint8 *data, gint data_len)
{
	qq_data *qd = (qq_data *) gc->proto_data;
	gint bytes;
	gchar *title, *brief, *url;
	gchar *content;

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

	/* qq_show_packet("Rcv news", data, data_len); */

	bytes = 4;	/* skip unknown 4 bytes */

	bytes += qq_get_vstr(&title, QQ_CHARSET_DEFAULT, sizeof(guint8), data + bytes);
	bytes += qq_get_vstr(&brief, QQ_CHARSET_DEFAULT, sizeof(guint8), data + bytes);
	bytes += qq_get_vstr(&url, QQ_CHARSET_DEFAULT, sizeof(guint8), data + bytes);

	content = g_strdup_printf(_("Server News:\n%s\n%s\n%s"), title, brief, url);

	if (qd->is_show_news) {
		qq_got_message(gc, content);
	} else {
		purple_debug_info("QQ", "QQ Server news:\n%s\n", content);
	}
	g_free(title);
	g_free(brief);
	g_free(url);
	g_free(content);
}
Example #2
0
static void server_buddy_add_request_ex(PurpleConnection *gc, gchar *from, gchar *to,
		guint8 *data, gint data_len)
{
	gint bytes;
	guint32 uid;
	gchar *msg;
	guint8 allow_reverse;

	g_return_if_fail(from != NULL && to != NULL);
	g_return_if_fail(data != NULL && data_len >= 3);
	uid = strtoul(from, NULL, 10);
	g_return_if_fail(uid != 0);

	/* qq_show_packet("server_buddy_add_request_ex", data, data_len); */

	bytes = 0;
	bytes += qq_get_vstr(&msg, QQ_CHARSET_DEFAULT, data+bytes);
	bytes += qq_get8(&allow_reverse, data + bytes);	/* allow_reverse = 0x01, allowed */
	server_buddy_check_code(gc, from, data + bytes, data_len - bytes);

	if (strlen(msg) <= 0) {
		g_free(msg);
		msg = g_strdup( _("No reason given") );
	}
	buddy_add_input(gc, uid, msg);
	g_free(msg);
}
Example #3
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);
}
Example #4
0
/* process group cmd reply "search group" */
void qq_process_room_search(PurpleConnection *gc, guint8 *data, gint len, guint32 ship32)
{
	qq_data *qd;
	qq_room_data rmd;
	PurpleChat *chat;
	gint bytes;
	guint8 search_type;
	guint16 unknown;

	g_return_if_fail(data != NULL && len > 0);
	qd = (qq_data *) gc->proto_data;

	bytes = 0;
	bytes += qq_get8(&search_type, data + bytes);

	/* now it starts with group_info_entry */
	bytes += qq_get32(&(rmd.id), data + bytes);
	bytes += qq_get32(&(rmd.ext_id), data + bytes);
	bytes += qq_get8(&(rmd.type8), data + bytes);
	bytes += qq_get16(&(unknown), data + bytes);
	bytes += qq_get16(&(unknown), data + bytes);
	bytes += qq_get32(&(rmd.creator_uid), data + bytes);
	bytes += qq_get16(&(unknown), data + bytes);
	bytes += qq_get16(&(unknown), data + bytes);
	bytes += qq_get16(&(unknown), data + bytes);
	bytes += qq_get32(&(rmd.category), data + bytes);
	bytes += qq_get_vstr(&(rmd.title_utf8), QQ_CHARSET_DEFAULT, data + bytes);
	bytes += qq_get16(&(unknown), data + bytes);
	bytes += qq_get8(&(rmd.auth_type), data + bytes);
	bytes += qq_get_vstr(&(rmd.desc_utf8), QQ_CHARSET_DEFAULT, data + bytes);
	/* end of one qq_group */
	if(bytes != len) {
		purple_debug_error("QQ",
			"group_cmd_search_group: Dangerous error! maybe protocol changed, notify developers!");
	}

	if (ship32 == QQ_ROOM_SEARCH_FOR_JOIN) {
		chat = qq_room_find_or_new(gc, rmd.id, rmd.ext_id);
		g_return_if_fail(chat != NULL);

		qq_room_update_chat_info(chat, &rmd);
		qq_request_room_join(gc, &rmd);
	} else {
		add_to_roomlist(qd, &rmd);
	}
}
Example #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);
}
Example #6
0
static void server_buddy_added_ex(PurpleConnection *gc, gchar *from, gchar *to,
		guint8 *data, gint data_len)
{
	gint bytes;
	guint8 allow_reverse;
	gchar *msg;

	g_return_if_fail(from != NULL && to != NULL);
	g_return_if_fail(data != NULL && data_len >= 3);

	qq_show_packet("server_buddy_added_ex", data, data_len);

	bytes = 0;
	bytes += qq_get_vstr(&msg, QQ_CHARSET_DEFAULT, data+bytes);	/* always empty msg */
	purple_debug_info("QQ", "Buddy added msg: %s\n", msg);
	bytes += qq_get8(&allow_reverse, data + bytes);	/* allow_reverse = 0x01, allowed */
	server_buddy_check_code(gc, from, data + bytes, data_len - bytes);

	g_free(msg);
}
Example #7
0
static void do_msg_sys(PurpleConnection *gc, guint8 *data, gint data_len)
{
	guint8 reply;
	gchar *msg, *msg_esc;
	qq_data * qd;

	g_return_if_fail(gc != NULL && gc->proto_data != NULL && data != NULL && data_len != 0);

	qd = (qq_data *)gc->proto_data;

	qq_get8(&reply, data+4);
	qq_get_vstr(&msg, NULL, sizeof(guint8), data+5);

	if (reply == 0x01) {
		purple_debug_error("QQ", "We are kicked out by QQ server\n");
		msg_esc = purple_markup_escape_text(msg, -1);
		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, msg_esc);
		g_free(msg);
		g_free(msg_esc);
		return;
	}
	
	qq_got_message(gc, msg);
}
Example #8
0
/* process reply to get_memo packet */
void qq_process_get_buddy_memo(PurpleConnection *gc, guint8* data, gint data_len,
		guint32 update_class, guint32 action)
{
	gchar **segments;
	gint bytes;
	gint index;
	guint8 rcv_cmd;
	guint32 rcv_uid;
	guint8 unk1_8;
	guint8 is_success;

	g_return_if_fail(NULL != gc && NULL != data && 0 != data_len);
	/*
	   qq_show_packet("MEMO REACH", data, data_len);
	   */
	purple_debug_info("QQ", "action=0x%02X\n", action);

	bytes = 0;

	/* TX looks a bit clever than before... :) */
	bytes += qq_get8(&rcv_cmd, data+bytes);
	purple_debug_info("QQ", "rcv_cmd=0x%02X\n", rcv_cmd);

	/* it's possible that packet contains no buddy uid and no memo!!!
	 * go to next step according to previous action sent */
	if (1 == data_len) { /* only one byte */
		purple_debug_info("QQ", "memo packet contains no buddy uid and memo...\n");
		if (QQ_BUDDY_MEMO_MODIFY == action) {
			qq_create_buddy_memo(gc, (guint32)update_class, QQ_BUDDY_MEMO_MODIFY);
			return;
		}
		return;
	}

	switch (rcv_cmd) {
		case QQ_BUDDY_MEMO_MODIFY:
		case QQ_BUDDY_MEMO_REMOVE:
			bytes += qq_get8(&is_success, data+bytes);
			if (QQ_BUDDY_MEMO_REQUEST_SUCCESS == is_success) {
				purple_notify_message(gc, PURPLE_NOTIFY_MSG_INFO,
						_("Memo Modify"), _("Server says:"),
						_("Your request was accepted."),
						NULL, NULL);
				purple_debug_info("QQ", "memo change succeessfully!\n");
			}
			else {
				purple_notify_message(gc, PURPLE_NOTIFY_MSG_INFO,
						_("Memo Modify"), _("Server says:"),
						_("Your request was rejected."),
						NULL, NULL);
				purple_debug_info("QQ", "memo change failed\n");
			}
			break;
		case QQ_BUDDY_MEMO_GET:
			bytes += qq_get32(&rcv_uid, data+bytes);
			purple_debug_info("QQ", "rcv_uid=%u\n", rcv_uid);
			bytes += qq_get8(&unk1_8, data+bytes);
			purple_debug_info("QQ", "unk1_8=0x%02X\n", unk1_8);
			segments = g_new0(gchar*, QQ_MEMO_SIZE);
			for (index = 0; index < QQ_MEMO_SIZE; index++) {
				/* get utf8 string */
				bytes += qq_get_vstr(&segments[index], QQ_CHARSET_DEFAULT, data+bytes);
				/*
				   purple_debug_info("QQ", "bytes:%d, seg:%s\n", bytes, segments[index]);
				   */
			}

			/* common action, update buddy memo */
			update_buddy_memo(gc, rcv_uid, segments[QQ_MEMO_ALIAS]);

			/* memo is thing that we regard our buddy as, so we need one more buddy_uid */
			memo_modify_dialogue(gc, rcv_uid, segments, action);
			break;
		default:
			purple_debug_info("QQ", "received an UNKNOWN memo cmd!!!\n");
			break;
	}
}
Example #9
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();
}
Example #10
0
/* process the reply to get_members_info packet */
void qq_process_room_cmd_get_members_info( guint8 *data, gint len, guint32 index, PurpleConnection *gc )
{
	gint bytes;
	gint num;
	guint32 id, member_uid;
	guint16 unknown;
	qq_room_data *rmd;
	qq_buddy_data *bd;
	gchar *nick;

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

	/* qq_show_packet("qq_process_room_cmd_get_members_info", data, len); */

	bytes = 0;
	bytes += qq_get32(&id, data + bytes);
	g_return_if_fail(id > 0);

	rmd = qq_room_data_find(gc, id);
	g_return_if_fail(rmd != NULL);

	num = 0;

	while (bytes < len) {
		bytes += qq_get32(&member_uid, data + bytes);
		g_return_if_fail(member_uid > 0);
		bd = qq_room_buddy_find_or_new(gc, rmd, member_uid);
		g_return_if_fail(bd != NULL);

		num++;
		bytes += qq_get16(&(bd->face), data + bytes);
		bytes += qq_get8(&(bd->age), data + bytes);
		bytes += qq_get8(&(bd->gender), data + bytes);
		/* only here use old charset GB18030 */
		bytes += qq_get_vstr(&nick, QQ_CHARSET_DEFAULT, sizeof(guint8), data + bytes);
		bytes += qq_get16(&unknown, data + bytes);
		bytes += qq_get8(&(bd->ext_flag), data + bytes);
		bytes += qq_get8(&(bd->comm_flag), data + bytes);

		qq_filter_str(nick);
		bd->nickname = g_strdup(nick);
		g_free(nick);

#if 0
		purple_debug_info("QQ",
				"member [%d]: ext_flag=0x%02x, comm_flag=0x%02x, nick=%s\n",
				member_uid, bd->ext_flag, bd->comm_flag, bd->nickname);
#endif

		bd->last_update = time(NULL);
	}
	if (bytes > len) {
		purple_debug_error("QQ",
				"group_cmd_get_members_info: Dangerous error! maybe protocol changed, notify developers!");
	}
	purple_debug_info("QQ", "Group \"%s\" got %d member info\n", rmd->name, num);

	if (index)
	{
		qq_request_room_get_members_info(gc, id, 0, index);
		return;
	}
	rmd->has_got_members_info = TRUE;
	qq_room_conv_set_onlines(gc, rmd);
}
Example #11
0
void qq_process_room_cmd_get_info(guint8 *data, gint data_len, guint32 action, PurpleConnection *gc)
{
	qq_data *qd;
	qq_room_data *rmd;
	qq_buddy_data *bd;
	PurpleChat *chat;
	PurpleConversation *conv;
	guint8 organization, role;
	guint16 max_members;
	guint32 resend_flag, member_uid, id, qun_id, last_uid;
	gint bytes; 
	guint num=0;
	guint8 has_more=0;
	gchar *topic;

	g_return_if_fail(data != NULL && data_len > 0);
	qd = (qq_data *) gc->proto_data;

	/* qq_show_packet("Room Info", data, data_len); */

	bytes = 0;
	bytes += qq_get32(&id, data + bytes);
	g_return_if_fail(id > 0);

	bytes += qq_get32(&qun_id, data + bytes);
	g_return_if_fail(qun_id > 0);

	chat = qq_room_find_or_new(gc, id, qun_id);
	g_return_if_fail(chat != NULL);
	rmd = qq_room_data_find(gc, id);
	g_return_if_fail(rmd != NULL);

	bytes += qq_get32(&resend_flag, data + bytes);		//first 00 00 00 03, then 00 00 00 02

	if (resend_flag == 0x00000003)
	{
		bytes += qq_get8(&(rmd->type8), data + bytes);
		bytes += 4;	//maybe vip sign
		bytes += qq_get32(&(rmd->creator_uid), data + bytes);
		if (rmd->creator_uid == qd->uid)
			rmd->my_role = QQ_ROOM_ROLE_ADMIN;
		bytes += qq_get8(&(rmd->auth_type), data + bytes);
		bytes += 4	;	/* oldCategory */
		bytes += 2;	// 00 00
		bytes += qq_get32(&(rmd->category), data + bytes);
		bytes += qq_get16(&max_members, data + bytes);
		bytes += 1; 
		bytes += 8;
		purple_debug_info("QQ", "type: %u creator: %u category: %u max_members: %u\n",
			rmd->type8, rmd->creator_uid, rmd->category, max_members);

		bytes += qq_get_vstr(&(rmd->name), NULL, sizeof(guint8), data + bytes);
		bytes += 2;	/* 0x0000 */
		bytes += qq_get_vstr(&(rmd->bulletin), NULL, sizeof(guint8), data + bytes);
		bytes += qq_get_vstr(&(rmd->intro), NULL, sizeof(guint8), data + bytes);
		bytes += qq_get_vstr(&(rmd->token), NULL, sizeof(guint16), data + bytes);
		purple_debug_info("QQ", "room [%s] bulletin [%s] intro [%s] \n",
			rmd->name, rmd->bulletin, rmd->intro);
		bytes += 2;		//Unknown
		bytes += qq_get32(&last_uid, data + bytes);	/* last_uid of this recv, request more with it */
		bytes += qq_get8(&has_more, data + bytes);	/* if there are more, request again */
		/* now comes the member list separated by 0x00 */
	} else {
		/* resend_flag 00 00 00 02 is special, start with random one only 5 bytes */
		bytes += qq_get32(&member_uid, data + bytes);
		num++;
		bytes += qq_get8(&organization, data + bytes);
		bd = qq_room_buddy_find_or_new(gc, rmd, member_uid);
	}


	while (bytes < data_len) {
		bytes += qq_get32(&member_uid, data + bytes);
		num++;
		bytes += qq_get8(&organization, data + bytes);
		bytes += qq_get8(&role, data + bytes);

#if 0
		if(organization != 0 || role != 0) {
			purple_debug_info("QQ", "%u, organization=%d, role=%d\n", member_uid, organization, role);
		}
#endif
		
		bd = qq_room_buddy_find_or_new(gc, rmd, member_uid);
		if (bd != NULL)
			bd->role = role;
	}

	purple_debug_info("QQ", "Qun \"%s\" has received %d members\n", rmd->name, num);

	if (has_more)
	{
		qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_INFO, id, NULL, 0,
			0, last_uid);
	} else {
		qq_room_update_chat_info(chat, rmd);
		if (action == QQ_ROOM_INFO_DISPLAY) {
			room_info_display(gc, rmd);
		}

		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
			rmd->name, purple_connection_get_account(gc));
		if(NULL == conv) {
			purple_debug_warning("QQ", "Conversation \"%s\" is not opened\n", rmd->name);
			return;
		}

		topic = g_strdup_printf("%u %s", rmd->qun_id, rmd->bulletin);
		purple_debug_info("QQ", "Set chat topic to %s\n", topic);
		purple_conv_chat_set_topic(PURPLE_CONV_CHAT(conv), NULL, topic);
		g_free(topic);
	}
}