⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 im.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/** * @file im.c * * purple * * Purple is the legal property of its developers, whose names are too numerous * to list here.  Please refer to the COPYRIGHT file distributed with this * source distribution. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include "conversation.h"#include "debug.h"#include "internal.h"#include "notify.h"#include "server.h"#include "util.h"#include "buddy_info.h"#include "buddy_list.h"#include "buddy_opt.h"#include "char_conv.h"#include "crypt.h"#include "group_im.h"#include "header_info.h"#include "im.h"#include "packet_parse.h"#include "send_core.h"#include "send_file.h"#include "utils.h"#define QQ_SEND_IM_REPLY_OK       0x00#define DEFAULT_FONT_NAME_LEN 	  4/* a debug function */void _qq_show_packet(const gchar *desc, const guint8 *buf, gint len);enum{        QQ_NORMAL_IM_TEXT = 0x000b,	QQ_NORMAL_IM_FILE_REQUEST_TCP = 0x0001,	QQ_NORMAL_IM_FILE_APPROVE_TCP = 0x0003,	QQ_NORMAL_IM_FILE_REJECT_TCP = 0x0005,	QQ_NORMAL_IM_FILE_REQUEST_UDP = 0x0035,	QQ_NORMAL_IM_FILE_APPROVE_UDP = 0x0037,	QQ_NORMAL_IM_FILE_REJECT_UDP = 0x0039,	QQ_NORMAL_IM_FILE_NOTIFY = 0x003b,	QQ_NORMAL_IM_FILE_PASV = 0x003f,			/* are you behind a firewall? */	QQ_NORMAL_IM_FILE_CANCEL = 0x0049,	QQ_NORMAL_IM_FILE_EX_REQUEST_UDP = 0x81,	QQ_NORMAL_IM_FILE_EX_REQUEST_ACCEPT = 0x83,	QQ_NORMAL_IM_FILE_EX_REQUEST_CANCEL = 0x85,	QQ_NORMAL_IM_FILE_EX_NOTIFY_IP = 0x87};enum {	QQ_RECV_SYS_IM_KICK_OUT = 0x01};typedef struct _qq_recv_im_header qq_recv_im_header;typedef struct _qq_recv_normal_im_text qq_recv_normal_im_text;typedef struct _qq_recv_normal_im_common qq_recv_normal_im_common;typedef struct _qq_recv_normal_im_unprocessed qq_recv_normal_im_unprocessed;struct _qq_recv_normal_im_common {	/* this is the common part of normal_text */	guint16 sender_ver;	guint32 sender_uid;	guint32 receiver_uid;	guint8 *session_md5;	guint16 normal_im_type;};struct _qq_recv_normal_im_text {	qq_recv_normal_im_common *common;	/* now comes the part for text only */	guint16 msg_seq;	guint32 send_time;	guint16 sender_icon;	guint8 unknown2[3];	guint8 is_there_font_attr;	guint8 unknown3[4];	guint8 msg_type;	gchar *msg;		/* no fixed length, ends with 0x00 */	guint8 *font_attr;	gint font_attr_len;};struct _qq_recv_normal_im_unprocessed {	qq_recv_normal_im_common *common;	/* now comes the part of unprocessed */	guint8 *unknown;	/* no fixed length */	gint length;};struct _qq_recv_im_header {	guint32 sender_uid;	guint32 receiver_uid;	guint32 server_im_seq;	guint8 sender_ip[4];	guint16 sender_port;	guint16 im_type;};#define QQ_SEND_IM_AFTER_MSG_HEADER_LEN 8#define DEFAULT_FONT_NAME "\0xcb\0xce\0xcc\0xe5"guint8 *qq_get_send_im_tail(const gchar *font_color,			    const gchar *font_size,			    const gchar *font_name,			    gboolean is_bold, gboolean is_italic, gboolean is_underline, gint tail_len){	gchar *s1;	unsigned char *rgb;	gint font_name_len;	guint8 *send_im_tail;	const guint8 simsun[] = { 0xcb, 0xce, 0xcc, 0xe5 };	if (font_name) {		font_name_len = strlen(font_name);	} else {		font_name_len = DEFAULT_FONT_NAME_LEN;		font_name = (const gchar *) simsun;	}	send_im_tail = g_new0(guint8, tail_len);	g_strlcpy((gchar *) (send_im_tail + QQ_SEND_IM_AFTER_MSG_HEADER_LEN),		  font_name, tail_len - QQ_SEND_IM_AFTER_MSG_HEADER_LEN);	send_im_tail[tail_len - 1] = (guint8) tail_len;	send_im_tail[0] = 0x00;	if (font_size) {		send_im_tail[1] = (guint8) (atoi(font_size) * 3 + 1);	} else {		send_im_tail[1] = 10;	}	if (is_bold)		send_im_tail[1] |= 0x20;	if (is_italic)		send_im_tail[1] |= 0x40;	if (is_underline)		send_im_tail[1] |= 0x80;	if (font_color) {		s1 = g_strndup(font_color + 1, 6);		/* Henry: maybe this is a bug of purple, the string should have		 * the length of odd number @_@		 * George Ang: This BUG maybe fixed by Purple. adding new byte		 * would cause a crash.		 */		/* s2 = g_strdup_printf("%sH", s1); */		rgb = purple_base16_decode(s1, NULL);		g_free(s1);		/* g_free(s2); */		if (rgb)		{			memcpy(send_im_tail + 2, rgb, 3);			g_free(rgb);		} else {			send_im_tail[2] = send_im_tail[3] = send_im_tail[4] = 0;		}	} else {		send_im_tail[2] = send_im_tail[3] = send_im_tail[4] = 0;	}	send_im_tail[5] = 0x00;	send_im_tail[6] = 0x86;	send_im_tail[7] = 0x22;	/* encoding, 0x8622=GB, 0x0000=EN, define BIG5 support here */	_qq_show_packet("QQ_MESG", send_im_tail, tail_len);	return (guint8 *) send_im_tail;}static const gchar *qq_get_recv_im_type_str(gint type){	switch (type) {	case QQ_RECV_IM_TO_BUDDY:		return "QQ_RECV_IM_TO_BUDDY";	case QQ_RECV_IM_TO_UNKNOWN:		return "QQ_RECV_IM_TO_UNKNOWN";	case QQ_RECV_IM_UNKNOWN_QUN_IM:		return "QQ_RECV_IM_UNKNOWN_QUN_IM";	case QQ_RECV_IM_ADD_TO_QUN:		return "QQ_RECV_IM_ADD_TO_QUN";	case QQ_RECV_IM_DEL_FROM_QUN:		return "QQ_RECV_IM_DEL_FROM_QUN";	case QQ_RECV_IM_APPLY_ADD_TO_QUN:		return "QQ_RECV_IM_APPLY_ADD_TO_QUN";	case QQ_RECV_IM_CREATE_QUN:		return "QQ_RECV_IM_CREATE_QUN";	case QQ_RECV_IM_SYS_NOTIFICATION:		return "QQ_RECV_IM_SYS_NOTIFICATION";	case QQ_RECV_IM_APPROVE_APPLY_ADD_TO_QUN:		return "QQ_RECV_IM_APPROVE_APPLY_ADD_TO_QUN";	case QQ_RECV_IM_REJCT_APPLY_ADD_TO_QUN:		return "QQ_RECV_IM_REJCT_APPLY_ADD_TO_QUN";	case QQ_RECV_IM_TEMP_QUN_IM:		return "QQ_RECV_IM_TEMP_QUN_IM";	case QQ_RECV_IM_QUN_IM:		return "QQ_RECV_IM_QUN_IM";	default:		return "QQ_RECV_IM_UNKNOWN";	}}/* when we receive a message, * we send an ACK which is the first 16 bytes of incoming packet */static void _qq_send_packet_recv_im_ack(PurpleConnection *gc, guint16 seq, guint8 *data){	qq_send_cmd(gc, QQ_CMD_RECV_IM, FALSE, seq, FALSE, data, 16);}/* read the common parts of the normal_im, * returns the bytes read if succeed, or -1 if there is any error */static gint _qq_normal_im_common_read(guint8 *data, guint8 **cursor, gint len, qq_recv_normal_im_common *common){	gint bytes;	g_return_val_if_fail(data != NULL && len != 0 && common != NULL, -1);	bytes = 0;	/* now push data into common header */	bytes += read_packet_w(data, cursor, len, &(common->sender_ver));	bytes += read_packet_dw(data, cursor, len, &(common->sender_uid));	bytes += read_packet_dw(data, cursor, len, &(common->receiver_uid));	common->session_md5 = g_memdup(*cursor, QQ_KEY_LENGTH);	bytes += QQ_KEY_LENGTH;	*cursor += QQ_KEY_LENGTH;	bytes += read_packet_w(data, cursor, len, &(common->normal_im_type));	if (bytes != 28) {	/* read common place fail */		purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Expect 28 bytes, read %d bytes\n", bytes);		return -1;	}	return bytes;}/* process received normal text IM */static void _qq_process_recv_normal_im_text    (guint8 *data, guint8 **cursor, gint len, qq_recv_normal_im_common *common, PurpleConnection *gc){	guint16 purple_msg_type;	gchar *name;	gchar *msg_with_purple_smiley;	gchar *msg_utf8_encoded;	qq_data *qd;	qq_recv_normal_im_text *im_text;	g_return_if_fail(common != NULL);	qd = (qq_data *) gc->proto_data;	/* now it is QQ_NORMAL_IM_TEXT */	if (*cursor >= (data + len - 1)) {		purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Received normal IM text is empty\n");		return;	} else		im_text = g_newa(qq_recv_normal_im_text, 1);	im_text->common = common;	/* push data into im_text */	read_packet_w(data, cursor, len, &(im_text->msg_seq));	read_packet_dw(data, cursor, len, &(im_text->send_time));	read_packet_w(data, cursor, len, &(im_text->sender_icon));	read_packet_data(data, cursor, len, (guint8 *) & (im_text->unknown2), 3);	read_packet_b(data, cursor, len, &(im_text->is_there_font_attr));	/**	 * from lumaqq	for unknown3	 *	totalFragments = buf.get() & 255;         *	fragmentSequence = buf.get() & 255;         *	messageId = buf.getChar();	 */	read_packet_data(data, cursor, len, (guint8 *) & (im_text->unknown3), 4);	read_packet_b(data, cursor, len, &(im_text->msg_type));	/* we need to check if this is auto-reply	 * QQ2003iii build 0304, returns the msg without font_attr	 * even the is_there_font_attr shows 0x01, and msg does not ends with 0x00 */	if (im_text->msg_type == QQ_IM_AUTO_REPLY) {		im_text->is_there_font_attr = 0x00;	/* indeed there is no this flag */		im_text->msg = g_strndup(*(gchar **) cursor, data + len - *cursor);	} else {		/* it is normal mesasge */		if (im_text->is_there_font_attr) {			im_text->msg = g_strdup(*(gchar **) cursor);			*cursor += strlen(im_text->msg) + 1;			im_text->font_attr_len = data + len - *cursor;			im_text->font_attr = g_memdup(*cursor, im_text->font_attr_len);		} else		/* not im_text->is_there_font_attr */			im_text->msg = g_strndup(*(gchar **) cursor, data + len - *cursor);	}			/* if im_text->msg_type */	_qq_show_packet("QQ_MESG recv", data, *cursor - data);	name = uid_to_purple_name(common->sender_uid);	if (purple_find_buddy(gc->account, name) == NULL)		qq_add_buddy_by_recv_packet(gc, common->sender_uid, FALSE, TRUE);	purple_msg_type = (im_text->msg_type == QQ_IM_AUTO_REPLY) ? PURPLE_MESSAGE_AUTO_RESP : 0;	msg_with_purple_smiley = qq_smiley_to_purple(im_text->msg);	msg_utf8_encoded = im_text->is_there_font_attr ?	    qq_encode_to_purple(im_text->font_attr,			      im_text->font_attr_len,			      msg_with_purple_smiley) : qq_to_utf8(msg_with_purple_smiley, QQ_CHARSET_DEFAULT);	/* 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, name, msg_utf8_encoded, purple_msg_type, (time_t) im_text->send_time);	g_free(msg_utf8_encoded);	g_free(msg_with_purple_smiley);	g_free(name);	g_free(im_text->msg);	if (im_text->is_there_font_attr)		g_free(im_text->font_attr);}/* it is a normal IM, maybe text or video request */static void _qq_process_recv_normal_im(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc){	gint bytes;	qq_recv_normal_im_common *common;	qq_recv_normal_im_unprocessed *im_unprocessed;	gchar *hex_dump;	g_return_if_fail (data != NULL && len != 0);	if (*cursor >= (data + len - 1)) {		purple_debug (PURPLE_DEBUG_WARNING, "QQ",			    "Received normal IM is empty\n");		return;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -