From: Ethan B. <ebl...@us...> - 2005-11-12 23:04:55
|
Update of /cvsroot/gaim/gaim/src/protocols/silc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv1476/src/protocols/silc Modified Files: buddy.c chat.c ops.c silc.c Added Files: wb.c wb.h Log Message: SILC whiteboard support from Pekka Riikonen. --- NEW FILE: wb.c --- /* wb.c Author: Pekka Riikonen <pri...@si...> 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 "silcgaim.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 SILCGAIM_WB_MIME "MIME-Version: 1.0\r\nContent-Type: application/x-wb\r\nContent-Transfer-Encoding: binary\r\n\r\n" #define SILCGAIM_WB_HEADER strlen(SILCGAIM_WB_MIME) + 11 #define SILCGAIM_WB_WIDTH 500 #define SILCGAIM_WB_HEIGHT 400 #define SILCGAIM_WB_WIDTH_MAX 1024 #define SILCGAIM_WB_HEIGHT_MAX 1024 /* Commands */ typedef enum { SILCGAIM_WB_DRAW = 0x01, SILCGAIM_WB_CLEAR = 0x02, } SilcGaimWbCommand; /* Brush size */ typedef enum { SILCGAIM_WB_BRUSH_SMALL = 2, SILCGAIM_WB_BRUSH_MEDIUM = 5, SILCGAIM_WB_BRUSH_LARGE = 10, } SilcGaimWbBrushSize; /* Brush color (XXX Gaim should provide default colors) */ typedef enum { SILCGAIM_WB_COLOR_BLACK = 0, SILCGAIM_WB_COLOR_RED = 13369344, SILCGAIM_WB_COLOR_GREEN = 52224, SILCGAIM_WB_COLOR_BLUE = 204, SILCGAIM_WB_COLOR_YELLOW = 15658496, SILCGAIM_WB_COLOR_ORANGE = 16737792, SILCGAIM_WB_COLOR_CYAN = 52428, SILCGAIM_WB_COLOR_VIOLET = 5381277, SILCGAIM_WB_COLOR_PURPLE = 13369548, SILCGAIM_WB_COLOR_TAN = 12093547, SILCGAIM_WB_COLOR_BROWN = 5256485, SILCGAIM_WB_COLOR_GREY = 11184810, SILCGAIM_WB_COLOR_WHITE = 16777215, } SilcGaimWbColor; typedef struct { int type; /* 0 = buddy, 1 = channel */ union { SilcClientEntry client; SilcChannelEntry channel; } u; int width; int height; int brush_size; int brush_color; } *SilcGaimWb; /* Initialize whiteboard */ GaimWhiteboard *silcgaim_wb_init(SilcGaim sg, SilcClientEntry client_entry) { SilcClientConnection conn; GaimWhiteboard *wb; SilcGaimWb wbs; conn = sg->conn; wb = gaim_whiteboard_get_session(sg->account, client_entry->nickname); if (!wb) wb = gaim_whiteboard_create(sg->account, client_entry->nickname, 0); if (!wb) return NULL; wbs = silc_calloc(1, sizeof(*wbs)); if (!wbs) return NULL; wbs->type = 0; wbs->u.client = client_entry; wbs->width = SILCGAIM_WB_WIDTH; wbs->height = SILCGAIM_WB_HEIGHT; wbs->brush_size = SILCGAIM_WB_BRUSH_SMALL; wbs->brush_color = SILCGAIM_WB_COLOR_BLACK; wb->proto_data = wbs; /* Start the whiteboard */ gaim_whiteboard_start(wb); gaim_whiteboard_clear(wb); return wb; } GaimWhiteboard *silcgaim_wb_init_ch(SilcGaim sg, SilcChannelEntry channel) { GaimWhiteboard *wb; SilcGaimWb wbs; wb = gaim_whiteboard_get_session(sg->account, channel->channel_name); if (!wb) wb = gaim_whiteboard_create(sg->account, channel->channel_name, 0); if (!wb) return NULL; wbs = silc_calloc(1, sizeof(*wbs)); if (!wbs) return NULL; wbs->type = 1; wbs->u.channel = channel; wbs->width = SILCGAIM_WB_WIDTH; wbs->height = SILCGAIM_WB_HEIGHT; wbs->brush_size = SILCGAIM_WB_BRUSH_SMALL; wbs->brush_color = SILCGAIM_WB_COLOR_BLACK; wb->proto_data = wbs; /* Start the whiteboard */ gaim_whiteboard_start(wb); gaim_whiteboard_clear(wb); return wb; } static void silcgaim_wb_parse(SilcGaimWb wbs, GaimWhiteboard *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) silcgaim_wb_set_dimensions(wb, height, width); if (command == SILCGAIM_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); gaim_whiteboard_draw_line(wb, x, y, x + dx, y + dy, brush_color, brush_size); x += dx; y += dy; } } if (command == SILCGAIM_WB_CLEAR) gaim_whiteboard_clear(wb); } typedef struct { unsigned char *message; SilcUInt32 message_len; SilcGaim sg; SilcClientEntry sender; SilcChannelEntry channel; } *SilcGaimWbRequest; static void silcgaim_wb_request_cb(SilcGaimWbRequest req, gint id) { GaimWhiteboard *wb; if (id != 1) goto out; if (!req->channel) wb = silcgaim_wb_init(req->sg, req->sender); else wb = silcgaim_wb_init_ch(req->sg, req->channel); silcgaim_wb_parse(wb->proto_data, wb, req->message, req->message_len); out: silc_free(req->message); silc_free(req); } static void silcgaim_wb_request(SilcClient client, const unsigned char *message, SilcUInt32 message_len, SilcClientEntry sender, SilcChannelEntry channel) { char tmp[128]; SilcGaimWbRequest req; GaimConnection *gc; SilcGaim sg; 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); } gc = client->application; sg = gc->proto_data; 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; gaim_request_action(gc, _("Whiteboard"), tmp, NULL, 1, req, 2, _("Yes"), G_CALLBACK(silcgaim_wb_request_cb), _("No"), G_CALLBACK(silcgaim_wb_request_cb)); } /* Process incoming whiteboard message */ void silcgaim_wb_receive(SilcClient client, SilcClientConnection conn, SilcClientEntry sender, SilcMessagePayload payload, SilcMessageFlags flags, const unsigned char *message, SilcUInt32 message_len) { SilcGaim sg; GaimConnection *gc; GaimWhiteboard *wb; SilcGaimWb wbs; gc = client->application; sg = gc->proto_data; wb = gaim_whiteboard_get_session(sg->account, sender->nickname); if (!wb) { /* Ask user if they want to open the whiteboard */ silcgaim_wb_request(client, message, message_len, sender, NULL); return; } wbs = wb->proto_data; silcgaim_wb_parse(wbs, wb, (unsigned char *)message, message_len); } /* Process incoming whiteboard message on channel */ void silcgaim_wb_receive_ch(SilcClient client, SilcClientConnection conn, SilcClientEntry sender, SilcChannelEntry channel, SilcMessagePayload payload, SilcMessageFlags flags, const unsigned char *message, SilcUInt32 message_len) { SilcGaim sg; GaimConnection *gc; GaimWhiteboard *wb; SilcGaimWb wbs; gc = client->application; sg = gc->proto_data; wb = gaim_whiteboard_get_session(sg->account, channel->channel_name); if (!wb) { /* Ask user if they want to open the whiteboard */ silcgaim_wb_request(client, message, message_len, sender, channel); return; } wbs = wb->proto_data; silcgaim_wb_parse(wbs, wb, (unsigned char *)message, message_len); } /* Send whiteboard message */ void silcgaim_wb_send(GaimWhiteboard *wb, GList *draw_list) { SilcGaimWb wbs = wb->proto_data; SilcBuffer packet; GList *list; int len; GaimConnection *gc; SilcGaim sg; g_return_if_fail(draw_list); gc = gaim_account_get_connection(wb->account); g_return_if_fail(gc); sg = gc->proto_data; g_return_if_fail(sg); len = SILCGAIM_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(SILCGAIM_WB_MIME), SILC_STR_UI_CHAR(SILCGAIM_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, SILCGAIM_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 */ 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); } /* Gaim Whiteboard operations */ void silcgaim_wb_start(GaimWhiteboard *wb) { /* Nothing here. Everything is in initialization */ } void silcgaim_wb_end(GaimWhiteboard *wb) { silc_free(wb->proto_data); wb->proto_data = NULL; } void silcgaim_wb_get_dimensions(GaimWhiteboard *wb, int *width, int *height) { SilcGaimWb wbs = wb->proto_data; *width = wbs->width; *height = wbs->height; } void silcgaim_wb_set_dimensions(GaimWhiteboard *wb, int width, int height) { SilcGaimWb wbs = wb->proto_data; wbs->width = width > SILCGAIM_WB_WIDTH_MAX ? SILCGAIM_WB_WIDTH_MAX : width; wbs->height = height > SILCGAIM_WB_HEIGHT_MAX ? SILCGAIM_WB_HEIGHT_MAX : height; /* Update whiteboard */ gaim_whiteboard_set_dimensions(wb, width, height); } void silcgaim_wb_get_brush(GaimWhiteboard *wb, int *size, int *color) { SilcGaimWb wbs = wb->proto_data; *size = wbs->brush_size; *color = wbs->brush_color; } void silcgaim_wb_set_brush(GaimWhiteboard *wb, int size, int color) { SilcGaimWb wbs = wb->proto_data; wbs->brush_size = size; wbs->brush_color = color; /* Update whiteboard */ gaim_whiteboard_set_brush(wb, size, color); } void silcgaim_wb_clear(GaimWhiteboard *wb) { SilcGaimWb wbs = wb->proto_data; SilcBuffer packet; int len; GaimConnection *gc; SilcGaim sg; gc = gaim_account_get_connection(wb->account); g_return_if_fail(gc); sg = gc->proto_data; g_return_if_fail(sg); len = SILCGAIM_WB_HEADER; packet = silc_buffer_alloc_size(len); if (!packet) return; /* Assmeble packet */ silc_buffer_format(packet, SILC_STR_UI32_STRING(SILCGAIM_WB_MIME), SILC_STR_UI_CHAR(SILCGAIM_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); } --- NEW FILE: wb.h --- /* silcgaim.h Author: Pekka Riikonen <pri...@si...> 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. */ #ifndef SILCGAIM_WB_H #define SILCGAIM_WB_H #include "silcgaim.h" #include "whiteboard.h" GaimWhiteboard * silcgaim_wb_init(SilcGaim sg, SilcClientEntry client_entry); GaimWhiteboard * silcgaim_wb_init_ch(SilcGaim sg, SilcChannelEntry channel); void silcgaim_wb_receive(SilcClient client, SilcClientConnection conn, SilcClientEntry sender, SilcMessagePayload payload, SilcMessageFlags flags, const unsigned char *message, SilcUInt32 message_len); void silcgaim_wb_receive_ch(SilcClient client, SilcClientConnection conn, SilcClientEntry sender, SilcChannelEntry channel, SilcMessagePayload payload, SilcMessageFlags flags, const unsigned char *message, SilcUInt32 message_len); void silcgaim_wb_start(GaimWhiteboard *wb); void silcgaim_wb_end(GaimWhiteboard *wb); void silcgaim_wb_get_dimensions(GaimWhiteboard *wb, int *width, int *height); void silcgaim_wb_set_dimensions(GaimWhiteboard *wb, int width, int height); void silcgaim_wb_get_brush(GaimWhiteboard *wb, int *size, int *color); void silcgaim_wb_set_brush(GaimWhiteboard *wb, int size, int color); void silcgaim_wb_send(GaimWhiteboard *wb, GList *draw_list); void silcgaim_wb_clear(GaimWhiteboard *wb); #endif /* SILCGAIM_WB_H */ Index: buddy.c =================================================================== RCS file: /cvsroot/gaim/gaim/src/protocols/silc/buddy.c,v retrieving revision 1.30 retrieving revision 1.31 diff -u -d -p -r1.30 -r1.31 --- buddy.c 2 Oct 2005 16:50:08 -0000 1.30 +++ buddy.c 12 Nov 2005 23:04:44 -0000 1.31 @@ -20,6 +20,7 @@ #include "silcincludes.h" #include "silcclient.h" #include "silcgaim.h" +#include "wb.h" /***************************** Key Agreement *********************************/ @@ -1547,9 +1548,21 @@ silcgaim_buddy_kill(GaimBlistNode *node, b->name, "Killed by operator", NULL); } -GList *silcgaim_buddy_menu(GaimBuddy *buddy) +typedef struct { + SilcGaim sg; + SilcClientEntry client_entry; +} *SilcGaimBuddyWb; + +static void +silcgaim_buddy_wb(GaimBlistNode *node, gpointer data) { + SilcGaimBuddyWb wb = data; + silcgaim_wb_init(wb->sg, wb->client_entry); + silc_free(wb); +} +GList *silcgaim_buddy_menu(GaimBuddy *buddy) +{ GaimConnection *gc = gaim_account_get_connection(buddy->account); SilcGaim sg = gc->proto_data; SilcClientConnection conn = sg->conn; @@ -1557,6 +1570,7 @@ GList *silcgaim_buddy_menu(GaimBuddy *bu SilcClientEntry client_entry = NULL; GaimBlistNodeAction *act; GList *m = NULL; + SilcGaimBuddyWb wb; pkfile = gaim_blist_node_get_string((GaimBlistNode *) buddy, "public-key"); client_entry = silc_client_get_client_by_id(sg->client, @@ -1597,5 +1611,12 @@ GList *silcgaim_buddy_menu(GaimBuddy *bu m = g_list_append(m, act); } + wb = silc_calloc(1, sizeof(*wb)); + wb->sg = sg; + wb->client_entry = client_entry; + act = gaim_blist_node_action_new(_("Draw On Whiteboard"), + silcgaim_buddy_wb, (void *)wb, NULL); + m = g_list_append(m, act); + return m; } Index: chat.c =================================================================== RCS file: /cvsroot/gaim/gaim/src/protocols/silc/chat.c,v retrieving revision 1.24 retrieving revision 1.25 diff -u -d -p -r1.24 -r1.25 --- chat.c 6 Sep 2005 03:04:07 -0000 1.24 +++ chat.c 12 Nov 2005 23:04:44 -0000 1.25 @@ -20,6 +20,7 @@ #include "silcincludes.h" #include "silcclient.h" #include "silcgaim.h" +#include "wb.h" /***************************** Channel Routines ******************************/ @@ -832,6 +833,19 @@ silcgaim_chat_setsecret(GaimBlistNode *n "+s", NULL); } +typedef struct { + SilcGaim sg; + SilcChannelEntry channel; +} *SilcGaimChatWb; + +static void +silcgaim_chat_wb(GaimBlistNode *node, gpointer data) +{ + SilcGaimChatWb wb = data; + silcgaim_wb_init_ch(wb->sg, wb->channel); + silc_free(wb); +} + GList *silcgaim_chat_menu(GaimChat *chat) { GHashTable *components = chat->components; @@ -949,6 +963,16 @@ GList *silcgaim_chat_menu(GaimChat *chat } } + if (channel) { + SilcGaimChatWb wb; + wb = silc_calloc(1, sizeof(*wb)); + wb->sg = sg; + wb->channel = channel; + act = gaim_blist_node_action_new(_("Draw On Whiteboard"), + silcgaim_chat_wb, (void *)wb, NULL); + m = g_list_append(m, act); + } + return m; } Index: ops.c =================================================================== RCS file: /cvsroot/gaim/gaim/src/protocols/silc/ops.c,v retrieving revision 1.37 retrieving revision 1.38 diff -u -d -p -r1.37 -r1.38 --- ops.c 12 Sep 2005 20:04:37 -0000 1.37 +++ ops.c 12 Nov 2005 23:04:44 -0000 1.38 @@ -20,6 +20,7 @@ #include "silcincludes.h" #include "silcclient.h" #include "silcgaim.h" +#include "wb.h" /* Message sent to the application by library. `conn' associates the message to a specific connection. `conn', however, may be NULL. @@ -80,7 +81,23 @@ silc_channel_message(SilcClient client, } if (flags & SILC_MESSAGE_FLAG_DATA) { - /* XXX */ + char type[128], enc[128]; + unsigned char *data; + SilcUInt32 data_len; + + memset(type, 0, sizeof(type)); + memset(enc, 0, sizeof(enc)); + + if (!silc_mime_parse(message, message_len, NULL, 0, + type, sizeof(type) - 1, enc, sizeof(enc) - 1, &data, + &data_len)) + return; + + if (!strcmp(type, "application/x-wb") && + !strcmp(enc, "binary")) + silcgaim_wb_receive_ch(client, conn, sender, channel, + payload, flags, data, data_len); + return; } @@ -159,7 +176,23 @@ silc_private_message(SilcClient client, } if (flags & SILC_MESSAGE_FLAG_DATA) { - /* XXX */ + char type[128], enc[128]; + unsigned char *data; + SilcUInt32 data_len; + + memset(type, 0, sizeof(type)); + memset(enc, 0, sizeof(enc)); + + if (!silc_mime_parse(message, message_len, NULL, 0, + type, sizeof(type) - 1, enc, sizeof(enc) - 1, &data, + &data_len)) + return; + + if (!strcmp(type, "application/x-wb") && + !strcmp(enc, "binary")) + silcgaim_wb_receive(client, conn, sender, payload, + flags, data, data_len); + return; } Index: silc.c =================================================================== RCS file: /cvsroot/gaim/gaim/src/protocols/silc/silc.c,v retrieving revision 1.51 retrieving revision 1.52 diff -u -d -p -r1.51 -r1.52 --- silc.c 26 Oct 2005 05:40:02 -0000 1.51 +++ silc.c 12 Nov 2005 23:04:44 -0000 1.52 @@ -21,6 +21,7 @@ #include "silcclient.h" #include "silcgaim.h" #include "version.h" +#include "wb.h" extern SilcClientOperations ops; static GaimPlugin *silc_plugin = NULL; @@ -1484,6 +1485,18 @@ static GaimPluginUiInfo prefs_info = silcgaim_pref_frame, }; +static GaimWhiteboardPrplOps silcgaim_wb_ops = +{ + silcgaim_wb_start, + silcgaim_wb_end, + silcgaim_wb_get_dimensions, + silcgaim_wb_set_dimensions, + silcgaim_wb_get_brush, + silcgaim_wb_set_brush, + silcgaim_wb_send, + silcgaim_wb_clear, +}; + static GaimPluginProtocolInfo prpl_info = { OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | @@ -1543,7 +1556,8 @@ static GaimPluginProtocolInfo prpl_info silcgaim_roomlist_cancel, /* roomlist_cancel */ NULL, /* roomlist_expand_category */ NULL, /* can_receive_file */ - silcgaim_ftp_send_file /* send_file */ + silcgaim_ftp_send_file, /* send_file */ + &silcgaim_wb_ops, /* whiteboard operations */ }; static GaimPluginInfo info = |