pidgin/pidgin

Bump the version for release
release-2.x.y v2.10.12
2015-12-31, Gary Kramlich
2ac1dcb9eb2e
Bump the version for release
/*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 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 "libymsg.h"
#include "yahoo_packet.h"
#include "yahoo_friend.h"
#include "yahoochat.h"
#include "ycht.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
*****************************************************************************/
PurpleCmdRet yahoo_doodle_purple_cmd_start(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data)
{
PurpleAccount *account;
PurpleConnection *gc;
const gchar *name;
if(*args && args[0])
return PURPLE_CMD_RET_FAILED;
account = purple_conversation_get_account(conv);
gc = purple_account_get_connection(account);
name = purple_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
*/
purple_conv_im_write(PURPLE_CONV_IM(conv), "", _("Sent Doodle request."),
PURPLE_MESSAGE_NICK | PURPLE_MESSAGE_RECV, time(NULL));
return PURPLE_CMD_RET_OK;
}
void yahoo_doodle_initiate(PurpleConnection *gc, const char *name)
{
PurpleAccount *account;
char *to = (char*)name;
g_return_if_fail(gc);
g_return_if_fail(name);
account = purple_connection_get_account(gc);
if(purple_whiteboard_get_session(account, to) == NULL)
{
/* Insert this 'session' in the list. At this point, it's only a
* requested session.
*/
purple_whiteboard_create(account, to, DOODLE_STATE_REQUESTING);
}
/* NOTE Perhaps some careful handling of remote assumed established
* sessions
*/
yahoo_doodle_command_send_ready(gc, to, DOODLE_IMV_KEY);
yahoo_doodle_command_send_request(gc, to, DOODLE_IMV_KEY);
}
static void yahoo_doodle_command_got_request(PurpleConnection *gc, const char *from, const char *imv_key)
{
PurpleAccount *account;
PurpleWhiteboard *wb;
purple_debug_info("yahoo", "doodle: Got Request (%s)\n", from);
account = purple_connection_get_account(gc);
/* Only handle this if local client requested Doodle session (else local
* client would have sent one)
*/
wb = purple_whiteboard_get_session(account, from);
/* If a session with the remote user doesn't exist */
if(wb == NULL)
{
doodle_session *ds;
/* 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);
purple_notify_message(NULL, PURPLE_NOTIFY_MSG_INFO, "Doodle",
dialog_message, NULL, NULL, NULL);
*/
wb = purple_whiteboard_create(account, from, DOODLE_STATE_REQUESTED);
ds = wb->proto_data;
ds->imv_key = g_strdup(imv_key);
yahoo_doodle_command_send_ready(gc, from, imv_key);
}
/* TODO Might be required to clear the canvas of an existing doodle
* session at this point
*/
}
static void yahoo_doodle_command_got_ready(PurpleConnection *gc, const char *from, const char *imv_key)
{
PurpleAccount *account;
PurpleWhiteboard *wb;
purple_debug_info("yahoo", "doodle: Got Ready(%s)\n", from);
account = purple_connection_get_account(gc);
/* Only handle this if local client requested Doodle session (else local
* client would have sent one)
*/
wb = purple_whiteboard_get_session(account, from);
if(wb == NULL)
return;
if(wb->state == DOODLE_STATE_REQUESTING)
{
doodle_session *ds = wb->proto_data;
purple_whiteboard_start(wb);
wb->state = DOODLE_STATE_ESTABLISHED;
yahoo_doodle_command_send_confirm(gc, from, imv_key);
/* Let's steal the imv_key and reuse it */
g_free(ds->imv_key);
ds->imv_key = g_strdup(imv_key);
}
else if(wb->state == DOODLE_STATE_ESTABLISHED)
{
/* TODO Ask whether to save picture too */
purple_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 imv key)
*/
else if(wb->state == DOODLE_STATE_REQUESTED)
{
/* purple_whiteboard_start(wb); */
yahoo_doodle_command_send_ready(gc, from, imv_key);
}
}
static void yahoo_doodle_command_got_draw(PurpleConnection *gc, const char *from, const char *message)
{
PurpleAccount *account;
PurpleWhiteboard *wb;
char **tokens;
int i;
GList *d_list = NULL; /* a local list of drawing info */
g_return_if_fail(message != NULL);
purple_debug_info("yahoo", "doodle: Got Draw (%s)\n", from);
purple_debug_info("yahoo", "doodle: Draw message: %s\n", message);
account = purple_connection_get_account(gc);
/* Only handle this if local client requested Doodle session (else local
* client would have sent one)
*/
wb = purple_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);
}
static void yahoo_doodle_command_got_clear(PurpleConnection *gc, const char *from)
{
PurpleAccount *account;
PurpleWhiteboard *wb;
purple_debug_info("yahoo", "doodle: Got Clear (%s)\n", from);
account = purple_connection_get_account(gc);
/* Only handle this if local client requested Doodle session (else local
* client would have sent one)
*/
wb = purple_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 */
purple_whiteboard_clear(wb);
}
}
static void
yahoo_doodle_command_got_extra(PurpleConnection *gc, const char *from, const char *message, const char *imv_key)
{
purple_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, imv_key);
}
static void yahoo_doodle_command_got_confirm(PurpleConnection *gc, const char *from)
{
PurpleAccount *account;
PurpleWhiteboard *wb;
purple_debug_info("yahoo", "doodle: Got Confirm (%s)\n", from);
/* Get the doodle session */
account = purple_connection_get_account(gc);
/* Only handle this if local client requested Doodle session (else local
* client would have sent one)
*/
wb = purple_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;
purple_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;
purple_whiteboard_start(wb);
}
}
void yahoo_doodle_command_got_shutdown(PurpleConnection *gc, const char *from)
{
PurpleAccount *account;
PurpleWhiteboard *wb;
g_return_if_fail(from != NULL);
purple_debug_info("yahoo", "doodle: Got Shutdown (%s)\n", from);
account = purple_connection_get_account(gc);
/* Only handle this if local client requested Doodle session (else local
* client would have sent one)
*/
wb = purple_whiteboard_get_session(account, from);
if(wb == NULL)
return;
/* TODO Ask if user wants to save picture before the session is closed */
wb->state = DOODLE_STATE_CANCELLED;
purple_whiteboard_destroy(wb);
}
static void yahoo_doodle_command_send_generic(const char *type,
PurpleConnection *gc,
const char *to,
const char *message,
int command,
const char *imv,
const char *sixtyfour)
{
YahooData *yd;
struct yahoo_packet *pkt;
purple_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, yd->session_id);
yahoo_packet_hash_str(pkt, 49, "IMVIRONMENT");
yahoo_packet_hash_str(pkt, 1, purple_account_get_username(gc->account));
yahoo_packet_hash_str(pkt, 14, message);
yahoo_packet_hash_int(pkt, 13, command);
yahoo_packet_hash_str(pkt, 5, to);
yahoo_packet_hash_str(pkt, 63, imv ? imv : DOODLE_IMV_KEY);
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_ready(PurpleConnection *gc, const char *to, const char *imv_key)
{
yahoo_doodle_command_send_generic("Ready", gc, to, "1", DOODLE_CMD_READY, imv_key, "1");
}
void yahoo_doodle_command_send_request(PurpleConnection *gc, const char *to, const char *imv_key)
{
yahoo_doodle_command_send_generic("Request", gc, to, "", DOODLE_CMD_REQUEST, imv_key, "0");
}
void yahoo_doodle_command_send_draw(PurpleConnection *gc, const char *to, const char *message, const char *imv_key)
{
yahoo_doodle_command_send_generic("Draw", gc, to, message, DOODLE_CMD_DRAW, imv_key, "1");
}
void yahoo_doodle_command_send_clear(PurpleConnection *gc, const char *to, const char *imv_key)
{
yahoo_doodle_command_send_generic("Clear", gc, to, " ", DOODLE_CMD_CLEAR, imv_key, "1");
}
void yahoo_doodle_command_send_extra(PurpleConnection *gc, const char *to, const char *message, const char *imv_key)
{
yahoo_doodle_command_send_generic("Extra", gc, to, message, DOODLE_CMD_EXTRA, imv_key, "1");
}
void yahoo_doodle_command_send_confirm(PurpleConnection *gc, const char *to, const char *imv_key)
{
yahoo_doodle_command_send_generic("Confirm", gc, to, "1", DOODLE_CMD_CONFIRM, imv_key, "1");
}
void yahoo_doodle_command_send_shutdown(PurpleConnection *gc, const char *to)
{
yahoo_doodle_command_send_generic("Shutdown", gc, to, "", DOODLE_CMD_SHUTDOWN, ";0", "0");
}
void yahoo_doodle_start(PurpleWhiteboard *wb)
{
doodle_session *ds = g_new0(doodle_session, 1);
/* purple_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(PurpleWhiteboard *wb)
{
PurpleConnection *gc = purple_account_get_connection(wb->account);
doodle_session *ds = wb->proto_data;
/* g_debug_debug("yahoo", "doodle: yahoo_doodle_end()\n"); */
if (gc && wb->state != DOODLE_STATE_CANCELLED)
yahoo_doodle_command_send_shutdown(gc, wb->who);
g_free(ds->imv_key);
g_free(wb->proto_data);
}
void yahoo_doodle_get_dimensions(const PurpleWhiteboard *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(PurpleWhiteboard *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, ds->imv_key);
g_free(message);
}
void yahoo_doodle_clear(PurpleWhiteboard *wb)
{
doodle_session *ds = wb->proto_data;
yahoo_doodle_command_send_clear(wb->account->gc, wb->who, ds->imv_key);
}
/* Traverse through the list and draw the points and lines */
void yahoo_doodle_draw_stroke(PurpleWhiteboard *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);
/*
purple_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);
purple_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 PurpleWhiteboard *wb, int *size, int *color)
{
doodle_session *ds = wb->proto_data;
*size = ds->brush_size;
*color = ds->brush_color;
}
void yahoo_doodle_set_brush(PurpleWhiteboard *wb, int size, int color)
{
doodle_session *ds = wb->proto_data;
ds->brush_size = size;
ds->brush_color = color;
/* Notify the core about the changes */
purple_whiteboard_set_brush(wb, size, color);
}
void yahoo_doodle_process(PurpleConnection *gc, const char *me, const char *from,
const char *command, const char *message, const char *imv_key)
{
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, imv_key);
break;
case DOODLE_CMD_READY:
yahoo_doodle_command_got_ready(gc, from, imv_key);
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, imv_key);
break;
case DOODLE_CMD_CONFIRM:
yahoo_doodle_command_got_confirm(gc, from);
break;
}
}