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

📄 odc.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Purple's oscar protocol plugin * This file is the legal property of its developers. * Please see the AUTHORS file distributed alongside this file. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*//* From the oscar PRPL */#include "oscar.h"#include "peer.h"/* From Purple */#include "conversation.h"#include "imgstore.h"#include "util.h"/** * Free any ODC related data and print a message to the conversation * window based on conn->disconnect_reason. */voidpeer_odc_close(PeerConnection *conn){	gchar *tmp;	if (conn->disconnect_reason == OSCAR_DISCONNECT_REMOTE_CLOSED)		tmp = g_strdup(_("The remote user has closed the connection."));	else if (conn->disconnect_reason == OSCAR_DISCONNECT_REMOTE_REFUSED)		tmp = g_strdup(_("The remote user has declined your request."));	else if (conn->disconnect_reason == OSCAR_DISCONNECT_LOST_CONNECTION)		tmp = g_strdup_printf(_("Lost connection with the remote user:<br>%s"),				conn->error_message);	else if (conn->disconnect_reason == OSCAR_DISCONNECT_INVALID_DATA)		tmp = g_strdup(_("Received invalid data on connection with remote user."));	else if (conn->disconnect_reason == OSCAR_DISCONNECT_COULD_NOT_CONNECT)		tmp = g_strdup(_("Could not establish a connection with the remote user."));	else		/*		 * We shouldn't print a message for some disconnect_reasons.		 * Like OSCAR_DISCONNECT_LOCAL_CLOSED.		 */		tmp = NULL;	if (tmp != NULL)	{		PurpleAccount *account;		PurpleConversation *conv;		account = purple_connection_get_account(conn->od->gc);		conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->sn);		purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL));		g_free(tmp);	}	if (conn->frame != NULL)	{		OdcFrame *frame;		frame = conn->frame;		g_free(frame->payload.data);		g_free(frame);	}}/** * Write the given OdcFrame to a ByteStream and send it out * on the established PeerConnection. */static voidpeer_odc_send(PeerConnection *conn, OdcFrame *frame){	PurpleAccount *account;	const char *username;	size_t length;	ByteStream bs;	purple_debug_info("oscar", "Outgoing ODC frame to %s with "		"type=0x%04x, flags=0x%04x, payload length=%u\n",		conn->sn, frame->type, frame->flags, frame->payload.len);	account = purple_connection_get_account(conn->od->gc);	username = purple_account_get_username(account);	memcpy(frame->sn, username, strlen(username));	memcpy(frame->cookie, conn->cookie, 8);	length = 76;	byte_stream_new(&bs, length + frame->payload.len);	byte_stream_putraw(&bs, conn->magic, 4);	byte_stream_put16(&bs, length);	byte_stream_put16(&bs, frame->type);	byte_stream_put16(&bs, frame->subtype);	byte_stream_put16(&bs, 0x0000);	byte_stream_putraw(&bs, frame->cookie, 8);	byte_stream_put16(&bs, 0x0000);	byte_stream_put16(&bs, 0x0000);	byte_stream_put16(&bs, 0x0000);	byte_stream_put16(&bs, 0x0000);	byte_stream_put32(&bs, frame->payload.len);	byte_stream_put16(&bs, 0x0000);	byte_stream_put16(&bs, frame->encoding);	byte_stream_put16(&bs, 0x0000);	byte_stream_put16(&bs, frame->flags);	byte_stream_put16(&bs, 0x0000);	byte_stream_put16(&bs, 0x0000);	byte_stream_putraw(&bs, frame->sn, 32);	byte_stream_putraw(&bs, frame->payload.data, frame->payload.len);	peer_connection_send(conn, &bs);	g_free(bs.data);}/** * Send a very basic ODC frame (which contains the cookie) so that the * remote user can verify that we are the person they were expecting. * If we made an outgoing connection to then remote user, then we send * this immediately.  If the remote user connected to us, then we wait * for the other person to send this to us, then we send one to them. */voidpeer_odc_send_cookie(PeerConnection *conn){	OdcFrame frame;	memset(&frame, 0, sizeof(OdcFrame));	frame.type = 0x0001;	frame.subtype = 0x0006;	frame.flags = 0x0060; /* Maybe this means "we're sending the cookie"? */	peer_odc_send(conn, &frame);}/** * Send client-to-client typing notification over an established direct connection. */voidpeer_odc_send_typing(PeerConnection *conn, PurpleTypingState typing){	OdcFrame frame;	memset(&frame, 0, sizeof(OdcFrame));	frame.type = 0x0001;	frame.subtype = 0x0006;	if (typing == PURPLE_TYPING)		frame.flags = 0x0002 | 0x0008;	else if (typing == PURPLE_TYPED)		frame.flags = 0x0002 | 0x0004;	else		frame.flags = 0x0002;	peer_odc_send(conn, &frame);}/** * Send client-to-client IM over an established direct connection. * To send a direct IM, call this just like you would aim_send_im. * * @param conn The already-connected ODC connection. * @param msg Null-terminated string to send. * @param len The length of the message to send, including binary data. * @param encoding See the AIM_CHARSET_* defines in oscar.h * @param autoreply TRUE if this is any auto-reply. */voidpeer_odc_send_im(PeerConnection *conn, const char *msg, int len, int encoding, gboolean autoreply){	OdcFrame frame;	g_return_if_fail(msg != NULL);	g_return_if_fail(len > 0);	memset(&frame, 0, sizeof(OdcFrame));	frame.type = 0x0001;	frame.subtype = 0x0006;	frame.payload.len = len;	frame.encoding = encoding;	frame.flags = autoreply;	byte_stream_new(&frame.payload, len);	byte_stream_putraw(&frame.payload, (guint8 *)msg, len);	peer_odc_send(conn, &frame);	g_free(frame.payload.data);}struct embedded_data{	size_t size;	const guint8 *data;};/** * This is called after a direct IM has been received in its entirety.  This * function is passed a long chunk of data which contains the IM with any * data chunks (images) appended to it. * * This function rips out all the data chunks and creates an imgstore for * each one.  In order to do this, it first goes through the IM and takes * out all the IMG tags.  When doing so, it rewrites the original IMG tag * with one compatible with the imgstore Purple core code. For each one, we * then read in chunks of data from the end of the message and actually * create the img store using the given data. * * For somewhat easy reference, here's a sample message * (with added whitespace): * * <HTML><BODY BGCOLOR="#ffffff"> *     <FONT LANG="0"> *     This is a really stupid picture:<BR> *     <IMG SRC="Sample.jpg" ID="1" WIDTH="283" HEIGHT="212" DATASIZE="9894"><BR> *     Yeah it is<BR> *     Here is another one:<BR> *     <IMG SRC="Soap Bubbles.bmp" ID="2" WIDTH="256" HEIGHT="256" DATASIZE="65978"> *     </FONT> * </BODY></HTML> * <BINARY> *     <DATA ID="1" SIZE="9894">datadatadatadata</DATA> *     <DATA ID="2" SIZE="65978">datadatadatadata</DATA> * </BINARY> */static voidpeer_odc_handle_payload(PeerConnection *conn, const char *msg, size_t len, int encoding, gboolean autoreply){	PurpleConnection *gc;	PurpleAccount *account;	const char *msgend, *binary_start, *dataend;	const char *tmp, *start, *end, *idstr, *src, *sizestr;	GData *attributes;	GHashTable *embedded_datas;	struct embedded_data *embedded_data;	GSList *images;	gchar *utf8;	GString *newmsg;	PurpleMessageFlags imflags;	gc = conn->od->gc;	account = purple_connection_get_account(gc);	dataend = msg + len;	/*	 * Create a hash table containing references to each embedded	 * data chunk.  The key is the "ID" and the value is an	 * embedded_data struct.	 */	embedded_datas = g_hash_table_new_full(g_direct_hash,			g_direct_equal, NULL, g_free);	/*	 * Create an index of any binary chunks.  If we run into any	 * problems while parsing the binary data section then we stop	 * parsing it, and the local user will see broken image icons.	 */	/* TODO: Use a length argument when looking for the <binary> tag! */	binary_start = purple_strcasestr(msg, "<binary>");	if (binary_start == NULL)		msgend = dataend;	else	{		msgend = binary_start;		/* Move our pointer to immediately after the <binary> tag */		tmp = binary_start + 8;		/* The embedded binary markup has a mimimum length of 29 bytes */		/* TODO: Use a length argument when looking for the <data> tag! */		while ((tmp + 29 <= dataend) &&				purple_markup_find_tag("data", tmp, &start, &tmp, &attributes))		{			unsigned int id;			size_t size;			/* Move the binary pointer from ">" to the start of the data */			tmp++;			/* Get the ID */			idstr = g_datalist_get_data(&attributes, "id");			if (idstr == NULL)			{				g_datalist_clear(&attributes);				break;			}			id = atoi(idstr);			/* Get the size */			sizestr = g_datalist_get_data(&attributes, "size");			if (sizestr == NULL)			{				g_datalist_clear(&attributes);

⌨️ 快捷键说明

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