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

📄 wb.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
字号:
/*  wb.c  Author: Pekka Riikonen <priikone@silcnet.org>  Copyright (C) 2005 Pekka Riikonen  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; version 2 of the License.  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.*/#include "silcincludes.h"#include "silcclient.h"#include "silcpurple.h"#include "wb.h"/*  SILC Whiteboard packet:  1 byte	command  2 bytes	width  2 bytes	height  4 bytes	brush color  2 bytes	brush size  n bytes	data   Data:  4 bytes	x  4 bytes	y  Commands:  0x01		draw  0x02		clear  MIME:  MIME-Version: 1.0  Content-Type: application/x-wb  Content-Transfer-Encoding: binary*/#define SILCPURPLE_WB_MIME "MIME-Version: 1.0\r\nContent-Type: application/x-wb\r\nContent-Transfer-Encoding: binary\r\n\r\n"#define SILCPURPLE_WB_HEADER strlen(SILCPURPLE_WB_MIME) + 11#define SILCPURPLE_WB_WIDTH 500#define SILCPURPLE_WB_HEIGHT 400#define SILCPURPLE_WB_WIDTH_MAX 1024#define SILCPURPLE_WB_HEIGHT_MAX 1024/* Commands */typedef enum {	SILCPURPLE_WB_DRAW 	= 0x01,	SILCPURPLE_WB_CLEAR	= 0x02,} SilcPurpleWbCommand;/* Brush size */typedef enum {	SILCPURPLE_WB_BRUSH_SMALL = 2,	SILCPURPLE_WB_BRUSH_MEDIUM = 5,	SILCPURPLE_WB_BRUSH_LARGE = 10,} SilcPurpleWbBrushSize;/* Brush color (XXX Purple should provide default colors) */typedef enum {	SILCPURPLE_WB_COLOR_BLACK		= 0,	SILCPURPLE_WB_COLOR_RED		= 13369344,	SILCPURPLE_WB_COLOR_GREEN		= 52224,	SILCPURPLE_WB_COLOR_BLUE		= 204,	SILCPURPLE_WB_COLOR_YELLOW 	= 15658496,	SILCPURPLE_WB_COLOR_ORANGE	= 16737792,	SILCPURPLE_WB_COLOR_CYAN		= 52428,	SILCPURPLE_WB_COLOR_VIOLET	= 5381277,	SILCPURPLE_WB_COLOR_PURPLE	= 13369548,	SILCPURPLE_WB_COLOR_TAN		= 12093547,	SILCPURPLE_WB_COLOR_BROWN		= 5256485,	SILCPURPLE_WB_COLOR_GREY		= 11184810,	SILCPURPLE_WB_COLOR_WHITE		= 16777215,} SilcPurpleWbColor;typedef struct {	int type;		/* 0 = buddy, 1 = channel */	union {		SilcClientEntry client;		SilcChannelEntry channel;	} u;	int width;	int height;	int brush_size;	int brush_color;} *SilcPurpleWb;/* Initialize whiteboard */PurpleWhiteboard *silcpurple_wb_init(SilcPurple sg, SilcClientEntry client_entry){        SilcClientConnection conn;	PurpleWhiteboard *wb;	SilcPurpleWb wbs;	conn = sg->conn;	wb = purple_whiteboard_get_session(sg->account, client_entry->nickname);	if (!wb)		wb = purple_whiteboard_create(sg->account, client_entry->nickname, 0);	if (!wb)		return NULL;	if (!wb->proto_data) {		wbs = silc_calloc(1, sizeof(*wbs));		if (!wbs)			return NULL;		wbs->type = 0;		wbs->u.client = client_entry;		wbs->width = SILCPURPLE_WB_WIDTH;		wbs->height = SILCPURPLE_WB_HEIGHT;		wbs->brush_size = SILCPURPLE_WB_BRUSH_SMALL;		wbs->brush_color = SILCPURPLE_WB_COLOR_BLACK;		wb->proto_data = wbs;		/* Start the whiteboard */		purple_whiteboard_start(wb);		purple_whiteboard_clear(wb);	}	return wb;}PurpleWhiteboard *silcpurple_wb_init_ch(SilcPurple sg, SilcChannelEntry channel){	PurpleWhiteboard *wb;	SilcPurpleWb wbs;	wb = purple_whiteboard_get_session(sg->account, channel->channel_name);	if (!wb)		wb = purple_whiteboard_create(sg->account, channel->channel_name, 0);	if (!wb)		return NULL;	if (!wb->proto_data) {		wbs = silc_calloc(1, sizeof(*wbs));		if (!wbs)			return NULL;		wbs->type = 1;		wbs->u.channel = channel;		wbs->width = SILCPURPLE_WB_WIDTH;		wbs->height = SILCPURPLE_WB_HEIGHT;		wbs->brush_size = SILCPURPLE_WB_BRUSH_SMALL;		wbs->brush_color = SILCPURPLE_WB_COLOR_BLACK;		wb->proto_data = wbs;		/* Start the whiteboard */		purple_whiteboard_start(wb);		purple_whiteboard_clear(wb);	}	return wb;}static voidsilcpurple_wb_parse(SilcPurpleWb wbs, PurpleWhiteboard *wb,		  unsigned char *message, SilcUInt32 message_len){	SilcUInt8 command;	SilcUInt16 width, height, brush_size;	SilcUInt32 brush_color, x, y, dx, dy;	SilcBufferStruct buf;	int ret;	/* Parse the packet */	silc_buffer_set(&buf, message, message_len);	ret = silc_buffer_unformat(&buf,				   SILC_STR_UI_CHAR(&command),				   SILC_STR_UI_SHORT(&width),				   SILC_STR_UI_SHORT(&height),				   SILC_STR_UI_INT(&brush_color),				   SILC_STR_UI_SHORT(&brush_size),				   SILC_STR_END);	if (ret < 0)		return;	silc_buffer_pull(&buf, ret);	/* Update whiteboard if its dimensions changed */	if (width != wbs->width || height != wbs->height)		silcpurple_wb_set_dimensions(wb, height, width);	if (command == SILCPURPLE_WB_DRAW) {		/* Parse data and draw it */		ret = silc_buffer_unformat(&buf,					   SILC_STR_UI_INT(&dx),					   SILC_STR_UI_INT(&dy),					   SILC_STR_END);		if (ret < 0)			return;		silc_buffer_pull(&buf, 8);		x = dx;		y = dy;		while (buf.len > 0) {			ret = silc_buffer_unformat(&buf,						   SILC_STR_UI_INT(&dx),						   SILC_STR_UI_INT(&dy),						   SILC_STR_END);			if (ret < 0)				return;			silc_buffer_pull(&buf, 8);			purple_whiteboard_draw_line(wb, x, y, x + dx, y + dy,						  brush_color, brush_size);			x += dx;			y += dy;		}	}	if (command == SILCPURPLE_WB_CLEAR)		purple_whiteboard_clear(wb);}typedef struct {  unsigned char *message;  SilcUInt32 message_len;  SilcPurple sg;  SilcClientEntry sender;  SilcChannelEntry channel;} *SilcPurpleWbRequest;static voidsilcpurple_wb_request_cb(SilcPurpleWbRequest req, gint id){	PurpleWhiteboard *wb;        if (id != 1)                goto out;	if (!req->channel)		wb = silcpurple_wb_init(req->sg, req->sender);	else		wb = silcpurple_wb_init_ch(req->sg, req->channel);	silcpurple_wb_parse(wb->proto_data, wb, req->message, req->message_len);  out:	silc_free(req->message);	silc_free(req);}static voidsilcpurple_wb_request(SilcClient client, const unsigned char *message, 		    SilcUInt32 message_len, SilcClientEntry sender, 		    SilcChannelEntry channel){	char tmp[128];	SilcPurpleWbRequest req;	PurpleConnection *gc;	SilcPurple sg;	gc = client->application;	sg = gc->proto_data;	/* Open whiteboard automatically if requested */	if (purple_account_get_bool(sg->account, "open-wb", FALSE)) {		PurpleWhiteboard *wb;		if (!channel)			wb = silcpurple_wb_init(sg, sender);		else			wb = silcpurple_wb_init_ch(sg, channel);		silcpurple_wb_parse(wb->proto_data, wb, (unsigned char *)message,				  message_len);		return;	}	if (!channel) {		g_snprintf(tmp, sizeof(tmp),			_("%s sent message to whiteboard. Would you like "			  "to open the whiteboard?"), sender->nickname);	} else {		g_snprintf(tmp, sizeof(tmp),			_("%s sent message to whiteboard on %s channel. "			  "Would you like to open the whiteboard?"),			sender->nickname, channel->channel_name);	}	req = silc_calloc(1, sizeof(*req));	if (!req)		return;	req->message = silc_memdup(message, message_len);	req->message_len = message_len;	req->sender = sender;	req->channel = channel;	req->sg = sg;	purple_request_action(gc, _("Whiteboard"), tmp, NULL, 1,				sg->account, sender->nickname, NULL, req, 2,			    _("Yes"), G_CALLBACK(silcpurple_wb_request_cb),			    _("No"), G_CALLBACK(silcpurple_wb_request_cb));}/* Process incoming whiteboard message */void silcpurple_wb_receive(SilcClient client, SilcClientConnection conn,			 SilcClientEntry sender, SilcMessagePayload payload,			 SilcMessageFlags flags, const unsigned char *message,			 SilcUInt32 message_len){	SilcPurple sg;        PurpleConnection *gc;	PurpleWhiteboard *wb;	SilcPurpleWb wbs;	gc = client->application;        sg = gc->proto_data;	wb = purple_whiteboard_get_session(sg->account, sender->nickname);	if (!wb) {		/* Ask user if they want to open the whiteboard */		silcpurple_wb_request(client, message, message_len,				    sender, NULL);		return;	}	wbs = wb->proto_data;	silcpurple_wb_parse(wbs, wb, (unsigned char *)message, message_len);}/* Process incoming whiteboard message on channel */void silcpurple_wb_receive_ch(SilcClient client, SilcClientConnection conn,			    SilcClientEntry sender, SilcChannelEntry channel,			    SilcMessagePayload payload,			    SilcMessageFlags flags,			    const unsigned char *message,			    SilcUInt32 message_len){	SilcPurple sg;        PurpleConnection *gc;	PurpleWhiteboard *wb;	SilcPurpleWb wbs;	gc = client->application;        sg = gc->proto_data;	wb = purple_whiteboard_get_session(sg->account, channel->channel_name);	if (!wb) {		/* Ask user if they want to open the whiteboard */		silcpurple_wb_request(client, message, message_len,				    sender, channel);		return;	}	wbs = wb->proto_data;	silcpurple_wb_parse(wbs, wb, (unsigned char *)message, message_len);}/* Send whiteboard message */void silcpurple_wb_send(PurpleWhiteboard *wb, GList *draw_list){	SilcPurpleWb wbs = wb->proto_data;	SilcBuffer packet;	GList *list;	int len;        PurpleConnection *gc;        SilcPurple sg;	g_return_if_fail(draw_list);	gc = purple_account_get_connection(wb->account);	g_return_if_fail(gc); 	sg = gc->proto_data;	g_return_if_fail(sg);	len = SILCPURPLE_WB_HEADER;	for (list = draw_list; list; list = list->next)		len += 4;	packet = silc_buffer_alloc_size(len);	if (!packet)		return;	/* Assmeble packet */	silc_buffer_format(packet,			   SILC_STR_UI32_STRING(SILCPURPLE_WB_MIME),			   SILC_STR_UI_CHAR(SILCPURPLE_WB_DRAW),			   SILC_STR_UI_SHORT(wbs->width),			   SILC_STR_UI_SHORT(wbs->height),			   SILC_STR_UI_INT(wbs->brush_color),			   SILC_STR_UI_SHORT(wbs->brush_size),			   SILC_STR_END);	silc_buffer_pull(packet, SILCPURPLE_WB_HEADER);	for (list = draw_list; list; list = list->next) {		silc_buffer_format(packet,				   SILC_STR_UI_INT(GPOINTER_TO_INT(list->data)),				   SILC_STR_END);		silc_buffer_pull(packet, 4);	}	/* Send the message */	if (wbs->type == 0) {		/* Private message */		silc_client_send_private_message(sg->client, sg->conn, 						 wbs->u.client, 						 SILC_MESSAGE_FLAG_DATA,						 packet->head, len, TRUE);	} else if (wbs->type == 1) {		/* Channel message. Channel private keys are not supported. */		silc_client_send_channel_message(sg->client, sg->conn,						 wbs->u.channel, NULL,						 SILC_MESSAGE_FLAG_DATA,						 packet->head, len, TRUE);	}	silc_buffer_free(packet);}/* Purple Whiteboard operations */void silcpurple_wb_start(PurpleWhiteboard *wb){	/* Nothing here.  Everything is in initialization */}void silcpurple_wb_end(PurpleWhiteboard *wb){	silc_free(wb->proto_data);	wb->proto_data = NULL;}void silcpurple_wb_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height){	SilcPurpleWb wbs = wb->proto_data;	*width = wbs->width;	*height = wbs->height;}void silcpurple_wb_set_dimensions(PurpleWhiteboard *wb, int width, int height){	SilcPurpleWb wbs = wb->proto_data;	wbs->width = width > SILCPURPLE_WB_WIDTH_MAX ? SILCPURPLE_WB_WIDTH_MAX :			width;	wbs->height = height > SILCPURPLE_WB_HEIGHT_MAX ? SILCPURPLE_WB_HEIGHT_MAX :			height;	/* Update whiteboard */	purple_whiteboard_set_dimensions(wb, wbs->width, wbs->height);}void silcpurple_wb_get_brush(const PurpleWhiteboard *wb, int *size, int *color){	SilcPurpleWb wbs = wb->proto_data;	*size = wbs->brush_size;	*color = wbs->brush_color;}void silcpurple_wb_set_brush(PurpleWhiteboard *wb, int size, int color){	SilcPurpleWb wbs = wb->proto_data;	wbs->brush_size = size;	wbs->brush_color = color;	/* Update whiteboard */	purple_whiteboard_set_brush(wb, size, color);}void silcpurple_wb_clear(PurpleWhiteboard *wb){	SilcPurpleWb wbs = wb->proto_data;	SilcBuffer packet;	int len;        PurpleConnection *gc;        SilcPurple sg;	gc = purple_account_get_connection(wb->account);	g_return_if_fail(gc); 	sg = gc->proto_data;	g_return_if_fail(sg);	len = SILCPURPLE_WB_HEADER;	packet = silc_buffer_alloc_size(len);	if (!packet)		return;	/* Assmeble packet */	silc_buffer_format(packet,			   SILC_STR_UI32_STRING(SILCPURPLE_WB_MIME),			   SILC_STR_UI_CHAR(SILCPURPLE_WB_CLEAR),			   SILC_STR_UI_SHORT(wbs->width),			   SILC_STR_UI_SHORT(wbs->height),			   SILC_STR_UI_INT(wbs->brush_color),			   SILC_STR_UI_SHORT(wbs->brush_size),			   SILC_STR_END);	/* Send the message */	if (wbs->type == 0) {		/* Private message */		silc_client_send_private_message(sg->client, sg->conn, 						 wbs->u.client, 						 SILC_MESSAGE_FLAG_DATA,						 packet->head, len, TRUE);	} else if (wbs->type == 1) {		/* Channel message */		silc_client_send_channel_message(sg->client, sg->conn,						 wbs->u.channel, NULL,						 SILC_MESSAGE_FLAG_DATA,						 packet->head, len, TRUE);	}	silc_buffer_free(packet);}

⌨️ 快捷键说明

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