2 silc-channels.c : irssi
4 Copyright (C) 2000 - 2001 Timo Sirainen
5 Pekka Riikonen <priikone@poseidon.pspt.fi>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "net-nonblock.h"
25 #include "net-sendbuffer.h"
35 #include "channels-setup.h"
37 #include "silc-servers.h"
38 #include "silc-channels.h"
39 #include "silc-queries.h"
40 #include "silc-nicklist.h"
41 #include "window-item-def.h"
43 #include "fe-common/core/printtext.h"
44 #include "fe-common/silc/module-formats.h"
46 #include "silc-commands.h"
48 SILC_CHANNEL_REC *silc_channel_create(SILC_SERVER_REC *server,
49 const char *name, int automatic)
51 SILC_CHANNEL_REC *rec;
53 g_return_val_if_fail(server == NULL || IS_SILC_SERVER(server), NULL);
54 g_return_val_if_fail(name != NULL, NULL);
56 rec = g_new0(SILC_CHANNEL_REC, 1);
57 rec->chat_type = SILC_PROTOCOL;
58 rec->name = g_strdup(name);
61 channel_init((CHANNEL_REC *) rec, automatic);
65 static void sig_channel_destroyed(SILC_CHANNEL_REC *channel)
67 if (!IS_SILC_CHANNEL(channel))
69 if (channel->server && channel->server->disconnected)
72 if (channel->server != NULL && !channel->left && !channel->kicked) {
73 /* destroying channel record without actually
74 having left the channel yet */
75 silc_command_exec(channel->server, "LEAVE", channel->name);
79 static void silc_channels_join(SILC_SERVER_REC *server,
80 const char *channels, int automatic)
83 SILC_CHANNEL_REC *chanrec;
85 list = g_strsplit(channels, ",", -1);
86 for (tmp = list; *tmp != NULL; tmp++) {
87 chanrec = silc_channel_find(server, *tmp);
91 silc_command_exec(server, "JOIN", *tmp);
97 static void sig_connected(SILC_SERVER_REC *server)
99 if (IS_SILC_SERVER(server))
100 server->channels_join = (void *) silc_channels_join;
103 /* "server quit" signal from the core to indicate that QUIT command
106 static void sig_server_quit(SILC_SERVER_REC *server, const char *msg)
108 if (IS_SILC_SERVER(server) && server->conn && server->conn->sock)
109 silc_command_exec(server, "QUIT", msg);
112 /* Find Irssi channel entry by SILC channel entry */
114 SILC_CHANNEL_REC *silc_channel_find_entry(SILC_SERVER_REC *server,
115 SilcChannelEntry entry)
119 g_return_val_if_fail(IS_SILC_SERVER(server), NULL);
121 for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
122 SILC_CHANNEL_REC *rec = tmp->data;
124 if (rec->entry == entry)
131 /* PART (LEAVE) command. */
133 static void command_part(const char *data, SILC_SERVER_REC *server,
136 SILC_CHANNEL_REC *chanrec;
139 CMD_SILC_SERVER(server);
141 if (!IS_SILC_SERVER(server) || !server->connected)
142 cmd_return_error(CMDERR_NOT_CONNECTED);
144 if (!strcmp(data, "*") || *data == '\0') {
145 if (!IS_SILC_CHANNEL(item))
146 cmd_return_error(CMDERR_NOT_JOINED);
150 chanrec = silc_channel_find(server, data);
152 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
154 memset(userhost, 0, sizeof(userhost));
155 snprintf(userhost, sizeof(userhost) - 1, "%s@%s",
156 server->conn->local_entry->username,
157 server->conn->local_entry->hostname);
158 signal_emit("message part", 5, server, chanrec->name,
159 server->nick, userhost, "");
161 chanrec->left = TRUE;
162 silc_command_exec(server, "LEAVE", chanrec->name);
165 channel_destroy(CHANNEL(chanrec));
168 /* ME local command. */
170 static void command_me(const char *data, SILC_SERVER_REC *server,
173 SILC_CHANNEL_REC *chanrec;
174 char *tmpcmd = "ME", *tmp;
176 unsigned char **argv;
177 SilcUInt32 *argv_lens, *argv_types;
180 CMD_SILC_SERVER(server);
182 if (!IS_SILC_SERVER(server) || !server->connected)
183 cmd_return_error(CMDERR_NOT_CONNECTED);
185 if (!IS_SILC_CHANNEL(item))
186 cmd_return_error(CMDERR_NOT_JOINED);
188 /* Now parse all arguments */
189 tmp = g_strconcat(tmpcmd, " ", data, NULL);
190 silc_parse_command_line(tmp, &argv, &argv_lens,
191 &argv_types, &argc, 2);
195 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
197 chanrec = silc_channel_find(server, item->name);
199 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
201 /* Send the action message */
202 silc_client_send_channel_message(silc_client, server->conn,
203 chanrec->entry, NULL,
204 SILC_MESSAGE_FLAG_ACTION,
205 argv[1], argv_lens[1], TRUE);
207 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
208 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION,
209 server->conn->local_entry->nickname, argv[1]);
211 for (i = 0; i < argc; i++)
213 silc_free(argv_lens);
214 silc_free(argv_types);
217 /* ACTION local command. Same as ME but takes the channel as mandatory
220 static void command_action(const char *data, SILC_SERVER_REC *server,
223 SILC_CHANNEL_REC *chanrec;
224 char *tmpcmd = "ME", *tmp;
226 unsigned char **argv;
227 SilcUInt32 *argv_lens, *argv_types;
230 CMD_SILC_SERVER(server);
231 if (!IS_SILC_SERVER(server) || !server->connected)
232 cmd_return_error(CMDERR_NOT_CONNECTED);
234 if (!IS_SILC_CHANNEL(item))
235 cmd_return_error(CMDERR_NOT_JOINED);
237 /* Now parse all arguments */
238 tmp = g_strconcat(tmpcmd, " ", data, NULL);
239 silc_parse_command_line(tmp, &argv, &argv_lens,
240 &argv_types, &argc, 3);
244 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
246 chanrec = silc_channel_find(server, argv[1]);
248 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
250 /* Send the action message */
251 silc_client_send_channel_message(silc_client, server->conn,
252 chanrec->entry, NULL,
253 SILC_MESSAGE_FLAG_ACTION,
254 argv[2], argv_lens[2], TRUE);
256 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
257 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION,
258 server->conn->local_entry->nickname, argv[2]);
260 for (i = 0; i < argc; i++)
262 silc_free(argv_lens);
263 silc_free(argv_types);
266 /* NOTICE local command. */
268 static void command_notice(const char *data, SILC_SERVER_REC *server,
271 SILC_CHANNEL_REC *chanrec;
272 char *tmpcmd = "ME", *tmp;
274 unsigned char **argv;
275 SilcUInt32 *argv_lens, *argv_types;
278 CMD_SILC_SERVER(server);
279 if (!IS_SILC_SERVER(server) || !server->connected)
280 cmd_return_error(CMDERR_NOT_CONNECTED);
282 if (!IS_SILC_CHANNEL(item))
283 cmd_return_error(CMDERR_NOT_JOINED);
285 /* Now parse all arguments */
286 tmp = g_strconcat(tmpcmd, " ", data, NULL);
287 silc_parse_command_line(tmp, &argv, &argv_lens,
288 &argv_types, &argc, 2);
292 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
294 chanrec = silc_channel_find(server, item->name);
296 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
298 /* Send the action message */
299 silc_client_send_channel_message(silc_client, server->conn,
300 chanrec->entry, NULL,
301 SILC_MESSAGE_FLAG_NOTICE,
302 argv[1], argv_lens[1], TRUE);
304 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
305 MSGLEVEL_NOTICES, SILCTXT_CHANNEL_OWNNOTICE,
306 server->conn->local_entry->nickname, argv[1]);
308 for (i = 0; i < argc; i++)
310 silc_free(argv_lens);
311 silc_free(argv_types);
314 /* AWAY local command. Sends UMODE command that sets the SILC_UMODE_GONE
317 static void command_away(const char *data, SILC_SERVER_REC *server,
322 CMD_SILC_SERVER(server);
324 if (!IS_SILC_SERVER(server) || !server->connected)
325 cmd_return_error(CMDERR_NOT_CONNECTED);
328 /* Remove any possible away message */
329 silc_client_set_away_message(silc_client, server->conn, NULL);
332 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
335 /* Set the away message */
336 silc_client_set_away_message(silc_client, server->conn, (char *)data);
339 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
340 SILCTXT_SET_AWAY, data);
343 signal_emit("away mode changed", 1, server);
345 silc_command_exec(server, "UMODE", set ? "+g" : "-g");
349 int type; /* 1 = msg, 2 = channel */
351 SILC_SERVER_REC *server;
354 /* Key agreement callback that is called after the key agreement protocol
355 has been performed. This is called also if error occured during the
356 key agreement protocol. The `key' is the allocated key material and
357 the caller is responsible of freeing it. The `key' is NULL if error
358 has occured. The application can freely use the `key' to whatever
359 purpose it needs. See lib/silcske/silcske.h for the definition of
360 the SilcSKEKeyMaterial structure. */
362 static void keyagr_completion(SilcClient client,
363 SilcClientConnection conn,
364 SilcClientEntry client_entry,
365 SilcKeyAgreementStatus status,
366 SilcSKEKeyMaterial *key,
369 KeyInternal i = (KeyInternal)context;
372 case SILC_KEY_AGREEMENT_OK:
373 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
374 SILCTXT_KEY_AGREEMENT_OK, client_entry->nickname);
377 /* Set the private key for this client */
378 silc_client_del_private_message_key(client, conn, client_entry);
379 silc_client_add_private_message_key_ske(client, conn, client_entry,
380 NULL, key, i->responder);
381 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
382 SILCTXT_KEY_AGREEMENT_PRIVMSG,
383 client_entry->nickname);
384 silc_ske_free_key_material(key);
389 case SILC_KEY_AGREEMENT_ERROR:
390 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
391 SILCTXT_KEY_AGREEMENT_ERROR, client_entry->nickname);
394 case SILC_KEY_AGREEMENT_FAILURE:
395 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
396 SILCTXT_KEY_AGREEMENT_FAILURE, client_entry->nickname);
399 case SILC_KEY_AGREEMENT_TIMEOUT:
400 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
401 SILCTXT_KEY_AGREEMENT_TIMEOUT, client_entry->nickname);
404 case SILC_KEY_AGREEMENT_ABORTED:
405 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
406 SILCTXT_KEY_AGREEMENT_ABORTED, client_entry->nickname);
409 case SILC_KEY_AGREEMENT_ALREADY_STARTED:
410 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
411 SILCTXT_KEY_AGREEMENT_ALREADY_STARTED,
412 client_entry->nickname);
415 case SILC_KEY_AGREEMENT_SELF_DENIED:
416 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
417 SILCTXT_KEY_AGREEMENT_SELF_DENIED);
428 /* Local command KEY. This command is used to set and unset private
429 keys for channels, set and unset private keys for private messages
430 with remote clients and to send key agreement requests and
431 negotiate the key agreement protocol with remote client. The
432 key agreement is supported only to negotiate private message keys,
433 it currently cannot be used to negotiate private keys for channels,
434 as it is not convenient for that purpose. */
437 SILC_SERVER_REC *server;
443 /* Callback to be called after client information is resolved from the
446 static void silc_client_command_key_get_clients(SilcClient client,
447 SilcClientConnection conn,
448 SilcClientEntry *clients,
449 SilcUInt32 clients_count,
452 KeyGetClients internal = (KeyGetClients)context;
455 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown nick: %s",
457 silc_free(internal->data);
458 silc_free(internal->nick);
463 signal_emit("command key", 3, internal->data, internal->server,
466 silc_free(internal->data);
467 silc_free(internal->nick);
471 static void command_key(const char *data, SILC_SERVER_REC *server,
474 SilcClientConnection conn;
475 SilcClientEntry *entrys, client_entry = NULL;
476 SilcUInt32 entry_count;
477 SILC_CHANNEL_REC *chanrec = NULL;
478 SilcChannelEntry channel_entry = NULL;
479 char *nickname = NULL, *tmp;
480 int command = 0, port = 0, type = 0;
481 char *hostname = NULL;
482 KeyInternal internal = NULL;
484 unsigned char **argv;
485 SilcUInt32 *argv_lens, *argv_types;
486 char *bindhost = NULL;
488 CMD_SILC_SERVER(server);
490 if (!server || !IS_SILC_SERVER(server) || !server->connected)
491 cmd_return_error(CMDERR_NOT_CONNECTED);
495 /* Now parse all arguments */
496 tmp = g_strconcat("KEY", " ", data, NULL);
497 silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 7);
501 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
504 if (!strcasecmp(argv[1], "msg"))
506 if (!strcasecmp(argv[1], "channel"))
510 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
513 if (argv[2][0] == '*') {
514 nickname = strdup("*");
516 /* Parse the typed nickname. */
517 if (!silc_parse_userfqdn(argv[2], &nickname, NULL)) {
518 printformat_module("fe-common/silc", server, NULL,
519 MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
523 /* Find client entry */
524 entrys = silc_client_get_clients_local(silc_client, conn, nickname,
525 argv[2], &entry_count);
527 KeyGetClients inter = silc_calloc(1, sizeof(*inter));
528 inter->server = server;
529 inter->data = strdup(data);
530 inter->nick = strdup(nickname);
532 silc_client_get_clients(silc_client, conn, nickname, argv[2],
533 silc_client_command_key_get_clients, inter);
536 client_entry = entrys[0];
542 /* Get channel entry */
545 if (argv[2][0] == '*') {
546 if (!conn->current_channel) {
548 cmd_return_error(CMDERR_NOT_JOINED);
550 name = conn->current_channel->channel_name;
555 chanrec = silc_channel_find(server, name);
556 if (chanrec == NULL) {
558 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
560 channel_entry = chanrec->entry;
564 if (!strcasecmp(argv[3], "set")) {
568 if (type == 1 && client_entry) {
569 /* Set private message key */
571 silc_client_del_private_message_key(silc_client, conn, client_entry);
574 silc_client_add_private_message_key(silc_client, conn, client_entry,
578 TRUE : FALSE), FALSE);
580 silc_client_add_private_message_key(silc_client, conn, client_entry,
584 TRUE : FALSE), FALSE);
586 /* Send the key to the remote client so that it starts using it
588 silc_client_send_private_message_key(silc_client, conn,
590 } else if (type == 2) {
591 /* Set private channel key */
592 char *cipher = NULL, *hmac = NULL;
594 if (!(channel_entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
595 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
596 SILCTXT_CH_PRIVATE_KEY_NOMODE,
597 channel_entry->channel_name);
606 if (!silc_client_add_channel_private_key(silc_client, conn,
611 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
612 SILCTXT_CH_PRIVATE_KEY_ERROR,
613 channel_entry->channel_name);
617 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
618 SILCTXT_CH_PRIVATE_KEY_ADD,
619 channel_entry->channel_name);
627 if (!strcasecmp(argv[3], "unset")) {
630 if (type == 1 && client_entry) {
631 /* Unset private message key */
632 silc_client_del_private_message_key(silc_client, conn, client_entry);
633 } else if (type == 2) {
634 /* Unset channel key(s) */
635 SilcChannelPrivateKey *keys;
636 SilcUInt32 keys_count;
640 silc_client_del_channel_private_keys(silc_client, conn,
644 number = atoi(argv[4]);
645 keys = silc_client_list_channel_private_keys(silc_client, conn,
651 if (!number || number > keys_count) {
652 silc_client_free_channel_private_keys(keys, keys_count);
656 silc_client_del_channel_private_key(silc_client, conn, channel_entry,
658 silc_client_free_channel_private_keys(keys, keys_count);
666 if (!strcasecmp(argv[3], "list")) {
670 SilcPrivateMessageKeys keys;
671 SilcUInt32 keys_count;
675 keys = silc_client_list_private_message_keys(silc_client, conn,
680 /* list the private message key(s) */
681 if (nickname[0] == '*') {
682 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
683 SILCTXT_PRIVATE_KEY_LIST);
684 for (k = 0; k < keys_count; k++) {
685 memset(buf, 0, sizeof(buf));
686 strncat(buf, " ", 2);
687 len = strlen(keys[k].client_entry->nickname);
688 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
690 for (i = 0; i < 30 - len; i++)
694 len = strlen(keys[k].cipher);
695 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
697 for (i = 0; i < 14 - len; i++)
702 strcat(buf, "<hidden>");
704 strcat(buf, "*generated*");
706 silc_say(silc_client, conn, SILC_CLIENT_MESSAGE_INFO, "%s", buf);
709 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
710 SILCTXT_PRIVATE_KEY_LIST_NICK,
711 client_entry->nickname);
712 for (k = 0; k < keys_count; k++) {
713 if (keys[k].client_entry != client_entry)
716 memset(buf, 0, sizeof(buf));
717 strncat(buf, " ", 2);
718 len = strlen(keys[k].client_entry->nickname);
719 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
721 for (i = 0; i < 30 - len; i++)
725 len = strlen(keys[k].cipher);
726 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
728 for (i = 0; i < 14 - len; i++)
733 strcat(buf, "<hidden>");
735 strcat(buf, "*generated*");
737 silc_say(silc_client, conn, SILC_CLIENT_MESSAGE_INFO, "%s", buf);
741 silc_client_free_private_message_keys(keys, keys_count);
743 } else if (type == 2) {
744 SilcChannelPrivateKey *keys;
745 SilcUInt32 keys_count;
749 keys = silc_client_list_channel_private_keys(silc_client, conn,
753 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
754 SILCTXT_CH_PRIVATE_KEY_LIST,
755 channel_entry->channel_name);
760 for (k = 0; k < keys_count; k++) {
761 memset(buf, 0, sizeof(buf));
762 strncat(buf, " ", 2);
764 len = strlen(keys[k]->cipher->cipher->name);
765 strncat(buf, keys[k]->cipher->cipher->name, len > 16 ? 16 : len);
767 for (i = 0; i < 16 - len; i++)
771 len = strlen(silc_hmac_get_name(keys[k]->hmac));
772 strncat(buf, silc_hmac_get_name(keys[k]->hmac), len > 16 ? 16 : len);
774 for (i = 0; i < 16 - len; i++)
778 strcat(buf, "<hidden>");
780 silc_say(silc_client, conn, SILC_CLIENT_MESSAGE_INFO, "%s", buf);
783 silc_client_free_channel_private_keys(keys, keys_count);
789 /* Send command is used to send key agreement */
790 if (!strcasecmp(argv[3], "agreement")) {
796 port = atoi(argv[5]);
798 internal = silc_calloc(1, sizeof(*internal));
799 internal->type = type;
800 internal->server = server;
803 if (settings_get_bool("use_auto_addr")) {
805 hostname = (char *)settings_get_str("auto_public_ip");
807 /* If the hostname isn't set, treat this case as if auto_public_ip
809 if ((hostname) && (*hostname == '\0')) {
812 bindhost = (char *)settings_get_str("auto_bind_ip");
814 /* if the bind_ip isn't set, but the public_ip IS, then assume then
815 public_ip is the same value as the bind_ip. */
816 if ((bindhost) && (*bindhost == '\0'))
818 port = settings_get_int("auto_bind_port");
820 } /* if use_auto_addr */
824 /* Start command is used to start key agreement (after receiving the
825 key_agreement client operation). */
826 if (!strcasecmp(argv[3], "negotiate")) {
832 port = atoi(argv[5]);
834 internal = silc_calloc(1, sizeof(*internal));
835 internal->type = type;
836 internal->server = server;
839 /* Change current channel private key */
840 if (!strcasecmp(argv[3], "change")) {
843 /* Unset channel key(s) */
844 SilcChannelPrivateKey *keys;
845 SilcUInt32 keys_count;
848 keys = silc_client_list_channel_private_keys(silc_client, conn,
856 if (chanrec->cur_key >= keys_count)
857 chanrec->cur_key = 0;
861 number = atoi(argv[4]);
862 if (!number || number > keys_count)
863 chanrec->cur_key = 0;
865 chanrec->cur_key = number - 1;
868 /* Set the current channel private key */
869 silc_client_current_channel_private_key(silc_client, conn,
871 keys[chanrec->cur_key]);
872 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
873 SILCTXT_CH_PRIVATE_KEY_CHANGE, chanrec->cur_key + 1,
874 channel_entry->channel_name);
876 silc_client_free_channel_private_keys(keys, keys_count);
882 silc_say(silc_client, conn, SILC_CLIENT_MESSAGE_INFO,
883 "Usage: /KEY msg|channel <nickname|channel> "
884 "set|unset|agreement|negotiate [<arguments>]");
888 if (command == 4 && client_entry) {
889 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
890 SILCTXT_KEY_AGREEMENT, argv[2]);
891 internal->responder = TRUE;
892 silc_client_send_key_agreement(
893 silc_client, conn, client_entry, hostname,
895 settings_get_int("key_exchange_timeout_secs"),
896 keyagr_completion, internal);
902 if (command == 5 && client_entry && hostname) {
903 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
904 SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
905 internal->responder = FALSE;
906 silc_client_perform_key_agreement(silc_client, conn, client_entry,
907 hostname, port, keyagr_completion,
916 /* Lists locally saved client and server public keys. */
918 static void command_listkeys(const char *data, SILC_SERVER_REC *server,
924 void silc_channels_init(void)
926 signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
927 signal_add("server connected", (SIGNAL_FUNC) sig_connected);
928 signal_add("server quit", (SIGNAL_FUNC) sig_server_quit);
930 command_bind_silc("part", MODULE_NAME, (SIGNAL_FUNC) command_part);
931 command_bind_silc("me", MODULE_NAME, (SIGNAL_FUNC) command_me);
932 command_bind_silc("action", MODULE_NAME, (SIGNAL_FUNC) command_action);
933 command_bind_silc("notice", MODULE_NAME, (SIGNAL_FUNC) command_notice);
934 command_bind_silc("away", MODULE_NAME, (SIGNAL_FUNC) command_away);
935 command_bind_silc("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
936 command_bind_silc("listkeys", MODULE_NAME, (SIGNAL_FUNC) command_listkeys);
938 silc_nicklist_init();
941 void silc_channels_deinit(void)
943 signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
944 signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
945 signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit);
947 command_unbind("part", (SIGNAL_FUNC) command_part);
948 command_unbind("me", (SIGNAL_FUNC) command_me);
949 command_unbind("action", (SIGNAL_FUNC) command_action);
950 command_unbind("notice", (SIGNAL_FUNC) command_notice);
951 command_unbind("away", (SIGNAL_FUNC) command_away);
952 command_unbind("key", (SIGNAL_FUNC) command_key);
953 command_unbind("listkeys", (SIGNAL_FUNC) command_listkeys);
955 silc_nicklist_deinit();