src/protocols/silc/chat.c

branch
gaim
changeset 20470
77693555855f
parent 13071
b98e72d4089a
parent 20469
b2836a24d81e
child 20471
1966704b3e42
--- a/src/protocols/silc/chat.c	Mon Apr 16 00:43:53 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1450 +0,0 @@
-/*
-
-  silcgaim_chat.c
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2004 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"
-
-/***************************** Channel Routines ******************************/
-
-GList *silcgaim_chat_info(GaimConnection *gc)
-{
-	GList *ci = NULL;
-	struct proto_chat_entry *pce;
-
-	pce = g_new0(struct proto_chat_entry, 1);
-	pce->label = _("_Channel:");
-	pce->identifier = "channel";
-	pce->required = TRUE;
-	ci = g_list_append(ci, pce);
-
-	pce = g_new0(struct proto_chat_entry, 1);
-	pce->label = _("_Passphrase:");
-	pce->identifier = "passphrase";
-	pce->secret = TRUE;
-	ci = g_list_append(ci, pce);
-
-	return ci;
-}
-
-GHashTable *silcgaim_chat_info_defaults(GaimConnection *gc, const char *chat_name)
-{
-	GHashTable *defaults;
-
-	defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
-
-	if (chat_name != NULL)
-		g_hash_table_insert(defaults, "channel", g_strdup(chat_name));
-
-	return defaults;
-}
-
-static void
-silcgaim_chat_getinfo(GaimConnection *gc, GHashTable *components);
-
-static void
-silcgaim_chat_getinfo_res(SilcClient client,
-			  SilcClientConnection conn,
-			  SilcChannelEntry *channels,
-			  SilcUInt32 channels_count,
-			  void *context)
-{
-	GHashTable *components = context;
-	GaimConnection *gc = client->application;
-	const char *chname;
-	char tmp[256];
-
-	chname = g_hash_table_lookup(components, "channel");
-	if (!chname)
-		return;
-
-	if (!channels) {
-		g_snprintf(tmp, sizeof(tmp),
-			   _("Channel %s does not exist in the network"), chname);
-		gaim_notify_error(gc, _("Channel Information"),
-				  _("Cannot get channel information"), tmp);
-		return;
-	}
-
-	silcgaim_chat_getinfo(gc, components);
-}
-
-
-static void
-silcgaim_chat_getinfo(GaimConnection *gc, GHashTable *components)
-{
-	SilcGaim sg = gc->proto_data;
-	const char *chname;
-	char *buf, tmp[256], *tmp2;
-	GString *s;
-	SilcChannelEntry channel;
-	SilcHashTableList htl;
-	SilcChannelUser chu;
-
-	if (!components)
-		return;
-
-	chname = g_hash_table_lookup(components, "channel");
-	if (!chname)
-		return;
-	channel = silc_client_get_channel(sg->client, sg->conn,
-					  (char *)chname);
-	if (!channel) {
-		silc_client_get_channel_resolve(sg->client, sg->conn,
-						(char *)chname,
-						silcgaim_chat_getinfo_res,
-						components);
-		return;
-	}
-
-	s = g_string_new("");
-	tmp2 = g_markup_escape_text(channel->channel_name, -1);
-	g_string_append_printf(s, _("<b>Channel Name:</b> %s"), tmp2);
-	g_free(tmp2);
-	if (channel->user_list && silc_hash_table_count(channel->user_list))
-		g_string_append_printf(s, _("<br><b>User Count:</b> %d"),
-				       (int)silc_hash_table_count(channel->user_list));
-
-	silc_hash_table_list(channel->user_list, &htl);
-	while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-		if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) {
-			tmp2 = g_markup_escape_text(chu->client->nickname, -1);
-			g_string_append_printf(s, _("<br><b>Channel Founder:</b> %s"),
-					       tmp2);
-			g_free(tmp2);
-			break;
-		}
-	}
-	silc_hash_table_list_reset(&htl);
-
-	if (channel->channel_key)
-		g_string_append_printf(s, _("<br><b>Channel Cipher:</b> %s"),
-				       silc_cipher_get_name(channel->channel_key));
-	if (channel->hmac)
-		g_string_append_printf(s, _("<br><b>Channel HMAC:</b> %s"),
-				       silc_hmac_get_name(channel->hmac));
-
-	if (channel->topic) {
-		tmp2 = g_markup_escape_text(channel->topic, -1);
-		g_string_append_printf(s, _("<br><b>Channel Topic:</b><br>%s"), tmp2);
-		g_free(tmp2);
-	}
-
-	if (channel->mode) {
-		g_string_append_printf(s, _("<br><b>Channel Modes:</b> "));
-		silcgaim_get_chmode_string(channel->mode, tmp, sizeof(tmp));
-		g_string_append(s, tmp);
-	}
-
-	if (channel->founder_key) {
-		char *fingerprint, *babbleprint;
-		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);
-
-		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);
-	}
-
-	buf = g_string_free(s, FALSE);
-	gaim_notify_formatted(gc, NULL, _("Channel Information"), NULL, buf, NULL, NULL);
-	g_free(buf);
-}
-
-
-static void
-silcgaim_chat_getinfo_menu(GaimBlistNode *node, gpointer data)
-{
-	GaimChat *chat = (GaimChat *)node;
-	silcgaim_chat_getinfo(chat->account->gc, chat->components);
-}
-
-
-#if 0   /* XXX For now these are not implemented.  We need better
-	   listview dialog from Gaim for these. */
-/************************** Channel Invite List ******************************/
-
-static void
-silcgaim_chat_invitelist(GaimBlistNode *node, gpointer data);
-{
-
-}
-
-
-/**************************** Channel Ban List *******************************/
-
-static void
-silcgaim_chat_banlist(GaimBlistNode *node, gpointer data);
-{
-
-}
-#endif
-
-
-/************************* Channel Authentication ****************************/
-
-typedef struct {
-	SilcGaim sg;
-	SilcChannelEntry channel;
-	GaimChat *c;
-	SilcBuffer pubkeys;
-} *SilcGaimChauth;
-
-static void
-silcgaim_chat_chpk_add(void *user_data, const char *name)
-{
-	SilcGaimChauth sgc = (SilcGaimChauth)user_data;
-	SilcGaim sg = sgc->sg;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcPublicKey public_key;
-	SilcBuffer chpks, pk, chidp;
-	unsigned char mode[4];
-	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)) {
-		silcgaim_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys);
-		silc_buffer_free(sgc->pubkeys);
-		silc_free(sgc);
-		gaim_notify_error(client->application,
-				  _("Add Channel Public Key"),
-				  _("Could not load public key"), NULL);
-		return;
-	}
-
-	pk = silc_pkcs_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_free(pk);
-
-	m = sgc->channel->mode;
-	m |= SILC_CHANNEL_MODE_CHANNEL_AUTH;
-
-	/* Send CMODE */
-	SILC_PUT32_MSB(m, mode);
-	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,
-				 2, mode, sizeof(mode),
-				 9, chpks->data, chpks->len);
-	silc_buffer_free(chpks);
-	silc_buffer_free(chidp);
-	silc_buffer_free(sgc->pubkeys);
-	silc_free(sgc);
-}
-
-static void
-silcgaim_chat_chpk_cancel(void *user_data, const char *name)
-{
-	SilcGaimChauth sgc = (SilcGaimChauth)user_data;
-	silcgaim_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys);
-	silc_buffer_free(sgc->pubkeys);
-	silc_free(sgc);
-}
-
-static void
-silcgaim_chat_chpk_cb(SilcGaimChauth sgc, GaimRequestFields *fields)
-{
-	SilcGaim sg = sgc->sg;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	GaimRequestField *f;
-	const GList *list;
-	SilcPublicKey public_key;
-	SilcBuffer chpks, pk, chidp;
-	SilcUInt16 c = 0, ct;
-	unsigned char mode[4];
-	SilcUInt32 m;
-
-	f = gaim_request_fields_get_field(fields, "list");
-	if (!gaim_request_field_list_get_selected(f)) {
-		/* Add new public key */
-		gaim_request_file(sg->gc, _("Open Public Key..."), NULL, FALSE,
-				  G_CALLBACK(silcgaim_chat_chpk_add),
-				  G_CALLBACK(silcgaim_chat_chpk_cancel), sgc);
-		return;
-	}
-
-	list = gaim_request_field_list_get_items(f);
-	chpks = silc_buffer_alloc_size(2);
-
-	for (ct = 0; list; list = list->next, ct++) {
-		public_key = gaim_request_field_list_get_data(f, list->data);
-		if (gaim_request_field_list_is_selected(f, list->data)) {
-			/* Delete this public key */
-			pk = silc_pkcs_public_key_payload_encode(public_key);
-			chpks = silc_argument_payload_encode_one(chpks, pk->data,
-								 pk->len, 0x01);
-			silc_buffer_free(pk);
-			c++;
-		}
-		silc_pkcs_public_key_free(public_key);
-	}
-	if (!c) {
-		silc_buffer_free(chpks);
-		return;
-	}
-	SILC_PUT16_MSB(c, chpks->head);
-
-	m = sgc->channel->mode;
-	if (ct == c)
-		m &= ~SILC_CHANNEL_MODE_CHANNEL_AUTH;
-
-	/* Send CMODE */
-	SILC_PUT32_MSB(m, mode);
-	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,
-				 2, mode, sizeof(mode),
-				 9, chpks->data, chpks->len);
-	silc_buffer_free(chpks);
-	silc_buffer_free(chidp);
-	silc_buffer_free(sgc->pubkeys);
-	silc_free(sgc);
-}
-
-static void
-silcgaim_chat_chauth_ok(SilcGaimChauth sgc, GaimRequestFields *fields)
-{
-	SilcGaim sg = sgc->sg;
-	GaimRequestField *f;
-	const char *curpass, *val;
-	int set;
-
-	f = gaim_request_fields_get_field(fields, "passphrase");
-	val = gaim_request_field_string_get_value(f);
-	curpass = gaim_blist_node_get_string((GaimBlistNode *)sgc->c, "passphrase");
-
-	if (!val && curpass)
-		set = 0;
-	else if (val && !curpass)
-		set = 1;
-	else if (val && curpass && strcmp(val, curpass))
-		set = 1;
-	else
-		set = -1;
-
-	if (set == 1) {
-		silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-					 sgc->channel->channel_name, "+a", val, NULL);
-		gaim_blist_node_set_string((GaimBlistNode *)sgc->c, "passphrase", val);
-	} else if (set == 0) {
-		silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-					 sgc->channel->channel_name, "-a", NULL);
-		gaim_blist_node_remove_setting((GaimBlistNode *)sgc->c, "passphrase");
-	}
-
-	silc_buffer_free(sgc->pubkeys);
-	silc_free(sgc);
-}
-
-void silcgaim_chat_chauth_show(SilcGaim sg, SilcChannelEntry channel,
-			       SilcBuffer channel_pubkeys)
-{
-	SilcUInt16 argc;
-	SilcArgumentPayload chpks;
-	unsigned char *pk;
-	SilcUInt32 pk_len, type;
-	char *fingerprint, *babbleprint;
-	SilcPublicKey pubkey;
-	SilcPublicKeyIdentifier ident;
-	char tmp2[1024], t[512];
-	GaimRequestFields *fields;
-	GaimRequestFieldGroup *g;
-	GaimRequestField *f;
-	SilcGaimChauth sgc;
-	const char *curpass = NULL;
-
-	sgc = silc_calloc(1, sizeof(*sgc));
-	if (!sgc)
-		return;
-	sgc->sg = sg;
-	sgc->channel = channel;
-
-	fields = gaim_request_fields_new();
-
-	if (sgc->c)
-	  curpass = gaim_blist_node_get_string((GaimBlistNode *)sgc->c, "passphrase");
-
-	g = gaim_request_field_group_new(NULL);
-	f = gaim_request_field_string_new("passphrase", _("Channel Passphrase"),
-					  curpass, FALSE);
-	gaim_request_field_string_set_masked(f, TRUE);
-	gaim_request_field_group_add_field(g, f);
-	gaim_request_fields_add_group(fields, g);
-
-	g = gaim_request_field_group_new(NULL);
-	f = gaim_request_field_label_new("l1", _("Channel Public Keys List"));
-	gaim_request_field_group_add_field(g, f);
-	gaim_request_fields_add_group(fields, g);
-
-	g_snprintf(t, sizeof(t),
-		   _("Channel authentication is used to secure the channel from "
-		     "unauthorized access. The authentication may be based on "
-		     "passphrase and digital signatures. If passphrase is set, it "
-		     "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) {
-		f = gaim_request_field_list_new("list", NULL);
-		gaim_request_field_group_add_field(g, f);
-		gaim_request_fields(sg->gc, _("Channel Authentication"),
-				    _("Channel Authentication"), t, fields,
-				    _("Add / Remove"), G_CALLBACK(silcgaim_chat_chpk_cb),
-				    _("OK"), G_CALLBACK(silcgaim_chat_chauth_ok), sgc);
-		return;
-	}
-	sgc->pubkeys = silc_buffer_copy(channel_pubkeys);
-
-	g = gaim_request_field_group_new(NULL);
-	f = gaim_request_field_list_new("list", NULL);
-	gaim_request_field_group_add_field(g, f);
-	gaim_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) {
-		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);
-
-		g_snprintf(tmp2, sizeof(tmp2), "%s\n  %s\n  %s",
-			   ident->realname ? ident->realname : ident->username ?
-			   ident->username : "", fingerprint, babbleprint);
-		gaim_request_field_list_add(f, tmp2, pubkey);
-
-		silc_free(fingerprint);
-		silc_free(babbleprint);
-		silc_pkcs_free_identifier(ident);
-		pk = silc_argument_get_next_arg(chpks, &type, &pk_len);
-	}
-
-	gaim_request_field_list_set_multi_select(f, FALSE);
-	gaim_request_fields(sg->gc, _("Channel Authentication"),
-			    _("Channel Authentication"), t, fields,
-			    _("Add / Remove"), G_CALLBACK(silcgaim_chat_chpk_cb),
-			    _("OK"), G_CALLBACK(silcgaim_chat_chauth_ok), sgc);
-
-	silc_argument_payload_free(chpks);
-}
-
-static void
-silcgaim_chat_chauth(GaimBlistNode *node, gpointer data)
-{
-	GaimChat *chat;
-	GaimConnection *gc;
-	SilcGaim sg;
-
-	g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node));
-
-	chat = (GaimChat *) node;
-	gc = gaim_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(chat->components, "channel"),
-				 "+C", NULL);
-}
-
-
-/************************** Channel Private Groups **************************/
-
-/* Private groups are "virtual" channels.  They are groups inside a channel.
-   This is implemented by using channel private keys.  By knowing a channel
-   private key user becomes part of that group and is able to talk on that
-   group.  Other users, on the same channel, won't be able to see the
-   messages of that group.  It is possible to have multiple groups inside
-   a channel - and thus having multiple private keys on the channel. */
-
-typedef struct {
-	SilcGaim sg;
-	GaimChat *c;
-	const char *channel;
-} *SilcGaimCharPrv;
-
-static void
-silcgaim_chat_prv_add(SilcGaimCharPrv p, GaimRequestFields *fields)
-{
-	SilcGaim sg = p->sg;
-	char tmp[512];
-	GaimRequestField *f;
-	const char *name, *passphrase, *alias;
-	GHashTable *comp;
-	GaimGroup *g;
-	GaimChat *cn;
-
-	f = gaim_request_fields_get_field(fields, "name");
-	name = gaim_request_field_string_get_value(f);
-	if (!name) {
-		silc_free(p);
-		return;
-	}
-	f = gaim_request_fields_get_field(fields, "passphrase");
-	passphrase = gaim_request_field_string_get_value(f);
-	f = gaim_request_fields_get_field(fields, "alias");
-	alias = gaim_request_field_string_get_value(f);
-
-	/* 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));
-
-	cn = gaim_chat_new(sg->account, alias, comp);
-	g = (GaimGroup *)p->c->node.parent;
-	gaim_blist_add_chat(cn, g, (GaimBlistNode *)p->c);
-
-	/* Associate to a real channel */
-	gaim_blist_node_set_string((GaimBlistNode *)cn, "parentch", p->channel);
-
-	/* Join the group */
-	silcgaim_chat_join(sg->gc, comp);
-
-	silc_free(p);
-}
-
-static void
-silcgaim_chat_prv_cancel(SilcGaimCharPrv p, GaimRequestFields *fields)
-{
-	silc_free(p);
-}
-
-static void
-silcgaim_chat_prv(GaimBlistNode *node, gpointer data)
-{
-	GaimChat *chat;
-	GaimConnection *gc;
-	SilcGaim sg;
-
-	SilcGaimCharPrv p;
-	GaimRequestFields *fields;
-	GaimRequestFieldGroup *g;
-	GaimRequestField *f;
-	char tmp[512];
-
-	g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node));
-
-	chat = (GaimChat *) node;
-	gc = gaim_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	p = silc_calloc(1, sizeof(*p));
-	if (!p)
-		return;
-	p->sg = sg;
-
-	p->channel = g_hash_table_lookup(chat->components, "channel");
-	p->c = gaim_blist_find_chat(sg->account, p->channel);
-
-	fields = gaim_request_fields_new();
-
-	g = gaim_request_field_group_new(NULL);
-	f = gaim_request_field_string_new("name", _("Group Name"),
-					  NULL, FALSE);
-	gaim_request_field_group_add_field(g, f);
-
-	f = gaim_request_field_string_new("passphrase", _("Passphrase"),
-					  NULL, FALSE);
-	gaim_request_field_string_set_masked(f, TRUE);
-	gaim_request_field_group_add_field(g, f);
-
-	f = gaim_request_field_string_new("alias", _("Alias"),
-					  NULL, FALSE);
-	gaim_request_field_group_add_field(g, f);
-	gaim_request_fields_add_group(fields, g);
-
-	g_snprintf(tmp, sizeof(tmp),
-		   _("Please enter the %s channel private group name and passphrase."),
-		   p->channel);
-	gaim_request_fields(gc, _("Add Channel Private Group"), NULL, tmp, fields,
-			    _("Add"), G_CALLBACK(silcgaim_chat_prv_add),
-			    _("Cancel"), G_CALLBACK(silcgaim_chat_prv_cancel), p);
-}
-
-
-/****************************** Channel Modes ********************************/
-
-static void
-silcgaim_chat_permanent_reset(GaimBlistNode *node, gpointer data)
-{
-	GaimChat *chat;
-	GaimConnection *gc;
-	SilcGaim sg;
-
-	g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node));
-
-	chat = (GaimChat *) node;
-	gc = gaim_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(chat->components, "channel"),
-				 "-f", NULL);
-}
-
-static void
-silcgaim_chat_permanent(GaimBlistNode *node, gpointer data)
-{
-	GaimChat *chat;
-	GaimConnection *gc;
-	SilcGaim sg;
-	const char *channel;
-
-	g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node));
-
-	chat = (GaimChat *) node;
-	gc = gaim_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	if (!sg->conn)
-		return;
-
-	/* XXX we should have ability to define which founder
-	   key to use.  Now we use the user's own public key
-	   (default key). */
-
-	/* Call CMODE */
-	channel = g_hash_table_lookup(chat->components, "channel");
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", channel,
-				 "+f", NULL);
-}
-
-typedef struct {
-	SilcGaim sg;
-	const char *channel;
-} *SilcGaimChatInput;
-
-static void
-silcgaim_chat_ulimit_cb(SilcGaimChatInput s, const char *limit)
-{
-	SilcChannelEntry channel;
-	int ulimit = 0;
-
-	channel = silc_client_get_channel(s->sg->client, s->sg->conn,
-					  (char *)s->channel);
-	if (!channel)
-		return;
-	if (limit)
-		ulimit = atoi(limit);
-
-	if (!limit || !(*limit) || *limit == '0') {
-		if (limit && ulimit == channel->user_limit) {
-			silc_free(s);
-			return;
-		}
-		silc_client_command_call(s->sg->client, s->sg->conn, NULL, "CMODE",
-					 s->channel, "-l", NULL);
-
-		silc_free(s);
-		return;
-	}
-
-	if (ulimit == channel->user_limit) {
-		silc_free(s);
-		return;
-	}
-
-	/* Call CMODE */
-	silc_client_command_call(s->sg->client, s->sg->conn, NULL, "CMODE",
-				 s->channel, "+l", limit, NULL);
-
-	silc_free(s);
-}
-
-static void
-silcgaim_chat_ulimit(GaimBlistNode *node, gpointer data)
-{
-	GaimChat *chat;
-	GaimConnection *gc;
-	SilcGaim sg;
-
-	SilcGaimChatInput s;
-	SilcChannelEntry channel;
-	const char *ch;
-	char tmp[32];
-
-	g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node));
-
-	chat = (GaimChat *) node;
-	gc = gaim_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	if (!sg->conn)
-		return;
-
-	ch = g_strdup(g_hash_table_lookup(chat->components, "channel"));
-	channel = silc_client_get_channel(sg->client, sg->conn, (char *)ch);
-	if (!channel)
-		return;
-
-	s = silc_calloc(1, sizeof(*s));
-	if (!s)
-		return;
-	s->channel = ch;
-	s->sg = sg;
-	g_snprintf(tmp, sizeof(tmp), "%d", (int)channel->user_limit);
-	gaim_request_input(gc, _("User Limit"), NULL,
-			   _("Set user limit on channel. Set to zero to reset user limit."),
-			   tmp, FALSE, FALSE, NULL,
-			   _("OK"), G_CALLBACK(silcgaim_chat_ulimit_cb),
-			   _("Cancel"), G_CALLBACK(silcgaim_chat_ulimit_cb), s);
-}
-
-static void
-silcgaim_chat_resettopic(GaimBlistNode *node, gpointer data)
-{
-	GaimChat *chat;
-	GaimConnection *gc;
-	SilcGaim sg;
-
-	g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node));
-
-	chat = (GaimChat *) node;
-	gc = gaim_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(chat->components, "channel"),
-				 "-t", NULL);
-}
-
-static void
-silcgaim_chat_settopic(GaimBlistNode *node, gpointer data)
-{
-	GaimChat *chat;
-	GaimConnection *gc;
-	SilcGaim sg;
-
-	g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node));
-
-	chat = (GaimChat *) node;
-	gc = gaim_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(chat->components, "channel"),
-				 "+t", NULL);
-}
-
-static void
-silcgaim_chat_resetprivate(GaimBlistNode *node, gpointer data)
-{
-	GaimChat *chat;
-	GaimConnection *gc;
-	SilcGaim sg;
-
-	g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node));
-
-	chat = (GaimChat *) node;
-	gc = gaim_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(chat->components, "channel"),
-				 "-p", NULL);
-}
-
-static void
-silcgaim_chat_setprivate(GaimBlistNode *node, gpointer data)
-{
-	GaimChat *chat;
-	GaimConnection *gc;
-	SilcGaim sg;
-
-	g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node));
-
-	chat = (GaimChat *) node;
-	gc = gaim_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(chat->components, "channel"),
-				 "+p", NULL);
-}
-
-static void
-silcgaim_chat_resetsecret(GaimBlistNode *node, gpointer data)
-{
-	GaimChat *chat;
-	GaimConnection *gc;
-	SilcGaim sg;
-
-	g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node));
-
-	chat = (GaimChat *) node;
-	gc = gaim_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(chat->components, "channel"),
-				 "-s", NULL);
-}
-
-static void
-silcgaim_chat_setsecret(GaimBlistNode *node, gpointer data)
-{
-	GaimChat *chat;
-	GaimConnection *gc;
-	SilcGaim sg;
-
-	g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node));
-
-	chat = (GaimChat *) node;
-	gc = gaim_account_get_connection(chat->account);
-	sg = gc->proto_data;
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(chat->components, "channel"),
-				 "+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;
-	GaimConnection *gc = gaim_account_get_connection(chat->account);
-	SilcGaim sg = gc->proto_data;
-	SilcClientConnection conn = sg->conn;
-	const char *chname = NULL;
-	SilcChannelEntry channel = NULL;
-	SilcChannelUser chu = NULL;
-	SilcUInt32 mode = 0;
-
-	GList *m = NULL;
-	GaimMenuAction *act;
-
-	if (components)
-		chname = g_hash_table_lookup(components, "channel");
-	if (chname)
-		channel = silc_client_get_channel(sg->client, sg->conn,
-						  (char *)chname);
-	if (channel) {
-		chu = silc_client_on_channel(channel, conn->local_entry);
-		if (chu)
-			mode = chu->mode;
-	}
-
-	if (strstr(chname, "[Private Group]"))
-		return NULL;
-
-	act = gaim_menu_action_new(_("Get Info"),
-	                           GAIM_CALLBACK(silcgaim_chat_getinfo_menu),
-	                           NULL, NULL);
-	m = g_list_append(m, act);
-
-#if 0   /* XXX For now these are not implemented.  We need better
-	   listview dialog from Gaim for these. */
-	if (mode & SILC_CHANNEL_UMODE_CHANOP) {
-		act = gaim_menu_action_new(_("Invite List"),
-		                           GAIM_CALLBACK(silcgaim_chat_invitelist),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-
-		act = gaim_menu_action_new(_("Ban List"),
-		                           GAIM_CALLBACK(silcgaim_chat_banlist),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-	}
-#endif
-
-	if (chu) {
-		act = gaim_menu_action_new(_("Add Private Group"),
-		                           GAIM_CALLBACK(silcgaim_chat_prv),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-	}
-
-	if (mode & SILC_CHANNEL_UMODE_CHANFO) {
-		act = gaim_menu_action_new(_("Channel Authentication"),
-		                           GAIM_CALLBACK(silcgaim_chat_chauth),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-
-		if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
-			act = gaim_menu_action_new(_("Reset Permanent"),
-			                           GAIM_CALLBACK(silcgaim_chat_permanent_reset),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		} else {
-			act = gaim_menu_action_new(_("Set Permanent"),
-			                           GAIM_CALLBACK(silcgaim_chat_permanent),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		}
-	}
-
-	if (mode & SILC_CHANNEL_UMODE_CHANOP) {
-		act = gaim_menu_action_new(_("Set User Limit"),
-		                           GAIM_CALLBACK(silcgaim_chat_ulimit),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-
-		if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
-			act = gaim_menu_action_new(_("Reset Topic Restriction"),
-			                           GAIM_CALLBACK(silcgaim_chat_resettopic),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		} else {
-			act = gaim_menu_action_new(_("Set Topic Restriction"),
-			                           GAIM_CALLBACK(silcgaim_chat_settopic),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		}
-
-		if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) {
-			act = gaim_menu_action_new(_("Reset Private Channel"),
-			                           GAIM_CALLBACK(silcgaim_chat_resetprivate),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		} else {
-			act = gaim_menu_action_new(_("Set Private Channel"),
-			                           GAIM_CALLBACK(silcgaim_chat_setprivate),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		}
-
-		if (channel->mode & SILC_CHANNEL_MODE_SECRET) {
-			act = gaim_menu_action_new(_("Reset Secret Channel"),
-			                           GAIM_CALLBACK(silcgaim_chat_resetsecret),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		} else {
-			act = gaim_menu_action_new(_("Set Secret Channel"),
-			                           GAIM_CALLBACK(silcgaim_chat_setsecret),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		}
-	}
-
-	if (channel) {
-		SilcGaimChatWb wb;
-		wb = silc_calloc(1, sizeof(*wb));
-		wb->sg = sg;
-		wb->channel = channel;
-		act = gaim_menu_action_new(_("Draw On Whiteboard"),
-		                           GAIM_CALLBACK(silcgaim_chat_wb),
-		                           (void *)wb, NULL);
-		m = g_list_append(m, act);
-	}
-
-	return m;
-}
-
-
-/******************************* Joining Etc. ********************************/
-
-void silcgaim_chat_join_done(SilcClient client,
-			     SilcClientConnection conn,
-			     SilcClientEntry *clients,
-			     SilcUInt32 clients_count,
-			     void *context)
-{
-	GaimConnection *gc = client->application;
-	SilcGaim sg = gc->proto_data;
-	SilcChannelEntry channel = context;
-	GaimConversation *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,
-						   silcgaim_chat_join_done, channel);
-		return;
-	}
-
-	/* Add channel to Gaim */
-	channel->context = SILC_32_TO_PTR(++sg->channel_ids);
-	serv_got_joined_chat(gc, sg->channel_ids, channel->channel_name);
-	convo = gaim_find_conversation_with_account(GAIM_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)) {
-		GaimConvChatBuddyFlags f = GAIM_CBFLAGS_NONE;
-		if (!chu->client->nickname)
-			continue;
-		chu->context = SILC_32_TO_PTR(sg->channel_ids);
-
-		if (chu->mode & SILC_CHANNEL_UMODE_CHANFO)
-			f |= GAIM_CBFLAGS_FOUNDER;
-		if (chu->mode & SILC_CHANNEL_UMODE_CHANOP)
-			f |= GAIM_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);
-
-			gaim_conversation_write(convo, NULL, tmp,
-						GAIM_MESSAGE_SYSTEM, time(NULL));
-
-		}
-	}
-	silc_hash_table_list_reset(&htl);
-
-	gaim_conv_chat_add_users(GAIM_CONV_CHAT(convo), users, NULL, flags, FALSE);
-	g_list_free(users);
-	g_list_free(flags);
-
-	/* Set topic */
-	if (channel->topic)
-		gaim_conv_chat_set_topic(GAIM_CONV_CHAT(convo), NULL, channel->topic);
-
-	/* Set nick */
-	gaim_conv_chat_set_nick(GAIM_CONV_CHAT(convo), conn->local_entry->nickname);
-}
-
-char *silcgaim_get_chat_name(GHashTable *data)
-{
-	return g_strdup(g_hash_table_lookup(data, "channel"));
-}	
-
-void silcgaim_chat_join(GaimConnection *gc, GHashTable *data)
-{
-	SilcGaim sg = gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	const char *channel, *passphrase, *parentch;
-
-	if (!conn)
-		return;
-
-	channel = g_hash_table_lookup(data, "channel");
-	passphrase = g_hash_table_lookup(data, "passphrase");
-
-	/* Check if we are joining a private group.  Handle it
-	   purely locally as it's not a real channel */
-	if (strstr(channel, "[Private Group]")) {
-		SilcChannelEntry channel_entry;
-		SilcChannelPrivateKey key;
-		GaimChat *c;
-		SilcGaimPrvgrp grp;
-
-		c = gaim_blist_find_chat(sg->account, channel);
-		parentch = gaim_blist_node_get_string((GaimBlistNode *)c, "parentch");
-		if (!parentch)
-			return;
-
-		channel_entry = silc_client_get_channel(sg->client, sg->conn,
-							(char *)parentch);
-		if (!channel_entry ||
-		    !silc_client_on_channel(channel_entry, sg->conn->local_entry)) {
-			char tmp[512];
-			g_snprintf(tmp, sizeof(tmp),
-				   _("You have to join the %s channel before you are "
-				     "able to join the private group"), parentch);
-			gaim_notify_error(gc, _("Join Private Group"),
-					  _("Cannot join private group"), tmp);
-			return;
-		}
-
-		/* Add channel private key */
-		if (!silc_client_add_channel_private_key(client, conn,
-							 channel_entry, channel,
-							 NULL, NULL,
-							 (unsigned char *)passphrase,
-							 strlen(passphrase), &key))
-			return;
-
-		/* Join the group */
-		grp = silc_calloc(1, sizeof(*grp));
-		if (!grp)
-			return;
-		grp->id = ++sg->channel_ids + SILCGAIM_PRVGRP;
-		grp->chid = SILC_PTR_TO_32(channel_entry->context);
-		grp->parentch = parentch;
-		grp->channel = channel;
-		grp->key = key;
-		sg->grps = g_list_append(sg->grps, grp);
-		serv_got_joined_chat(gc, grp->id, channel);
-		return;
-	}
-
-	/* XXX We should have other properties here as well:
-	   1. whether to try to authenticate to the channel
-	     1a. with default key,
-	     1b. with specific key.
-	   2. whether to try to authenticate to become founder.
-	     2a. with default key,
-	     2b. with specific key.
-
-	   Since now such variety is not possible in the join dialog
-	   we always use -founder and -auth options, which try to
-	   do both 1 and 2 with default keys. */
-
-	/* Call JOIN */
-	if ((passphrase != NULL) && (*passphrase != '\0'))
-		silc_client_command_call(client, conn, NULL, "JOIN",
-					 channel, passphrase, "-auth", "-founder", NULL);
-	else
-		silc_client_command_call(client, conn, NULL, "JOIN",
-					 channel, "-auth", "-founder", NULL);
-}
-
-void silcgaim_chat_invite(GaimConnection *gc, int id, const char *msg,
-			  const char *name)
-{
-	SilcGaim sg = gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcHashTableList htl;
-	SilcChannelUser chu;
-	gboolean found = FALSE;
-
-	if (!conn)
-		return;
-
-	/* See if we are inviting on a private group.  Invite
-	   to the actual channel */
-	if (id > SILCGAIM_PRVGRP) {
-		GList *l;
-		SilcGaimPrvgrp prv;
-
-		for (l = sg->grps; l; l = l->next)
-			if (((SilcGaimPrvgrp)l->data)->id == id)
-				break;
-		if (!l)
-			return;
-		prv = l->data;
-		id = prv->chid;
-	}
-
-	/* Find channel by id */
-	silc_hash_table_list(conn->local_entry->channels, &htl);
-	while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-		if (SILC_PTR_TO_32(chu->channel->context) == id ) {
-			found = TRUE;
-			break;
-		}
-	}
-	silc_hash_table_list_reset(&htl);
-	if (!found)
-		return;
-
-	/* Call INVITE */
-	silc_client_command_call(client, conn, NULL, "INVITE",
-				 chu->channel->channel_name,
-				 name, NULL);
-}
-
-void silcgaim_chat_leave(GaimConnection *gc, int id)
-{
-	SilcGaim sg = gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcHashTableList htl;
-	SilcChannelUser chu;
-	gboolean found = FALSE;
-	GList *l;
-	SilcGaimPrvgrp prv;
-
-	if (!conn)
-		return;
-
-	/* See if we are leaving a private group */
-	if (id > SILCGAIM_PRVGRP) {
-		SilcChannelEntry channel;
-
-		for (l = sg->grps; l; l = l->next)
-			if (((SilcGaimPrvgrp)l->data)->id == id)
-				break;
-		if (!l)
-			return;
-		prv = l->data;
-		channel = silc_client_get_channel(sg->client, sg->conn,
-						  (char *)prv->parentch);
-		if (!channel)
-			return;
-		silc_client_del_channel_private_key(client, conn,
-						    channel, prv->key);
-		silc_free(prv);
-		sg->grps = g_list_remove(sg->grps, prv);
-		serv_got_chat_left(gc, id);
-		return;
-	}
-
-	/* Find channel by id */
-	silc_hash_table_list(conn->local_entry->channels, &htl);
-	while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-		if (SILC_PTR_TO_32(chu->channel->context) == id ) {
-			found = TRUE;
-			break;
-		}
-	}
-	silc_hash_table_list_reset(&htl);
-	if (!found)
-		return;
-
-	/* Call LEAVE */
-	silc_client_command_call(client, conn, NULL, "LEAVE",
-				 chu->channel->channel_name, NULL);
-
-	serv_got_chat_left(gc, id);
-
-	/* Leave from private groups on this channel as well */
-	for (l = sg->grps; l; l = l->next)
-		if (((SilcGaimPrvgrp)l->data)->chid == id) {
-			prv = l->data;
-			silc_client_del_channel_private_key(client, conn,
-							    chu->channel,
-							    prv->key);
-			serv_got_chat_left(gc, prv->id);
-			silc_free(prv);
-			sg->grps = g_list_remove(sg->grps, prv);
-			if (!sg->grps)
-				break;
-		}
-}
-
-int silcgaim_chat_send(GaimConnection *gc, int id, const char *msg, GaimMessageFlags msgflags)
-{
-	SilcGaim sg = gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcHashTableList htl;
-	SilcChannelUser chu;
-	SilcChannelEntry channel = NULL;
-	SilcChannelPrivateKey key = NULL;
-	SilcUInt32 flags;
-	int ret;
-	char *msg2, *tmp;
-	gboolean found = FALSE;
-	gboolean sign = gaim_account_get_bool(sg->account, "sign-verify", FALSE);
-
-	if (!msg || !conn)
-		return 0;
-
-	flags = SILC_MESSAGE_FLAG_UTF8;
-
-	tmp = msg2 = gaim_unescape_html(msg);
-
-	if (!g_ascii_strncasecmp(msg2, "/me ", 4))
-	{
-		msg2 += 4;
-		if (!*msg2) {
-			g_free(tmp);
-			return 0;
-		}
-		flags |= SILC_MESSAGE_FLAG_ACTION;
-	} else if (strlen(msg) > 1 && msg[0] == '/') {
-		if (!silc_client_command_call(client, conn, msg + 1))
-			gaim_notify_error(gc, _("Call Command"), _("Cannot call command"),
-							  _("Unknown command"));
-		g_free(tmp);
-		return 0;
-	}
-
-
-	if (sign)
-		flags |= SILC_MESSAGE_FLAG_SIGNED;
-
-	/* Get the channel private key if we are sending on
-	   private group */
-	if (id > SILCGAIM_PRVGRP) {
-		GList *l;
-		SilcGaimPrvgrp prv;
-
-		for (l = sg->grps; l; l = l->next)
-			if (((SilcGaimPrvgrp)l->data)->id == id)
-				break;
-		if (!l) {
-			g_free(tmp);
-			return 0;
-		}
-		prv = l->data;
-		channel = silc_client_get_channel(sg->client, sg->conn,
-						  (char *)prv->parentch);
-		if (!channel) {
-			g_free(tmp);
-			return 0;
-		}
-		key = prv->key;
-	}
-
-	if (!channel) {
-		/* Find channel by id */
-		silc_hash_table_list(conn->local_entry->channels, &htl);
-		while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-			if (SILC_PTR_TO_32(chu->channel->context) == id ) {
-				found = TRUE;
-				break;
-			}
-		}
-		silc_hash_table_list_reset(&htl);
-		if (!found) {
-			g_free(tmp);
-			return 0;
-		}
-		channel = chu->channel;
-	}
-
-	/* Send channel message */
-	ret = silc_client_send_channel_message(client, conn, channel, key,
-					       flags, (unsigned char *)msg2,
-					       strlen(msg2), TRUE);
-	if (ret) {
-		serv_got_chat_in(gc, id, gaim_connection_get_display_name(gc), 0, msg,
-				 time(NULL));
-	}
-	g_free(tmp);
-
-	return ret;
-}
-
-void silcgaim_chat_set_topic(GaimConnection *gc, int id, const char *topic)
-{
-	SilcGaim sg = gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcHashTableList htl;
-	SilcChannelUser chu;
-	gboolean found = FALSE;
-
-	if (!conn)
-		return;
-
-	/* See if setting topic on private group.  Set it
-	   on the actual channel */
-	if (id > SILCGAIM_PRVGRP) {
-		GList *l;
-		SilcGaimPrvgrp prv;
-
-		for (l = sg->grps; l; l = l->next)
-			if (((SilcGaimPrvgrp)l->data)->id == id)
-				break;
-		if (!l)
-			return;
-		prv = l->data;
-		id = prv->chid;
-	}
-
-	/* Find channel by id */
-	silc_hash_table_list(conn->local_entry->channels, &htl);
-	while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-		if (SILC_PTR_TO_32(chu->channel->context) == id ) {
-			found = TRUE;
-			break;
-		}
-	}
-	silc_hash_table_list_reset(&htl);
-	if (!found)
-		return;
-
-	/* Call TOPIC */
-	silc_client_command_call(client, conn, NULL, "TOPIC",
-				 chu->channel->channel_name, topic, NULL);
-}
-
-GaimRoomlist *silcgaim_roomlist_get_list(GaimConnection *gc)
-{
-	SilcGaim sg = gc->proto_data;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	GList *fields = NULL;
-	GaimRoomlistField *f;
-
-	if (!conn)
-		return NULL;
-
-	if (sg->roomlist)
-		gaim_roomlist_unref(sg->roomlist);
-
-	sg->roomlist_canceled = FALSE;
-
-	sg->roomlist = gaim_roomlist_new(gaim_connection_get_account(gc));
-	f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_STRING, "", "channel", TRUE);
-	fields = g_list_append(fields, f);
-	f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_INT,
-				    _("Users"), "users", FALSE);
-	fields = g_list_append(fields, f);
-	f = gaim_roomlist_field_new(GAIM_ROOMLIST_FIELD_STRING,
-				    _("Topic"), "topic", FALSE);
-	fields = g_list_append(fields, f);
-	gaim_roomlist_set_fields(sg->roomlist, fields);
-
-	/* Call LIST */
-	silc_client_command_call(client, conn, "LIST");
-
-	gaim_roomlist_set_in_progress(sg->roomlist, TRUE);
-
-	return sg->roomlist;
-}
-
-void silcgaim_roomlist_cancel(GaimRoomlist *list)
-{
-	GaimConnection *gc = gaim_account_get_connection(list->account);
-	SilcGaim sg;
-
-	if (!gc)
-		return;
-	sg = gc->proto_data;
-
-	gaim_roomlist_set_in_progress(list, FALSE);
-	if (sg->roomlist == list) {
-		gaim_roomlist_unref(sg->roomlist);
-		sg->roomlist = NULL;
-		sg->roomlist_canceled = TRUE;
-	}
-}

mercurial