Mercurial > pidgin
changeset 21044:6b02dba5bf41
Patch from Pekka Riikone to fix various SILC issues.
Fixes: #3103
author | Ethan Blanton <elb@pidgin.im> |
---|---|
date | Mon, 29 Oct 2007 00:19:53 +0000 |
parents | 6b9e304272e4 |
children | daf98e539358 |
files | libpurple/protocols/silc/chat.c libpurple/protocols/silc/ops.c libpurple/protocols/silc/pk.c libpurple/protocols/silc/silc.c libpurple/protocols/silc/silcpurple.h libpurple/protocols/silc/util.c libpurple/protocols/silc/wb.c |
diffstat | 7 files changed, 217 insertions(+), 78 deletions(-) [+] |
line wrap: on
line diff
--- a/libpurple/protocols/silc/chat.c Mon Oct 29 00:09:18 2007 +0000 +++ b/libpurple/protocols/silc/chat.c Mon Oct 29 00:19:53 2007 +0000 @@ -160,15 +160,17 @@ unsigned char *pk; SilcUInt32 pk_len; pk = silc_pkcs_public_key_encode(channel->founder_key, &pk_len); - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); + if (pk) { + fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); + babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - g_string_append_printf(s, _("<br><b>Founder Key Fingerprint:</b><br>%s"), fingerprint); - g_string_append_printf(s, _("<br><b>Founder Key Babbleprint:</b><br>%s"), babbleprint); + g_string_append_printf(s, _("<br><b>Founder Key Fingerprint:</b><br>%s"), fingerprint); + g_string_append_printf(s, _("<br><b>Founder Key Babbleprint:</b><br>%s"), babbleprint); - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); + silc_free(fingerprint); + silc_free(babbleprint); + silc_free(pk); + } } buf = g_string_free(s, FALSE); @@ -460,6 +462,8 @@ silc_dlist_start(channel_pubkeys); while ((public_key = silc_dlist_get(channel_pubkeys))) { pk = silc_pkcs_public_key_encode(public_key, &pk_len); + if (!pk) + continue; fingerprint = silc_hash_fingerprint(NULL, pk + 4, pk_len - 4); babbleprint = silc_hash_babbleprint(NULL, pk + 4, pk_len - 4); @@ -1013,9 +1017,6 @@ SilcClient client = sg->client; SilcClientConnection conn = sg->conn; const char *channel, *passphrase, *parentch; -#if 0 - PurpleChat *chat; -#endif if (!conn) return; @@ -1071,22 +1072,6 @@ return; } -#if 0 - /* If the channel is not on buddy list, automatically add it there. */ - chat = purple_blist_find_chat(sg->account, channel); - if (!chat) { - data = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, g_free); - g_hash_table_replace(data, g_strdup("channel"), - g_strdup(channel)); - if (passphrase) - g_hash_table_replace(data, g_strdup("passphrase"), - g_strdup(passphrase)); - chat = purple_chat_new(sg->account, NULL, data); - purple_blist_add_chat(chat, NULL, NULL); - } -#endif - /* XXX We should have other properties here as well: 1. whether to try to authenticate to the channel 1a. with default key, @@ -1320,7 +1305,7 @@ ret = silc_client_send_channel_message(client, conn, channel, key, - flags, NULL, + flags, sg->sha1hash, buf->data, silc_buffer_len(buf)); silc_mime_partial_free(list); @@ -1334,7 +1319,8 @@ /* Send channel message */ ret = silc_client_send_channel_message(client, conn, channel, key, - flags, NULL, (unsigned char *)msg2, + flags, sg->sha1hash, + (unsigned char *)msg2, strlen(msg2)); if (ret) { serv_got_chat_in(gc, id, purple_connection_get_display_name(gc), 0, msg,
--- a/libpurple/protocols/silc/ops.c Mon Oct 29 00:09:18 2007 +0000 +++ b/libpurple/protocols/silc/ops.c Mon Oct 29 00:19:53 2007 +0000 @@ -1274,13 +1274,15 @@ unsigned char *pk; SilcUInt32 pk_len; pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len); - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint); - purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint); - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); + if (pk) { + fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); + babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); + purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint); + purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint); + silc_free(fingerprint); + silc_free(babbleprint); + silc_free(pk); + } } #if 0 /* XXX for now, let's not show attrs here */ @@ -1346,13 +1348,15 @@ unsigned char *pk; SilcUInt32 pk_len; pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len); - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint); - purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint); - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); + if (pk) { + fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); + babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); + purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint); + purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint); + silc_free(fingerprint); + silc_free(babbleprint); + silc_free(pk); + } } purple_notify_userinfo(gc, nickname, user_info, NULL, NULL);
--- a/libpurple/protocols/silc/pk.c Mon Oct 29 00:09:18 2007 +0000 +++ b/libpurple/protocols/silc/pk.c Mon Oct 29 00:19:53 2007 +0000 @@ -158,6 +158,11 @@ NULL, &hostname, &ip, &port); pk = silc_pkcs_public_key_encode(public_key, &pk_len); + if (!pk) { + if (completion) + completion(FALSE, context); + return; + } if (conn_type == SILC_CONN_SERVER || conn_type == SILC_CONN_ROUTER) {
--- a/libpurple/protocols/silc/silc.c Mon Oct 29 00:09:18 2007 +0000 +++ b/libpurple/protocols/silc/silc.c Mon Oct 29 00:19:53 2007 +0000 @@ -128,6 +128,7 @@ NULL, 0); } +#if __SILC_TOOLKIT_VERSION < SILC_VERSION(1,1,1) static gboolean silcpurple_scheduler(gpointer *context) { @@ -135,6 +136,105 @@ silc_client_run_one(client); return TRUE; } +#else +typedef struct { + SilcPurple sg; + SilcUInt32 fd; + guint tag; +} *SilcPurpleTask; + +/* A timeout occurred. Call SILC scheduler. */ + +static gboolean +silcpurple_scheduler_timeout(gpointer context) +{ + SilcPurpleTask task = (SilcPurpleTask)context; + silc_client_run_one(task->sg->client); + silc_dlist_del(task->sg->tasks, task); + silc_free(task); + return FALSE; +} + +/* An fd task event occurred. Call SILC scheduler. */ + +static void +silcpurple_scheduler_fd(gpointer data, gint fd, PurpleInputCondition cond) +{ + SilcClient client = (SilcClient)data; + silc_client_run_one(client); +} + +/* SILC Scheduler notify callback. This is called whenever task is added to + or deleted from SILC scheduler. It's also called when fd task events + change. Here we add same tasks to glib's main loop. */ + +static void +silcpurple_scheduler(SilcSchedule schedule, + SilcBool added, SilcTask task, + SilcBool fd_task, SilcUInt32 fd, + SilcTaskEvent event, + long seconds, long useconds, + void *context) +{ + SilcClient client = (SilcClient)context; + PurpleConnection *gc = client->application; + SilcPurple sg = gc->proto_data; + SilcPurpleTask ptask = NULL; + + if (added) { + if (fd_task) { + /* Add fd or change fd events */ + PurpleInputCondition e = 0; + + silc_dlist_start(sg->tasks); + while ((ptask = silc_dlist_get(sg->tasks))) + if (ptask->fd == fd) { + purple_input_remove(ptask->tag); + break; + } + + if (event & SILC_TASK_READ) + e |= PURPLE_INPUT_READ; + if (event & SILC_TASK_WRITE) + e |= PURPLE_INPUT_WRITE; + + if (e) { + if (!ptask) { + ptask = silc_calloc(1, sizeof(*ptask)); + ptask->fd = fd; + silc_dlist_add(sg->tasks, ptask); + } + ptask->tag = purple_input_add(fd, e, silcpurple_scheduler_fd, + client); + } else if (ptask) { + silc_dlist_del(sg->tasks, ptask); + silc_free(ptask); + } + } else { + /* Add timeout */ + ptask = silc_calloc(1, sizeof(*ptask)); + ptask->sg = sg; + ptask->tag = purple_timeout_add((seconds * 1000) + + (useconds / 1000), + silcpurple_scheduler_timeout, + ptask); + silc_dlist_add(sg->tasks, ptask); + } + } else { + if (fd_task) { + /* Remove fd */ + silc_dlist_start(sg->tasks); + while ((ptask = silc_dlist_get(sg->tasks))) + if (ptask->fd == fd) { + purple_input_remove(ptask->tag); + silc_dlist_del(sg->tasks, ptask); + silc_free(ptask); + break; + } + } + } +} +#endif /* __SILC_TOOLKIT_VERSION */ static void silcpurple_connect_cb(SilcClient client, SilcClientConnection conn, @@ -316,6 +416,8 @@ return; } + silc_hash_alloc("sha1", &sg->sha1hash); + /* Wrap socket to TCP stream */ silc_socket_tcp_stream_create(source, TRUE, FALSE, sg->client->schedule, @@ -324,21 +426,11 @@ static void silcpurple_running(SilcClient client, void *context) { - PurpleAccount *account = context; - PurpleConnection *gc = account->gc; - SilcPurple sg; + SilcPurple sg = context; + PurpleConnection *gc = sg->gc; + PurpleAccount *account = purple_connection_get_account(gc); char pkd[256], prd[256]; - sg = silc_calloc(1, sizeof(*sg)); - if (!sg) - return; - memset(sg, 0, sizeof(*sg)); - sg->client = client; - sg->gc = gc; - sg->account = account; - sg->scheduler = SILC_PTR_TO_32(gc->proto_data); - gc->proto_data = sg; - /* Progress */ purple_connection_update_progress(gc, _("Connecting to SILC Server"), 1, 5); @@ -375,10 +467,10 @@ { SilcClient client; PurpleConnection *gc; + SilcPurple sg; SilcClientParams params; const char *cipher, *hmac; char *username, *hostname, *realname, **up; - guint scheduler; int i; gc = account->gc; @@ -431,11 +523,21 @@ break; } + sg = silc_calloc(1, sizeof(*sg)); + if (!sg) + return; + sg->client = client; + sg->gc = gc; + sg->account = account; + gc->proto_data = sg; + /* Init SILC client */ if (!silc_client_init(client, username, hostname, realname, - silcpurple_running, account)) { + silcpurple_running, sg)) { gc->wants_to_die = TRUE; purple_connection_error(gc, _("Cannot initialize SILC protocol")); + gc->proto_data = NULL; + silc_free(sg); return; } @@ -443,20 +545,32 @@ if (!silcpurple_check_silc_dir(gc)) { gc->wants_to_die = TRUE; purple_connection_error(gc, _("Error loading SILC key pair")); + gc->proto_data = NULL; + silc_free(sg); return; } +#if __SILC_TOOLKIT_VERSION < SILC_VERSION(1,1,1) /* Schedule SILC using Glib's event loop */ - scheduler = purple_timeout_add(300, (GSourceFunc)silcpurple_scheduler, client); - gc->proto_data = SILC_32_TO_PTR(scheduler); + sg->scheduler = purple_timeout_add(300, (GSourceFunc)silcpurple_scheduler, client); +#else + /* Run SILC scheduler */ + sg->tasks = silc_dlist_init(); + silc_schedule_set_notify(client->schedule, silcpurple_scheduler, + client); + silc_client_run_one(client); +#endif /* __SILC_TOOLKIT_VERSION */ } static int silcpurple_close_final(gpointer *context) { SilcPurple sg = (SilcPurple)context; + silc_client_stop(sg->client, NULL, NULL); silc_client_free(sg->client); + if (sg->sha1hash) + silc_hash_free(sg->sha1hash); if (sg->mimeass) silc_mime_assembler_free(sg->mimeass); silc_free(sg); @@ -467,16 +581,33 @@ silcpurple_close(PurpleConnection *gc) { SilcPurple sg = gc->proto_data; +#if __SILC_TOOLKIT_VERSION >= SILC_VERSION(1,1,1) + SilcPurpleTask task; +#endif /* __SILC_TOOLKIT_VERSION */ g_return_if_fail(sg != NULL); /* Send QUIT */ silc_client_command_call(sg->client, sg->conn, NULL, - "QUIT", "Download Pidgin: " PURPLE_WEBSITE, NULL); + "QUIT", "Download Pidgin: " PURPLE_WEBSITE, + NULL); if (sg->conn) silc_client_close_connection(sg->client, sg->conn); +#if __SILC_TOOLKIT_VERSION >= SILC_VERSION(1,1,1) + if (sg->conn) + silc_client_run_one(sg->client); + silc_schedule_set_notify(sg->client->schedule, NULL, NULL); + + silc_dlist_start(sg->tasks); + while ((task = silc_dlist_get(sg->tasks))) { + purple_input_remove(task->tag); + silc_free(task); + } + silc_dlist_uninit(sg->tasks); +#endif /* __SILC_TOOLKIT_VERSION */ + purple_timeout_remove(sg->scheduler); purple_timeout_add(1, (GSourceFunc)silcpurple_close_final, sg); } @@ -1155,7 +1286,7 @@ silc_dlist_start(list); while ((buf = silc_dlist_get(list)) != SILC_LIST_END) silc_client_send_private_message(client, conn, - client_entry, im->flags, NULL, + client_entry, im->flags, sg->sha1hash, buf->data, silc_buffer_len(buf)); silc_mime_partial_free(list); @@ -1167,7 +1298,7 @@ /* Send the message */ silc_client_send_private_message(client, conn, client_entry, im->flags, - NULL, (unsigned char *)im->message, im->message_len); + sg->sha1hash, (unsigned char *)im->message, im->message_len); purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname, im->message, 0, time(NULL)); goto out; @@ -1259,7 +1390,7 @@ while ((buf = silc_dlist_get(list)) != SILC_LIST_END) ret = silc_client_send_private_message(client, conn, - client_entry, mflags, NULL, + client_entry, mflags, sg->sha1hash, buf->data, silc_buffer_len(buf)); silc_mime_partial_free(list); @@ -1271,7 +1402,7 @@ /* Send private message directly */ ret = silc_client_send_private_message(client, conn, client_entry, - mflags, NULL, + mflags, sg->sha1hash, (unsigned char *)msg, strlen(msg));
--- a/libpurple/protocols/silc/silcpurple.h Mon Oct 29 00:09:18 2007 +0000 +++ b/libpurple/protocols/silc/silcpurple.h Mon Oct 29 00:19:53 2007 +0000 @@ -35,6 +35,9 @@ #include "server.h" #include "util.h" +#undef SILC_VERSION +#define SILC_VERSION(a, b, c) (((a) << 24) + ((b) << 16) + ((c) << 8)) + /* Default public and private key file names */ #define SILCPURPLE_PUBLIC_KEY_NAME "public_key.pub" #define SILCPURPLE_PRIVATE_KEY_NAME "private_key.prv" @@ -68,7 +71,9 @@ SilcClientConnection conn; SilcPublicKey public_key; SilcPrivateKey private_key; + SilcHash sha1hash; + SilcDList tasks; guint scheduler; PurpleConnection *gc; PurpleAccount *account;
--- a/libpurple/protocols/silc/util.c Mon Oct 29 00:09:18 2007 +0000 +++ b/libpurple/protocols/silc/util.c Mon Oct 29 00:19:53 2007 +0000 @@ -347,8 +347,12 @@ key_len = silc_pkcs_public_key_get_len(public_key); pk = silc_pkcs_public_key_encode(public_key, &pk_len); + if (!pk) + return; fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); + if (!fingerprint || !babbleprint) + return; s = g_string_new(""); if (ident->realname)
--- a/libpurple/protocols/silc/wb.c Mon Oct 29 00:09:18 2007 +0000 +++ b/libpurple/protocols/silc/wb.c Mon Oct 29 00:19:53 2007 +0000 @@ -254,10 +254,10 @@ static void silcpurple_wb_request(SilcClient client, const unsigned char *message, - SilcUInt32 message_len, SilcClientEntry sender, - SilcChannelEntry channel) + SilcUInt32 message_len, SilcClientEntry sender, + SilcChannelEntry channel) { - char tmp[128]; + char tmp[256]; SilcPurpleWbRequest req; PurpleConnection *gc; SilcPurple sg; @@ -274,20 +274,24 @@ else wb = silcpurple_wb_init_ch(sg, channel); - silcpurple_wb_parse(wb->proto_data, wb, (unsigned char *)message, - message_len); + silcpurple_wb_parse(wb->proto_data, wb, + (unsigned char *)message, + message_len); return; } + /* Close any previous unaccepted requests */ + purple_request_close_with_handle(sender); + if (!channel) { g_snprintf(tmp, sizeof(tmp), - _("%s sent message to whiteboard. Would you like " - "to open the whiteboard?"), sender->nickname); + _("%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); + _("%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)); @@ -299,10 +303,10 @@ 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)); + purple_request_action(sender, _("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 */