Mercurial > pidgin.yaz
view libpurple/protocols/yahoo/yahoo_doodle.c @ 15746:d3d9f28fb6d0
Fix a memory leak found by Peter Tang. Thanks man!
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Thu, 01 Mar 2007 08:33:21 +0000 |
parents | cf999f8e8a56 |
children | 32c366eeeb99 |
line wrap: on
line source
/* * gaim * * Gaim 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 * */ /****************************************************************************** * INCLUDES *****************************************************************************/ #include "internal.h" #include "account.h" #include "accountopt.h" #include "blist.h" #include "cipher.h" #include "cmds.h" #include "debug.h" #include "notify.h" #include "privacy.h" #include "prpl.h" #include "proxy.h" #include "request.h" #include "server.h" #include "util.h" #include "version.h" #include "yahoo.h" #include "yahoo_packet.h" #include "yahoo_friend.h" #include "yahoochat.h" #include "ycht.h" #include "yahoo_auth.h" #include "yahoo_filexfer.h" #include "yahoo_picture.h" #include "whiteboard.h" #include "yahoo_doodle.h" /****************************************************************************** * Globals *****************************************************************************/ #if 0 const int DefaultColorRGB24[] = { DOODLE_COLOR_RED, DOODLE_COLOR_ORANGE, DOODLE_COLOR_YELLOW, DOODLE_COLOR_GREEN, DOODLE_COLOR_CYAN, DOODLE_COLOR_BLUE, DOODLE_COLOR_VIOLET, DOODLE_COLOR_PURPLE, DOODLE_COLOR_TAN, DOODLE_COLOR_BROWN, DOODLE_COLOR_BLACK, DOODLE_COLOR_GREY, DOODLE_COLOR_WHITE }; #endif /****************************************************************************** * Functions *****************************************************************************/ GaimCmdRet yahoo_doodle_gaim_cmd_start(GaimConversation *conv, const char *cmd, char **args, char **error, void *data) { GaimAccount *account; GaimConnection *gc; const gchar *name; if(*args && args[0]) return GAIM_CMD_RET_FAILED; account = gaim_conversation_get_account(conv); gc = gaim_account_get_connection(account); name = gaim_conversation_get_name(conv); yahoo_doodle_initiate(gc, name); /* Write a local message to this conversation showing that a request for a * Doodle session has been made */ gaim_conv_im_write(GAIM_CONV_IM(conv), "", _("Sent Doodle request."), GAIM_MESSAGE_NICK | GAIM_MESSAGE_RECV, time(NULL)); return GAIM_CMD_RET_OK; } void yahoo_doodle_initiate(GaimConnection *gc, const char *name) { GaimAccount *account; char *to = (char*)name; GaimWhiteboard *wb; g_return_if_fail(gc); g_return_if_fail(name); account = gaim_connection_get_account(gc); wb = gaim_whiteboard_get_session(account, to); if(wb == NULL) { /* Insert this 'session' in the list. At this point, it's only a * requested session. */ gaim_whiteboard_create(account, to, DOODLE_STATE_REQUESTING); } /* NOTE Perhaps some careful handling of remote assumed established * sessions */ yahoo_doodle_command_send_request(gc, to); yahoo_doodle_command_send_ready(gc, to); } void yahoo_doodle_process(GaimConnection *gc, const char *me, const char *from, const char *command, const char *message) { if(!command) return; /* Now check to see what sort of Doodle message it is */ switch(atoi(command)) { case DOODLE_CMD_REQUEST: yahoo_doodle_command_got_request(gc, from); break; case DOODLE_CMD_READY: yahoo_doodle_command_got_ready(gc, from); break; case DOODLE_CMD_CLEAR: yahoo_doodle_command_got_clear(gc, from); break; case DOODLE_CMD_DRAW: yahoo_doodle_command_got_draw(gc, from, message); break; case DOODLE_CMD_EXTRA: yahoo_doodle_command_got_extra(gc, from, message); break; case DOODLE_CMD_CONFIRM: yahoo_doodle_command_got_confirm(gc, from); break; } } void yahoo_doodle_command_got_request(GaimConnection *gc, const char *from) { GaimAccount *account; GaimWhiteboard *wb; gaim_debug_info("yahoo", "doodle: Got Request (%s)\n", from); account = gaim_connection_get_account(gc); /* Only handle this if local client requested Doodle session (else local * client would have sent one) */ wb = gaim_whiteboard_get_session(account, from); /* If a session with the remote user doesn't exist */ if(wb == NULL) { /* Ask user if they wish to accept the request for a doodle session */ /* TODO Ask local user to start Doodle session with remote user */ /* NOTE This if/else statement won't work right--must use dialog * results */ /* char dialog_message[64]; g_sprintf(dialog_message, "%s is requesting to start a Doodle session with you.", from); gaim_notify_message(NULL, GAIM_NOTIFY_MSG_INFO, "Doodle", dialog_message, NULL, NULL, NULL); */ gaim_whiteboard_create(account, from, DOODLE_STATE_REQUESTED); yahoo_doodle_command_send_request(gc, from); } /* TODO Might be required to clear the canvas of an existing doodle * session at this point */ } void yahoo_doodle_command_got_ready(GaimConnection *gc, const char *from) { GaimAccount *account; GaimWhiteboard *wb; gaim_debug_info("yahoo", "doodle: Got Ready (%s)\n", from); account = gaim_connection_get_account(gc); /* Only handle this if local client requested Doodle session (else local * client would have sent one) */ wb = gaim_whiteboard_get_session(account, from); if(wb == NULL) return; if(wb->state == DOODLE_STATE_REQUESTING) { gaim_whiteboard_start(wb); wb->state = DOODLE_STATE_ESTABLISHED; yahoo_doodle_command_send_confirm(gc, from); } if(wb->state == DOODLE_STATE_ESTABLISHED) { /* TODO Ask whether to save picture too */ gaim_whiteboard_clear(wb); } /* NOTE Not sure about this... I am trying to handle if the remote user * already thinks we're in a session with them (when their chat message * contains the doodle;11 imv key) */ if(wb->state == DOODLE_STATE_REQUESTED) { /* gaim_whiteboard_start(wb); */ yahoo_doodle_command_send_request(gc, from); } } void yahoo_doodle_command_got_draw(GaimConnection *gc, const char *from, const char *message) { GaimAccount *account; GaimWhiteboard *wb; char **tokens; int i; GList *d_list = NULL; /* a local list of drawing info */ g_return_if_fail(message != NULL); gaim_debug_info("yahoo", "doodle: Got Draw (%s)\n", from); gaim_debug_info("yahoo", "doodle: Draw message: %s\n", message); account = gaim_connection_get_account(gc); /* Only handle this if local client requested Doodle session (else local * client would have sent one) */ wb = gaim_whiteboard_get_session(account, from); if(wb == NULL) return; /* TODO Functionalize * Convert drawing packet message to an integer list */ /* Check to see if the message begans and ends with quotes */ if((message[0] != '\"') || (message[strlen(message) - 1] != '\"')) return; /* Ignore the inital quotation mark. */ message += 1; tokens = g_strsplit(message, ",", 0); /* Traverse and extract all integers divided by commas */ for (i = 0; tokens[i] != NULL; i++) { int last = strlen(tokens[i]) - 1; if (tokens[i][last] == '"') tokens[i][last] = '\0'; d_list = g_list_prepend(d_list, GINT_TO_POINTER(atoi(tokens[i]))); } d_list = g_list_reverse(d_list); g_strfreev(tokens); yahoo_doodle_draw_stroke(wb, d_list); /* goodle_doodle_session_set_canvas_as_icon(ds); */ g_list_free(d_list); } void yahoo_doodle_command_got_clear(GaimConnection *gc, const char *from) { GaimAccount *account; GaimWhiteboard *wb; gaim_debug_info("yahoo", "doodle: Got Clear (%s)\n", from); account = gaim_connection_get_account(gc); /* Only handle this if local client requested Doodle session (else local * client would have sent one) */ wb = gaim_whiteboard_get_session(account, from); if(wb == NULL) return; if(wb->state == DOODLE_STATE_ESTABLISHED) { /* TODO Ask user whether to save the image before clearing it */ gaim_whiteboard_clear(wb); } } void yahoo_doodle_command_got_extra(GaimConnection *gc, const char *from, const char *message) { gaim_debug_info("yahoo", "doodle: Got Extra (%s)\n", from); /* I do not like these 'extra' features, so I'll only handle them in one * way, which is returning them with the command/packet to turn them off */ yahoo_doodle_command_send_extra(gc, from, DOODLE_EXTRA_NONE); } void yahoo_doodle_command_got_confirm(GaimConnection *gc, const char *from) { GaimAccount *account; GaimWhiteboard *wb; gaim_debug_info("yahoo", "doodle: Got Confirm (%s)\n", from); /* Get the doodle session */ account = gaim_connection_get_account(gc); /* Only handle this if local client requested Doodle session (else local * client would have sent one) */ wb = gaim_whiteboard_get_session(account, from); if(wb == NULL) return; /* TODO Combine the following IF's? */ /* Check if we requested a doodle session */ if(wb->state == DOODLE_STATE_REQUESTING) { wb->state = DOODLE_STATE_ESTABLISHED; gaim_whiteboard_start(wb); yahoo_doodle_command_send_confirm(gc, from); } /* Check if we accepted a request for a doodle session */ if(wb->state == DOODLE_STATE_REQUESTED) { wb->state = DOODLE_STATE_ESTABLISHED; gaim_whiteboard_start(wb); } } void yahoo_doodle_command_got_shutdown(GaimConnection *gc, const char *from) { GaimAccount *account; GaimWhiteboard *wb; g_return_if_fail(from != NULL); gaim_debug_info("yahoo", "doodle: Got Shutdown (%s)\n", from); account = gaim_connection_get_account(gc); /* Only handle this if local client requested Doodle session (else local * client would have sent one) */ wb = gaim_whiteboard_get_session(account, from); /* TODO Ask if user wants to save picture before the session is closed */ /* If this session doesn't exist, don't try and kill it */ if(wb == NULL) return; else { gaim_whiteboard_destroy(wb); /* yahoo_doodle_command_send_shutdown(gc, from); */ } } static void yahoo_doodle_command_send_generic(const char *type, GaimConnection *gc, const char *to, const char *message, const char *thirteen, const char *sixtythree, const char *sixtyfour) { struct yahoo_data *yd; struct yahoo_packet *pkt; gaim_debug_info("yahoo", "doodle: Sent %s (%s)\n", type, to); yd = gc->proto_data; /* Make and send an acknowledge (ready) Doodle packet */ pkt = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, 0); yahoo_packet_hash_str(pkt, 49, "IMVIRONMENT"); yahoo_packet_hash_str(pkt, 1, gaim_account_get_username(gc->account)); yahoo_packet_hash_str(pkt, 14, message); yahoo_packet_hash_str(pkt, 13, thirteen); yahoo_packet_hash_str(pkt, 5, to); yahoo_packet_hash_str(pkt, 63, sixtythree ? sixtythree : "doodle;11"); yahoo_packet_hash_str(pkt, 64, sixtyfour); yahoo_packet_hash_str(pkt, 1002, "1"); yahoo_packet_send_and_free(pkt, yd); } void yahoo_doodle_command_send_request(GaimConnection *gc, const char *to) { yahoo_doodle_command_send_generic("Request", gc, to, "1", "1", NULL, "1"); } void yahoo_doodle_command_send_ready(GaimConnection *gc, const char *to) { yahoo_doodle_command_send_generic("Ready", gc, to, "", "0", NULL, "0"); } void yahoo_doodle_command_send_draw(GaimConnection *gc, const char *to, const char *message) { yahoo_doodle_command_send_generic("Draw", gc, to, message, "3", NULL, "1"); } void yahoo_doodle_command_send_clear(GaimConnection *gc, const char *to) { yahoo_doodle_command_send_generic("Clear", gc, to, " ", "2", NULL, "1"); } void yahoo_doodle_command_send_extra(GaimConnection *gc, const char *to, const char *message) { yahoo_doodle_command_send_generic("Extra", gc, to, message, "4", NULL, "1"); } void yahoo_doodle_command_send_confirm(GaimConnection *gc, const char *to) { yahoo_doodle_command_send_generic("Confirm", gc, to, "1", "5", NULL, "1"); } void yahoo_doodle_command_send_shutdown(GaimConnection *gc, const char *to) { yahoo_doodle_command_send_generic("Shutdown", gc, to, "", "0", ";0", "0"); } void yahoo_doodle_start(GaimWhiteboard *wb) { doodle_session *ds = g_new0(doodle_session, 1); /* gaim_debug_debug("yahoo", "doodle: yahoo_doodle_start()\n"); */ /* Set default brush size and color */ ds->brush_size = DOODLE_BRUSH_SMALL; ds->brush_color = DOODLE_COLOR_RED; wb->proto_data = ds; } void yahoo_doodle_end(GaimWhiteboard *wb) { GaimConnection *gc = gaim_account_get_connection(wb->account); /* g_debug_debug("yahoo", "doodle: yahoo_doodle_end()\n"); */ yahoo_doodle_command_send_shutdown(gc, wb->who); g_free(wb->proto_data); } void yahoo_doodle_get_dimensions(const GaimWhiteboard *wb, int *width, int *height) { /* standard Doodle canvases are of one size: 368x256 */ *width = DOODLE_CANVAS_WIDTH; *height = DOODLE_CANVAS_HEIGHT; } static char *yahoo_doodle_build_draw_string(doodle_session *ds, GList *draw_list) { GString *message; g_return_val_if_fail(draw_list != NULL, NULL); message = g_string_new(""); g_string_printf(message, "\"%d,%d", ds->brush_color, ds->brush_size); for(; draw_list != NULL; draw_list = draw_list->next) { g_string_append_printf(message, ",%d", GPOINTER_TO_INT(draw_list->data)); } g_string_append_c(message, '"'); return g_string_free(message, FALSE); } void yahoo_doodle_send_draw_list(GaimWhiteboard *wb, GList *draw_list) { doodle_session *ds = wb->proto_data; char *message; g_return_if_fail(draw_list != NULL); message = yahoo_doodle_build_draw_string(ds, draw_list); yahoo_doodle_command_send_draw(wb->account->gc, wb->who, message); g_free(message); } void yahoo_doodle_clear(GaimWhiteboard *wb) { yahoo_doodle_command_send_clear(wb->account->gc, wb->who); } /* Traverse through the list and draw the points and lines */ void yahoo_doodle_draw_stroke(GaimWhiteboard *wb, GList *draw_list) { int brush_color; int brush_size; int x; int y; g_return_if_fail(draw_list != NULL); brush_color = GPOINTER_TO_INT(draw_list->data); draw_list = draw_list->next; g_return_if_fail(draw_list != NULL); brush_size = GPOINTER_TO_INT(draw_list->data); draw_list = draw_list->next; g_return_if_fail(draw_list != NULL); x = GPOINTER_TO_INT(draw_list->data); draw_list = draw_list->next; g_return_if_fail(draw_list != NULL); y = GPOINTER_TO_INT(draw_list->data); draw_list = draw_list->next; g_return_if_fail(draw_list != NULL); /* gaim_debug_debug("yahoo", "doodle: Drawing: color=%d, size=%d, (%d,%d)\n", brush_color, brush_size, x, y); */ while(draw_list != NULL && draw_list->next != NULL) { int dx = GPOINTER_TO_INT(draw_list->data); int dy = GPOINTER_TO_INT(draw_list->next->data); gaim_whiteboard_draw_line(wb, x, y, x + dx, y + dy, brush_color, brush_size); x += dx; y += dy; draw_list = draw_list->next->next; } } void yahoo_doodle_get_brush(const GaimWhiteboard *wb, int *size, int *color) { doodle_session *ds = (doodle_session *)wb->proto_data; *size = ds->brush_size; *color = ds->brush_color; } void yahoo_doodle_set_brush(GaimWhiteboard *wb, int size, int color) { doodle_session *ds = (doodle_session *)wb->proto_data; ds->brush_size = size; ds->brush_color = color; /* Notify the core about the changes */ gaim_whiteboard_set_brush(wb, size, color); }