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 *message = NULL;
177 unsigned char **argv;
178 SilcUInt32 *argv_lens, *argv_types;
181 CMD_SILC_SERVER(server);
183 if (!IS_SILC_SERVER(server) || !server->connected)
184 cmd_return_error(CMDERR_NOT_CONNECTED);
186 if (!IS_SILC_CHANNEL(item))
187 cmd_return_error(CMDERR_NOT_JOINED);
189 /* Now parse all arguments */
190 tmp = g_strconcat(tmpcmd, " ", data, NULL);
191 silc_parse_command_line(tmp, &argv, &argv_lens,
192 &argv_types, &argc, 2);
196 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
198 chanrec = silc_channel_find(server, item->name);
200 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
202 if (!silc_term_utf8()) {
203 int len = silc_utf8_encoded_len(argv[1], argv_lens[1],
204 SILC_STRING_LANGUAGE);
205 message = silc_calloc(len + 1, sizeof(*message));
206 g_return_if_fail(message != NULL);
207 silc_utf8_encode(argv[1], argv_lens[1], SILC_STRING_LANGUAGE,
211 /* Send the action message */
212 silc_client_send_channel_message(silc_client, server->conn,
213 chanrec->entry, NULL,
214 SILC_MESSAGE_FLAG_ACTION |
215 SILC_MESSAGE_FLAG_UTF8,
216 message ? message : argv[1],
217 message ? strlen(message) : argv_lens[1],
220 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
221 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION,
222 server->conn->local_entry->nickname, argv[1]);
224 for (i = 0; i < argc; i++)
226 silc_free(argv_lens);
227 silc_free(argv_types);
231 /* ACTION local command. Same as ME but takes the channel as mandatory
234 static void command_action(const char *data, SILC_SERVER_REC *server,
237 SILC_CHANNEL_REC *chanrec;
238 char *tmpcmd = "ME", *tmp;
240 unsigned char *message = NULL;
241 unsigned char **argv;
242 SilcUInt32 *argv_lens, *argv_types;
245 CMD_SILC_SERVER(server);
246 if (!IS_SILC_SERVER(server) || !server->connected)
247 cmd_return_error(CMDERR_NOT_CONNECTED);
249 if (!IS_SILC_CHANNEL(item))
250 cmd_return_error(CMDERR_NOT_JOINED);
252 /* Now parse all arguments */
253 tmp = g_strconcat(tmpcmd, " ", data, NULL);
254 silc_parse_command_line(tmp, &argv, &argv_lens,
255 &argv_types, &argc, 3);
259 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
261 chanrec = silc_channel_find(server, argv[1]);
263 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
265 if (!silc_term_utf8()) {
266 int len = silc_utf8_encoded_len(argv[2], argv_lens[2],
267 SILC_STRING_LANGUAGE);
268 message = silc_calloc(len + 1, sizeof(*message));
269 g_return_if_fail(message != NULL);
270 silc_utf8_encode(argv[2], argv_lens[2], SILC_STRING_LANGUAGE,
274 /* Send the action message */
275 silc_client_send_channel_message(silc_client, server->conn,
276 chanrec->entry, NULL,
277 SILC_MESSAGE_FLAG_ACTION |
278 SILC_MESSAGE_FLAG_UTF8,
279 message ? message : argv[2],
280 message ? strlen(message) : argv_lens[2],
283 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
284 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION,
285 server->conn->local_entry->nickname, argv[2]);
287 for (i = 0; i < argc; i++)
289 silc_free(argv_lens);
290 silc_free(argv_types);
294 /* NOTICE local command. */
296 static void command_notice(const char *data, SILC_SERVER_REC *server,
299 SILC_CHANNEL_REC *chanrec;
300 char *tmpcmd = "ME", *tmp;
302 unsigned char *message = NULL;
303 unsigned char **argv;
304 SilcUInt32 *argv_lens, *argv_types;
307 CMD_SILC_SERVER(server);
308 if (!IS_SILC_SERVER(server) || !server->connected)
309 cmd_return_error(CMDERR_NOT_CONNECTED);
311 if (!IS_SILC_CHANNEL(item))
312 cmd_return_error(CMDERR_NOT_JOINED);
314 /* Now parse all arguments */
315 tmp = g_strconcat(tmpcmd, " ", data, NULL);
316 silc_parse_command_line(tmp, &argv, &argv_lens,
317 &argv_types, &argc, 2);
321 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
323 chanrec = silc_channel_find(server, item->name);
325 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
327 if (!silc_term_utf8()) {
328 int len = silc_utf8_encoded_len(argv[1], argv_lens[1],
329 SILC_STRING_LANGUAGE);
330 message = silc_calloc(len + 1, sizeof(*message));
331 g_return_if_fail(message != NULL);
332 silc_utf8_encode(argv[1], argv_lens[1], SILC_STRING_LANGUAGE,
336 /* Send the action message */
337 silc_client_send_channel_message(silc_client, server->conn,
338 chanrec->entry, NULL,
339 SILC_MESSAGE_FLAG_NOTICE |
340 SILC_MESSAGE_FLAG_UTF8,
341 message ? message : argv[1],
342 message ? strlen(message) : argv_lens[1],
345 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
346 MSGLEVEL_NOTICES, SILCTXT_CHANNEL_OWNNOTICE,
347 server->conn->local_entry->nickname, argv[1]);
349 for (i = 0; i < argc; i++)
351 silc_free(argv_lens);
352 silc_free(argv_types);
356 /* AWAY local command. Sends UMODE command that sets the SILC_UMODE_GONE
359 static void command_away(const char *data, SILC_SERVER_REC *server,
364 CMD_SILC_SERVER(server);
366 if (!IS_SILC_SERVER(server) || !server->connected)
367 cmd_return_error(CMDERR_NOT_CONNECTED);
370 /* Remove any possible away message */
371 silc_client_set_away_message(silc_client, server->conn, NULL);
374 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
377 /* Set the away message */
378 silc_client_set_away_message(silc_client, server->conn, (char *)data);
381 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
382 SILCTXT_SET_AWAY, data);
385 server->usermode_away = set;
387 server->away_reason = g_strdup((char *)data);
388 signal_emit("away mode changed", 1, server);
390 silc_command_exec(server, "UMODE", set ? "+g" : "-g");
394 int type; /* 1 = msg, 2 = channel */
396 SILC_SERVER_REC *server;
399 /* Key agreement callback that is called after the key agreement protocol
400 has been performed. This is called also if error occured during the
401 key agreement protocol. The `key' is the allocated key material and
402 the caller is responsible of freeing it. The `key' is NULL if error
403 has occured. The application can freely use the `key' to whatever
404 purpose it needs. See lib/silcske/silcske.h for the definition of
405 the SilcSKEKeyMaterial structure. */
407 static void keyagr_completion(SilcClient client,
408 SilcClientConnection conn,
409 SilcClientEntry client_entry,
410 SilcKeyAgreementStatus status,
411 SilcSKEKeyMaterial *key,
414 KeyInternal i = (KeyInternal)context;
417 case SILC_KEY_AGREEMENT_OK:
418 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
419 SILCTXT_KEY_AGREEMENT_OK, client_entry->nickname);
422 /* Set the private key for this client */
423 silc_client_del_private_message_key(client, conn, client_entry);
424 silc_client_add_private_message_key_ske(client, conn, client_entry,
425 NULL, key, i->responder);
426 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
427 SILCTXT_KEY_AGREEMENT_PRIVMSG,
428 client_entry->nickname);
429 silc_ske_free_key_material(key);
434 case SILC_KEY_AGREEMENT_ERROR:
435 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
436 SILCTXT_KEY_AGREEMENT_ERROR, client_entry->nickname);
439 case SILC_KEY_AGREEMENT_FAILURE:
440 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
441 SILCTXT_KEY_AGREEMENT_FAILURE, client_entry->nickname);
444 case SILC_KEY_AGREEMENT_TIMEOUT:
445 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
446 SILCTXT_KEY_AGREEMENT_TIMEOUT, client_entry->nickname);
449 case SILC_KEY_AGREEMENT_ABORTED:
450 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
451 SILCTXT_KEY_AGREEMENT_ABORTED, client_entry->nickname);
454 case SILC_KEY_AGREEMENT_ALREADY_STARTED:
455 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
456 SILCTXT_KEY_AGREEMENT_ALREADY_STARTED,
457 client_entry->nickname);
460 case SILC_KEY_AGREEMENT_SELF_DENIED:
461 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
462 SILCTXT_KEY_AGREEMENT_SELF_DENIED);
473 /* Local command KEY. This command is used to set and unset private
474 keys for channels, set and unset private keys for private messages
475 with remote clients and to send key agreement requests and
476 negotiate the key agreement protocol with remote client. The
477 key agreement is supported only to negotiate private message keys,
478 it currently cannot be used to negotiate private keys for channels,
479 as it is not convenient for that purpose. */
482 SILC_SERVER_REC *server;
488 /* Callback to be called after client information is resolved from the
491 static void silc_client_command_key_get_clients(SilcClient client,
492 SilcClientConnection conn,
493 SilcClientEntry *clients,
494 SilcUInt32 clients_count,
497 KeyGetClients internal = (KeyGetClients)context;
500 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown nick: %s",
502 silc_free(internal->data);
503 silc_free(internal->nick);
508 signal_emit("command key", 3, internal->data, internal->server,
511 silc_free(internal->data);
512 silc_free(internal->nick);
516 static void command_key(const char *data, SILC_SERVER_REC *server,
519 SilcClientConnection conn;
520 SilcClientEntry *entrys, client_entry = NULL;
521 SilcUInt32 entry_count;
522 SILC_CHANNEL_REC *chanrec = NULL;
523 SilcChannelEntry channel_entry = NULL;
524 char *nickname = NULL, *tmp;
525 int command = 0, port = 0, type = 0;
526 char *hostname = NULL;
527 KeyInternal internal = NULL;
529 unsigned char **argv;
530 SilcUInt32 *argv_lens, *argv_types;
531 char *bindhost = NULL;
533 CMD_SILC_SERVER(server);
535 if (!server || !IS_SILC_SERVER(server) || !server->connected)
536 cmd_return_error(CMDERR_NOT_CONNECTED);
540 /* Now parse all arguments */
541 tmp = g_strconcat("KEY", " ", data, NULL);
542 silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 7);
546 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
549 if (!strcasecmp(argv[1], "msg"))
551 if (!strcasecmp(argv[1], "channel"))
555 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
558 if (argv[2][0] == '*') {
559 nickname = strdup("*");
561 /* Parse the typed nickname. */
562 if (!silc_parse_userfqdn(argv[2], &nickname, NULL)) {
563 printformat_module("fe-common/silc", server, NULL,
564 MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
568 /* Find client entry */
569 entrys = silc_client_get_clients_local(silc_client, conn, nickname,
570 argv[2], &entry_count);
572 KeyGetClients inter = silc_calloc(1, sizeof(*inter));
573 inter->server = server;
574 inter->data = strdup(data);
575 inter->nick = strdup(nickname);
577 silc_client_get_clients(silc_client, conn, nickname, argv[2],
578 silc_client_command_key_get_clients, inter);
581 client_entry = entrys[0];
587 /* Get channel entry */
590 if (argv[2][0] == '*') {
591 if (!conn->current_channel) {
593 cmd_return_error(CMDERR_NOT_JOINED);
595 name = conn->current_channel->channel_name;
600 chanrec = silc_channel_find(server, name);
601 if (chanrec == NULL) {
603 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
605 channel_entry = chanrec->entry;
609 if (!strcasecmp(argv[3], "set")) {
613 if (type == 1 && client_entry) {
614 /* Set private message key */
616 silc_client_del_private_message_key(silc_client, conn, client_entry);
619 silc_client_add_private_message_key(silc_client, conn, client_entry,
623 TRUE : FALSE), FALSE);
625 silc_client_add_private_message_key(silc_client, conn, client_entry,
629 TRUE : FALSE), FALSE);
631 /* Send the key to the remote client so that it starts using it
633 silc_client_send_private_message_key(silc_client, conn,
635 } else if (type == 2) {
636 /* Set private channel key */
637 char *cipher = NULL, *hmac = NULL;
639 if (!(channel_entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
640 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
641 SILCTXT_CH_PRIVATE_KEY_NOMODE,
642 channel_entry->channel_name);
651 if (!silc_client_add_channel_private_key(silc_client, conn,
656 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
657 SILCTXT_CH_PRIVATE_KEY_ERROR,
658 channel_entry->channel_name);
662 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
663 SILCTXT_CH_PRIVATE_KEY_ADD,
664 channel_entry->channel_name);
672 if (!strcasecmp(argv[3], "unset")) {
675 if (type == 1 && client_entry) {
676 /* Unset private message key */
677 silc_client_del_private_message_key(silc_client, conn, client_entry);
678 } else if (type == 2) {
679 /* Unset channel key(s) */
680 SilcChannelPrivateKey *keys;
681 SilcUInt32 keys_count;
685 silc_client_del_channel_private_keys(silc_client, conn,
689 number = atoi(argv[4]);
690 keys = silc_client_list_channel_private_keys(silc_client, conn,
696 if (!number || number > keys_count) {
697 silc_client_free_channel_private_keys(keys, keys_count);
701 silc_client_del_channel_private_key(silc_client, conn, channel_entry,
703 silc_client_free_channel_private_keys(keys, keys_count);
711 if (!strcasecmp(argv[3], "list")) {
715 SilcPrivateMessageKeys keys;
716 SilcUInt32 keys_count;
720 keys = silc_client_list_private_message_keys(silc_client, conn,
725 /* list the private message key(s) */
726 if (nickname[0] == '*') {
727 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
728 SILCTXT_PRIVATE_KEY_LIST);
729 for (k = 0; k < keys_count; k++) {
730 memset(buf, 0, sizeof(buf));
731 strncat(buf, " ", 2);
732 len = strlen(keys[k].client_entry->nickname);
733 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
735 for (i = 0; i < 30 - len; i++)
739 len = strlen(keys[k].cipher);
740 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
742 for (i = 0; i < 14 - len; i++)
747 strcat(buf, "<hidden>");
749 strcat(buf, "*generated*");
751 silc_say(silc_client, conn, SILC_CLIENT_MESSAGE_INFO, "%s", buf);
754 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
755 SILCTXT_PRIVATE_KEY_LIST_NICK,
756 client_entry->nickname);
757 for (k = 0; k < keys_count; k++) {
758 if (keys[k].client_entry != client_entry)
761 memset(buf, 0, sizeof(buf));
762 strncat(buf, " ", 2);
763 len = strlen(keys[k].client_entry->nickname);
764 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
766 for (i = 0; i < 30 - len; i++)
770 len = strlen(keys[k].cipher);
771 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
773 for (i = 0; i < 14 - len; i++)
778 strcat(buf, "<hidden>");
780 strcat(buf, "*generated*");
782 silc_say(silc_client, conn, SILC_CLIENT_MESSAGE_INFO, "%s", buf);
786 silc_client_free_private_message_keys(keys, keys_count);
788 } else if (type == 2) {
789 SilcChannelPrivateKey *keys;
790 SilcUInt32 keys_count;
794 keys = silc_client_list_channel_private_keys(silc_client, conn,
798 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
799 SILCTXT_CH_PRIVATE_KEY_LIST,
800 channel_entry->channel_name);
805 for (k = 0; k < keys_count; k++) {
806 memset(buf, 0, sizeof(buf));
807 strncat(buf, " ", 2);
809 len = strlen(keys[k]->cipher->cipher->name);
810 strncat(buf, keys[k]->cipher->cipher->name, len > 16 ? 16 : len);
812 for (i = 0; i < 16 - len; i++)
816 len = strlen(silc_hmac_get_name(keys[k]->hmac));
817 strncat(buf, silc_hmac_get_name(keys[k]->hmac), len > 16 ? 16 : len);
819 for (i = 0; i < 16 - len; i++)
823 strcat(buf, "<hidden>");
825 silc_say(silc_client, conn, SILC_CLIENT_MESSAGE_INFO, "%s", buf);
828 silc_client_free_channel_private_keys(keys, keys_count);
834 /* Send command is used to send key agreement */
835 if (!strcasecmp(argv[3], "agreement")) {
841 port = atoi(argv[5]);
843 internal = silc_calloc(1, sizeof(*internal));
844 internal->type = type;
845 internal->server = server;
848 if (settings_get_bool("use_auto_addr")) {
850 hostname = (char *)settings_get_str("auto_public_ip");
852 /* If the hostname isn't set, treat this case as if auto_public_ip
854 if ((hostname) && (*hostname == '\0')) {
857 bindhost = (char *)settings_get_str("auto_bind_ip");
859 /* if the bind_ip isn't set, but the public_ip IS, then assume then
860 public_ip is the same value as the bind_ip. */
861 if ((bindhost) && (*bindhost == '\0'))
863 port = settings_get_int("auto_bind_port");
865 } /* if use_auto_addr */
869 /* Start command is used to start key agreement (after receiving the
870 key_agreement client operation). */
871 if (!strcasecmp(argv[3], "negotiate")) {
877 port = atoi(argv[5]);
879 internal = silc_calloc(1, sizeof(*internal));
880 internal->type = type;
881 internal->server = server;
884 /* Change current channel private key */
885 if (!strcasecmp(argv[3], "change")) {
888 /* Unset channel key(s) */
889 SilcChannelPrivateKey *keys;
890 SilcUInt32 keys_count;
893 keys = silc_client_list_channel_private_keys(silc_client, conn,
901 if (chanrec->cur_key >= keys_count)
902 chanrec->cur_key = 0;
906 number = atoi(argv[4]);
907 if (!number || number > keys_count)
908 chanrec->cur_key = 0;
910 chanrec->cur_key = number - 1;
913 /* Set the current channel private key */
914 silc_client_current_channel_private_key(silc_client, conn,
916 keys[chanrec->cur_key]);
917 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
918 SILCTXT_CH_PRIVATE_KEY_CHANGE, chanrec->cur_key + 1,
919 channel_entry->channel_name);
921 silc_client_free_channel_private_keys(keys, keys_count);
927 silc_say(silc_client, conn, SILC_CLIENT_MESSAGE_INFO,
928 "Usage: /KEY msg|channel <nickname|channel> "
929 "set|unset|agreement|negotiate [<arguments>]");
933 if (command == 4 && client_entry) {
934 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
935 SILCTXT_KEY_AGREEMENT, argv[2]);
936 internal->responder = TRUE;
937 silc_client_send_key_agreement(
938 silc_client, conn, client_entry, hostname,
940 settings_get_int("key_exchange_timeout_secs"),
941 keyagr_completion, internal);
947 if (command == 5 && client_entry && hostname) {
948 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
949 SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
950 internal->responder = FALSE;
951 silc_client_perform_key_agreement(silc_client, conn, client_entry,
952 hostname, port, keyagr_completion,
961 /* Lists locally saved client and server public keys. */
963 static void command_listkeys(const char *data, SILC_SERVER_REC *server,
969 void silc_channels_init(void)
971 signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
972 signal_add("server connected", (SIGNAL_FUNC) sig_connected);
973 signal_add("server quit", (SIGNAL_FUNC) sig_server_quit);
975 command_bind_silc("part", MODULE_NAME, (SIGNAL_FUNC) command_part);
976 command_bind_silc("me", MODULE_NAME, (SIGNAL_FUNC) command_me);
977 command_bind_silc("action", MODULE_NAME, (SIGNAL_FUNC) command_action);
978 command_bind_silc("notice", MODULE_NAME, (SIGNAL_FUNC) command_notice);
979 command_bind_silc("away", MODULE_NAME, (SIGNAL_FUNC) command_away);
980 command_bind_silc("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
981 command_bind_silc("listkeys", MODULE_NAME, (SIGNAL_FUNC) command_listkeys);
983 silc_nicklist_init();
986 void silc_channels_deinit(void)
988 signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
989 signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
990 signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit);
992 command_unbind("part", (SIGNAL_FUNC) command_part);
993 command_unbind("me", (SIGNAL_FUNC) command_me);
994 command_unbind("action", (SIGNAL_FUNC) command_action);
995 command_unbind("notice", (SIGNAL_FUNC) command_notice);
996 command_unbind("away", (SIGNAL_FUNC) command_away);
997 command_unbind("key", (SIGNAL_FUNC) command_key);
998 command_unbind("listkeys", (SIGNAL_FUNC) command_listkeys);
1000 silc_nicklist_deinit();