Mercurial > pidgin
diff libpurple/protocols/silc/chat.c @ 17568:980a104267da
Patch from Pekka Riikonen to update the SILC protocol plugin to work with
SILC Toolkit 1.1
I added the fallback to SILC Toolkit 1.0 support (silc10 protocol
directory) and configure.ac adjustments, any problems with this are 100%
my fault.
author | Stu Tomlinson <stu@nosnilmot.com> |
---|---|
date | Sat, 09 Jun 2007 17:31:28 +0000 |
parents | a5176db228b7 |
children | 6b11b1398c2b |
line wrap: on
line diff
--- a/libpurple/protocols/silc/chat.c Sat Jun 09 16:39:00 2007 +0000 +++ b/libpurple/protocols/silc/chat.c Sat Jun 09 17:31:28 2007 +0000 @@ -4,7 +4,7 @@ Author: Pekka Riikonen <priikone@silcnet.org> - Copyright (C) 2004 Pekka Riikonen + Copyright (C) 2004 - 2007 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 @@ -17,7 +17,7 @@ */ -#include "silcincludes.h" +#include "silc.h" #include "silcclient.h" #include "silcpurple.h" #include "wb.h" @@ -61,10 +61,10 @@ static void silcpurple_chat_getinfo_res(SilcClient client, - SilcClientConnection conn, - SilcChannelEntry *channels, - SilcUInt32 channels_count, - void *context) + SilcClientConnection conn, + SilcStatus status, + SilcDList channels, + void *context) { GHashTable *components = context; PurpleConnection *gc = client->application; @@ -134,13 +134,14 @@ } silc_hash_table_list_reset(&htl); - if (channel->channel_key) + if (channel->cipher) g_string_append_printf(s, _("<br><b>Channel Cipher:</b> %s"), - silc_cipher_get_name(channel->channel_key)); + channel->cipher); + if (channel->hmac) /* Definition of HMAC: http://en.wikipedia.org/wiki/HMAC */ g_string_append_printf(s, _("<br><b>Channel HMAC:</b> %s"), - silc_hmac_get_name(channel->hmac)); + channel->hmac); if (channel->topic) { tmp2 = g_markup_escape_text(channel->topic, -1); @@ -211,7 +212,7 @@ SilcPurple sg; SilcChannelEntry channel; PurpleChat *c; - SilcBuffer pubkeys; + SilcDList pubkeys; } *SilcPurpleChauth; static void @@ -227,22 +228,21 @@ SilcUInt32 m; /* Load the public key */ - if (!silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_BIN)) { + if (!silc_pkcs_load_public_key(name, &public_key)) { silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys); - silc_buffer_free(sgc->pubkeys); + silc_dlist_uninit(sgc->pubkeys); silc_free(sgc); purple_notify_error(client->application, - _("Add Channel Public Key"), - _("Could not load public key"), NULL); + _("Add Channel Public Key"), + _("Could not load public key"), NULL); return; } - pk = silc_pkcs_public_key_payload_encode(public_key); + pk = silc_public_key_payload_encode(public_key); chpks = silc_buffer_alloc_size(2); SILC_PUT16_MSB(1, chpks->head); chpks = silc_argument_payload_encode_one(chpks, pk->data, - pk->len, 0x00); + silc_buffer_len(pk), 0x00); silc_buffer_free(pk); m = sgc->channel->mode; @@ -250,15 +250,20 @@ /* Send CMODE */ SILC_PUT32_MSB(m, mode); - chidp = silc_id_payload_encode(sgc->channel->id, SILC_ID_CHANNEL); + chidp = silc_id_payload_encode(&sgc->channel->id, SILC_ID_CHANNEL); silc_client_command_send(client, conn, SILC_COMMAND_CMODE, - ++conn->cmd_ident, 3, - 1, chidp->data, chidp->len, + silcpurple_command_reply, NULL, 3, + 1, chidp->data, silc_buffer_len(chidp), 2, mode, sizeof(mode), - 9, chpks->data, chpks->len); + 9, chpks->data, silc_buffer_len(chpks)); silc_buffer_free(chpks); silc_buffer_free(chidp); - silc_buffer_free(sgc->pubkeys); + if (sgc->pubkeys) { + silc_dlist_start(sgc->pubkeys); + while ((public_key = silc_dlist_get(sgc->pubkeys))) + silc_pkcs_public_key_free(public_key); + silc_dlist_uninit(sgc->pubkeys); + } silc_free(sgc); } @@ -266,8 +271,16 @@ silcpurple_chat_chpk_cancel(void *user_data, const char *name) { SilcPurpleChauth sgc = (SilcPurpleChauth)user_data; + SilcPublicKey public_key; + silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys); - silc_buffer_free(sgc->pubkeys); + + if (sgc->pubkeys) { + silc_dlist_start(sgc->pubkeys); + while ((public_key = silc_dlist_get(sgc->pubkeys))) + silc_pkcs_public_key_free(public_key); + silc_dlist_uninit(sgc->pubkeys); + } silc_free(sgc); } @@ -289,9 +302,9 @@ if (!purple_request_field_list_get_selected(f)) { /* Add new public key */ purple_request_file(sg->gc, _("Open Public Key..."), NULL, FALSE, - G_CALLBACK(silcpurple_chat_chpk_add), - G_CALLBACK(silcpurple_chat_chpk_cancel), - purple_connection_get_account(sg->gc), NULL, NULL, sgc); + G_CALLBACK(silcpurple_chat_chpk_add), + G_CALLBACK(silcpurple_chat_chpk_cancel), + purple_connection_get_account(sg->gc), NULL, NULL, sgc); return; } @@ -302,13 +315,12 @@ public_key = purple_request_field_list_get_data(f, list->data); if (purple_request_field_list_is_selected(f, list->data)) { /* Delete this public key */ - pk = silc_pkcs_public_key_payload_encode(public_key); + pk = silc_public_key_payload_encode(public_key); chpks = silc_argument_payload_encode_one(chpks, pk->data, - pk->len, 0x01); + silc_buffer_len(pk), 0x01); silc_buffer_free(pk); c++; } - silc_pkcs_public_key_free(public_key); } if (!c) { silc_buffer_free(chpks); @@ -322,15 +334,20 @@ /* Send CMODE */ SILC_PUT32_MSB(m, mode); - chidp = silc_id_payload_encode(sgc->channel->id, SILC_ID_CHANNEL); + chidp = silc_id_payload_encode(&sgc->channel->id, SILC_ID_CHANNEL); silc_client_command_send(client, conn, SILC_COMMAND_CMODE, - ++conn->cmd_ident, 3, - 1, chidp->data, chidp->len, + silcpurple_command_reply, NULL, 3, + 1, chidp->data, silc_buffer_len(chidp), 2, mode, sizeof(mode), - 9, chpks->data, chpks->len); + 9, chpks->data, silc_buffer_len(chpks)); silc_buffer_free(chpks); silc_buffer_free(chidp); - silc_buffer_free(sgc->pubkeys); + if (sgc->pubkeys) { + silc_dlist_start(sgc->pubkeys); + while ((public_key = silc_dlist_get(sgc->pubkeys))) + silc_pkcs_public_key_free(public_key); + silc_dlist_uninit(sgc->pubkeys); + } silc_free(sgc); } @@ -339,6 +356,7 @@ { SilcPurple sg = sgc->sg; PurpleRequestField *f; + SilcPublicKey public_key; const char *curpass, *val; int set; @@ -365,19 +383,23 @@ purple_blist_node_remove_setting((PurpleBlistNode *)sgc->c, "passphrase"); } - silc_buffer_free(sgc->pubkeys); + if (sgc->pubkeys) { + silc_dlist_start(sgc->pubkeys); + while ((public_key = silc_dlist_get(sgc->pubkeys))) + silc_pkcs_public_key_free(public_key); + silc_dlist_uninit(sgc->pubkeys); + } silc_free(sgc); } void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel, - SilcBuffer channel_pubkeys) + SilcDList channel_pubkeys) { - SilcUInt16 argc; - SilcArgumentPayload chpks; + SilcPublicKey public_key; + SilcSILCPublicKey silc_pubkey; unsigned char *pk; - SilcUInt32 pk_len, type; + SilcUInt32 pk_len; char *fingerprint, *babbleprint; - SilcPublicKey pubkey; SilcPublicKeyIdentifier ident; char tmp2[1024], t[512]; PurpleRequestFields *fields; @@ -399,7 +421,7 @@ g = purple_request_field_group_new(NULL); f = purple_request_field_string_new("passphrase", _("Channel Passphrase"), - curpass, FALSE); + curpass, FALSE); purple_request_field_string_set_masked(f, TRUE); purple_request_field_group_add_field(g, f); purple_request_fields_add_group(fields, g); @@ -416,55 +438,49 @@ "is required to be able to join. If channel public keys are set " "then only users whose public keys are listed are able to join.")); - if (!channel_pubkeys) { + if (!channel_pubkeys || !silc_dlist_count(channel_pubkeys)) { f = purple_request_field_list_new("list", NULL); purple_request_field_group_add_field(g, f); purple_request_fields(sg->gc, _("Channel Authentication"), - _("Channel Authentication"), t, fields, - _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb), - _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok), - purple_connection_get_account(sg->gc), NULL, NULL, sgc); + _("Channel Authentication"), t, fields, + _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb), + _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok), + purple_connection_get_account(sg->gc), NULL, NULL, sgc); + if (channel_pubkeys) + silc_dlist_uninit(channel_pubkeys); return; } - sgc->pubkeys = silc_buffer_copy(channel_pubkeys); + sgc->pubkeys = channel_pubkeys; g = purple_request_field_group_new(NULL); f = purple_request_field_list_new("list", NULL); purple_request_field_group_add_field(g, f); purple_request_fields_add_group(fields, g); - SILC_GET16_MSB(argc, channel_pubkeys->data); - chpks = silc_argument_payload_parse(channel_pubkeys->data + 2, - channel_pubkeys->len - 2, argc); - if (!chpks) - return; - - pk = silc_argument_get_first_arg(chpks, &type, &pk_len); - while (pk) { + silc_dlist_start(channel_pubkeys); + while ((public_key = silc_dlist_get(channel_pubkeys))) { + pk = silc_pkcs_public_key_encode(public_key, &pk_len); fingerprint = silc_hash_fingerprint(NULL, pk + 4, pk_len - 4); babbleprint = silc_hash_babbleprint(NULL, pk + 4, pk_len - 4); - silc_pkcs_public_key_payload_decode(pk, pk_len, &pubkey); - ident = silc_pkcs_decode_identifier(pubkey->identifier); + + silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key); + ident = &silc_pubkey->identifier; g_snprintf(tmp2, sizeof(tmp2), "%s\n %s\n %s", ident->realname ? ident->realname : ident->username ? ident->username : "", fingerprint, babbleprint); - purple_request_field_list_add(f, tmp2, pubkey); + purple_request_field_list_add(f, tmp2, public_key); silc_free(fingerprint); silc_free(babbleprint); - silc_pkcs_free_identifier(ident); - pk = silc_argument_get_next_arg(chpks, &type, &pk_len); } purple_request_field_list_set_multi_select(f, FALSE); purple_request_fields(sg->gc, _("Channel Authentication"), - _("Channel Authentication"), t, fields, - _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb), - _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok), - purple_connection_get_account(sg->gc), NULL, NULL, sgc); - - silc_argument_payload_free(chpks); + _("Channel Authentication"), t, fields, + _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb), + _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok), + purple_connection_get_account(sg->gc), NULL, NULL, sgc); } static void @@ -525,9 +541,9 @@ /* Add private group to buddy list */ g_snprintf(tmp, sizeof(tmp), "%s [Private Group]", name); - comp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); - g_hash_table_replace(comp, g_strdup("channel"), g_strdup(tmp)); - g_hash_table_replace(comp, g_strdup("passphrase"), g_strdup(passphrase)); + comp = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); + g_hash_table_replace(comp, "channel", g_strdup(tmp)); + g_hash_table_replace(comp, "passphrase", g_strdup(passphrase)); cn = purple_chat_new(sg->account, alias, comp); g = (PurpleGroup *)p->c->node.parent; @@ -596,9 +612,9 @@ _("Please enter the %s channel private group name and passphrase."), p->channel); purple_request_fields(gc, _("Add Channel Private Group"), NULL, tmp, fields, - _("Add"), G_CALLBACK(silcpurple_chat_prv_add), - _("Cancel"), G_CALLBACK(silcpurple_chat_prv_cancel), - purple_connection_get_account(gc), NULL, NULL, p); + _("Add"), G_CALLBACK(silcpurple_chat_prv_add), + _("Cancel"), G_CALLBACK(silcpurple_chat_prv_cancel), + purple_connection_get_account(gc), NULL, NULL, p); } @@ -907,7 +923,7 @@ m = g_list_append(m, act); } - if (mode & SILC_CHANNEL_UMODE_CHANFO) { + if (chu && mode & SILC_CHANNEL_UMODE_CHANFO) { act = purple_menu_action_new(_("Channel Authentication"), PURPLE_CALLBACK(silcpurple_chat_chauth), NULL, NULL); @@ -926,7 +942,7 @@ } } - if (mode & SILC_CHANNEL_UMODE_CHANOP) { + if (chu && mode & SILC_CHANNEL_UMODE_CHANOP) { act = purple_menu_action_new(_("Set User Limit"), PURPLE_CALLBACK(silcpurple_chat_ulimit), NULL, NULL); @@ -969,7 +985,7 @@ } } - if (channel) { + if (chu && channel) { SilcPurpleChatWb wb; wb = silc_calloc(1, sizeof(*wb)); wb->sg = sg; @@ -986,86 +1002,10 @@ /******************************* Joining Etc. ********************************/ -void silcpurple_chat_join_done(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - SilcChannelEntry channel = context; - PurpleConversation *convo; - SilcUInt32 retry = SILC_PTR_TO_32(channel->context); - SilcHashTableList htl; - SilcChannelUser chu; - GList *users = NULL, *flags = NULL; - char tmp[256]; - - if (!clients && retry < 1) { - /* Resolving users failed, try again. */ - channel->context = SILC_32_TO_PTR(retry + 1); - silc_client_get_clients_by_channel(client, conn, channel, - silcpurple_chat_join_done, channel); - return; - } - - /* Add channel to Purple */ - channel->context = SILC_32_TO_PTR(++sg->channel_ids); - serv_got_joined_chat(gc, sg->channel_ids, channel->channel_name); - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - return; - - /* Add all users to channel */ - silc_hash_table_list(channel->user_list, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - PurpleConvChatBuddyFlags f = PURPLE_CBFLAGS_NONE; - if (!chu->client->nickname) - continue; - chu->context = SILC_32_TO_PTR(sg->channel_ids); - - if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) - f |= PURPLE_CBFLAGS_FOUNDER; - if (chu->mode & SILC_CHANNEL_UMODE_CHANOP) - f |= PURPLE_CBFLAGS_OP; - users = g_list_append(users, g_strdup(chu->client->nickname)); - flags = g_list_append(flags, GINT_TO_POINTER(f)); - - if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) { - if (chu->client == conn->local_entry) - g_snprintf(tmp, sizeof(tmp), - _("You are channel founder on <I>%s</I>"), - channel->channel_name); - else - g_snprintf(tmp, sizeof(tmp), - _("Channel founder on <I>%s</I> is <I>%s</I>"), - channel->channel_name, chu->client->nickname); - - purple_conversation_write(convo, NULL, tmp, - PURPLE_MESSAGE_SYSTEM, time(NULL)); - - } - } - silc_hash_table_list_reset(&htl); - - purple_conv_chat_add_users(PURPLE_CONV_CHAT(convo), users, NULL, flags, FALSE); - g_list_free(users); - g_list_free(flags); - - /* Set topic */ - if (channel->topic) - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, channel->topic); - - /* Set nick */ - purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), conn->local_entry->nickname); -} - char *silcpurple_get_chat_name(GHashTable *data) { return g_strdup(g_hash_table_lookup(data, "channel")); -} +} void silcpurple_chat_join(PurpleConnection *gc, GHashTable *data) { @@ -1073,6 +1013,7 @@ SilcClient client = sg->client; SilcClientConnection conn = sg->conn; const char *channel, *passphrase, *parentch; + PurpleChat *chat; if (!conn) return; @@ -1128,6 +1069,20 @@ return; } + /* 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); + } + /* XXX We should have other properties here as well: 1. whether to try to authenticate to the channel 1a. with default key, @@ -1150,7 +1105,7 @@ } void silcpurple_chat_invite(PurpleConnection *gc, int id, const char *msg, - const char *name) + const char *name) { SilcPurple sg = gc->proto_data; SilcClient client = sg->client; @@ -1264,7 +1219,8 @@ } } -int silcpurple_chat_send(PurpleConnection *gc, int id, const char *msg, PurpleMessageFlags msgflags) +int silcpurple_chat_send(PurpleConnection *gc, int id, const char *msg, + PurpleMessageFlags msgflags) { SilcPurple sg = gc->proto_data; SilcClient client = sg->client; @@ -1274,10 +1230,13 @@ SilcChannelEntry channel = NULL; SilcChannelPrivateKey key = NULL; SilcUInt32 flags; - int ret; + int ret = 0; char *msg2, *tmp; gboolean found = FALSE; gboolean sign = purple_account_get_bool(sg->account, "sign-verify", FALSE); +#ifdef HAVE_SILCMIME_H + SilcDList list; +#endif if (!msg || !conn) return 0; @@ -1297,7 +1256,7 @@ } else if (strlen(msg) > 1 && msg[0] == '/') { if (!silc_client_command_call(client, conn, msg + 1)) purple_notify_error(gc, _("Call Command"), _("Cannot call command"), - _("Unknown command")); + _("Unknown command")); g_free(tmp); return 0; } @@ -1346,10 +1305,37 @@ channel = chu->channel; } +#ifdef HAVE_SILCMIME_H + /* Check for images */ + if (msgflags & PURPLE_MESSAGE_IMAGES) { + list = silcpurple_image_message(msg, &flags); + if (list) { + /* Send one or more MIME message. If more than one, they + are MIME fragments due to over large message */ + SilcBuffer buf; + + silc_dlist_start(list); + while ((buf = silc_dlist_get(list)) != SILC_LIST_END) + ret = + silc_client_send_channel_message(client, conn, + channel, key, + flags, NULL, + buf->data, + silc_buffer_len(buf)); + silc_mime_partial_free(list); + g_free(tmp); + + if (ret) + serv_got_chat_in(gc, id, purple_connection_get_display_name(gc), 0, msg, time(NULL)); + return ret; + } + } +#endif + /* Send channel message */ ret = silc_client_send_channel_message(client, conn, channel, key, - flags, (unsigned char *)msg2, - strlen(msg2), TRUE); + flags, NULL, (unsigned char *)msg2, + strlen(msg2)); if (ret) { serv_got_chat_in(gc, id, purple_connection_get_display_name(gc), 0, msg, time(NULL));