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 SILC_CHANNEL_REC *silc_channel_create(SILC_SERVER_REC *server,
47 const char *name, int automatic)
49 SILC_CHANNEL_REC *rec;
51 g_return_val_if_fail(server == NULL || IS_SILC_SERVER(server), NULL);
52 g_return_val_if_fail(name != NULL, NULL);
54 rec = g_new0(SILC_CHANNEL_REC, 1);
55 rec->chat_type = SILC_PROTOCOL;
56 rec->name = g_strdup(name);
59 channel_init((CHANNEL_REC *) rec, automatic);
63 static void sig_channel_destroyed(SILC_CHANNEL_REC *channel)
65 if (!IS_SILC_CHANNEL(channel))
68 if (channel->server != NULL && !channel->left && !channel->kicked) {
69 /* destroying channel record without actually
70 having left the channel yet */
71 silc_command_exec(channel->server, "PART", channel->name);
75 static void silc_channels_join(SILC_SERVER_REC *server,
76 const char *channels, int automatic)
78 char **list, **tmp, *channel;
80 list = g_strsplit(channels, ",", -1);
81 for (tmp = list; *tmp != NULL; tmp++) {
82 channel = **tmp == '#' ? g_strdup(*tmp) :
83 g_strconcat("#", *tmp, NULL);
84 silc_channel_create(server, channel, FALSE);
85 silc_command_exec(server, "JOIN", channel);
91 static void sig_connected(SILC_SERVER_REC *server)
93 if (IS_SILC_SERVER(server))
94 server->channels_join = (void *) silc_channels_join;
97 /* "server quit" signal from the core to indicate that QUIT command
100 static void sig_server_quit(SILC_SERVER_REC *server, const char *msg)
102 if (IS_SILC_SERVER(server))
103 silc_command_exec(server, "QUIT", msg);
107 * "event join". Joined to a channel.
110 SILC_CHANNEL_REC *silc_channel_find_entry(SILC_SERVER_REC *server,
111 SilcChannelEntry entry)
115 g_return_val_if_fail(IS_SILC_SERVER(server), NULL);
117 for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
118 SILC_CHANNEL_REC *rec = tmp->data;
120 if (rec->entry == entry)
127 static void event_join(SILC_SERVER_REC *server, va_list va)
129 SILC_CHANNEL_REC *chanrec;
130 SILC_NICK_REC *nickrec;
131 SilcClientEntry client;
132 SilcChannelEntry channel;
134 client = va_arg(va, SilcClientEntry);
135 channel = va_arg(va, SilcChannelEntry);
137 if (client == server->conn->local_entry) {
138 /* You joined to channel */
139 chanrec = silc_channel_find(server, channel->channel_name);
140 if (chanrec != NULL && !chanrec->joined)
141 chanrec->entry = channel;
143 chanrec = silc_channel_find_entry(server, channel);
144 if (chanrec != NULL) {
145 SilcChannelUser user;
147 silc_list_start(chanrec->entry->clients);
148 while ((user = silc_list_get(chanrec->entry->clients)) != NULL)
149 if (user->client == client) {
150 nickrec = silc_nicklist_insert(chanrec, user, TRUE);
156 signal_emit("message join", 4, server, channel->channel_name,
158 client->username == NULL ? "" : client->username);
162 * "event leave". Left a channel.
165 static void event_leave(SILC_SERVER_REC *server, va_list va)
167 SILC_CHANNEL_REC *chanrec;
168 SILC_NICK_REC *nickrec;
169 SilcClientEntry client;
170 SilcChannelEntry channel;
172 client = va_arg(va, SilcClientEntry);
173 channel = va_arg(va, SilcChannelEntry);
175 signal_emit("message part", 5, server, channel->channel_name,
176 client->nickname, client->username ? client->username : "",
179 chanrec = silc_channel_find_entry(server, channel);
180 if (chanrec != NULL) {
181 nickrec = silc_nicklist_find(chanrec, client);
183 nicklist_remove(CHANNEL(chanrec), NICK(nickrec));
188 * "event signoff". Left the network.
191 static void event_signoff(SILC_SERVER_REC *server, va_list va)
193 SilcClientEntry client;
197 client = va_arg(va, SilcClientEntry);
198 message = va_arg(va, char *);
200 signal_emit("message quit", 4, server, client->nickname,
201 client->username ? client->username : "",
202 message ? message : "");
204 nicks = nicklist_get_same_unique(SERVER(server), client);
205 for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) {
206 CHANNEL_REC *channel = tmp->data;
207 NICK_REC *nickrec = tmp->next->data;
209 nicklist_remove(channel, nickrec);
214 * "event topic". Changed topic.
217 static void event_topic(SILC_SERVER_REC *server, va_list va)
219 SILC_CHANNEL_REC *chanrec;
220 SilcClientEntry client;
221 SilcChannelEntry channel;
224 client = va_arg(va, SilcClientEntry);
225 topic = va_arg(va, char *);
226 channel = va_arg(va, SilcChannelEntry);
228 chanrec = silc_channel_find_entry(server, channel);
229 if (chanrec != NULL) {
230 g_free_not_null(chanrec->topic);
231 chanrec->topic = *topic == '\0' ? NULL : g_strdup(topic);
232 signal_emit("channel topic changed", 1, chanrec);
235 signal_emit("message topic", 5, server, channel->channel_name,
236 topic, client->nickname, client->username);
240 * "event invite". Invited or modified invite list.
243 static void event_invite(SILC_SERVER_REC *server, va_list va)
245 SilcClientEntry client;
246 SilcChannelEntry channel;
248 client = va_arg(va, SilcClientEntry);
249 channel = va_arg(va, SilcChannelEntry);
251 signal_emit("message invite", 4, server, channel->channel_name,
252 client->nickname, client->username);
256 * "event nick". Changed nickname.
259 static void event_nick(SILC_SERVER_REC *server, va_list va)
261 SilcClientEntry oldclient, newclient;
263 oldclient = va_arg(va, SilcClientEntry);
264 newclient = va_arg(va, SilcClientEntry);
266 nicklist_rename_unique(SERVER(server),
267 oldclient, oldclient->nickname,
268 newclient, newclient->nickname);
270 signal_emit("message nick", 4, server, newclient->nickname,
271 oldclient->nickname, newclient->username);
275 * "event cmode". Changed channel mode.
278 static void event_cmode(SILC_SERVER_REC *server, va_list va)
280 SILC_CHANNEL_REC *chanrec;
281 SilcClientEntry client;
282 SilcChannelEntry channel;
286 client = va_arg(va, SilcClientEntry);
287 modei = va_arg(va, uint32);
288 (void)va_arg(va, char *);
289 (void)va_arg(va, char *);
290 channel = va_arg(va, SilcChannelEntry);
292 mode = silc_client_chmode(modei, channel);
294 chanrec = silc_channel_find_entry(server, channel);
295 if (chanrec != NULL) {
296 g_free_not_null(chanrec->mode);
297 chanrec->mode = g_strdup(mode == NULL ? "" : mode);
298 signal_emit("channel mode changed", 1, chanrec);
301 printformat_module("fe-common/silc", server, channel->channel_name,
302 MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE,
303 channel->channel_name, mode ? mode : "removed all",
310 * "event cumode". Changed user's mode on channel.
313 static void event_cumode(SILC_SERVER_REC *server, va_list va)
315 SILC_CHANNEL_REC *chanrec;
316 SilcClientEntry client, destclient;
317 SilcChannelEntry channel;
321 client = va_arg(va, SilcClientEntry);
322 mode = va_arg(va, uint32);
323 destclient = va_arg(va, SilcClientEntry);
324 channel = va_arg(va, SilcChannelEntry);
326 modestr = silc_client_chumode(mode);
327 chanrec = silc_channel_find_entry(server, channel);
328 if (chanrec != NULL) {
331 if (destclient == server->conn->local_entry) {
333 (mode & SILC_CHANNEL_UMODE_CHANOP) != 0;
336 nick = silc_nicklist_find(chanrec, destclient);
338 nick->op = (mode & SILC_CHANNEL_UMODE_CHANOP) != 0;
339 signal_emit("nick mode changed", 2, chanrec, nick);
343 printformat_module("fe-common/silc", server, channel->channel_name,
344 MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
345 channel->channel_name, destclient->nickname,
346 modestr ? modestr : "removed all",
349 if (mode & SILC_CHANNEL_UMODE_CHANFO)
350 printformat_module("fe-common/silc",
351 server, channel->channel_name, MSGLEVEL_CRAP,
352 SILCTXT_CHANNEL_FOUNDER,
353 channel->channel_name, destclient->nickname);
359 * "event motd". Received MOTD.
362 static void event_motd(SILC_SERVER_REC *server, va_list va)
364 char *text = va_arg(va, char *);
366 if (!settings_get_bool("skip_motd"))
367 printtext_multiline(server, NULL, MSGLEVEL_CRAP, "%s", text);
371 * "event channel_change". Channel ID has changed.
374 static void event_channel_change(SILC_SERVER_REC *server, va_list va)
380 * "event server_signoff". Server has quit the network.
383 static void event_server_signoff(SILC_SERVER_REC *server, va_list va)
389 * "event kick". Someone was kicked from channel.
392 static void event_kick(SILC_SERVER_REC *server, va_list va)
398 * "event kill". Someone was killed from the network.
401 static void event_kill(SILC_SERVER_REC *server, va_list va)
407 * "event ban". Someone was banned or ban list was modified.
410 static void event_ban(SILC_SERVER_REC *server, va_list va)
415 /* PART (LEAVE) command. */
417 static void command_part(const char *data, SILC_SERVER_REC *server,
420 SILC_CHANNEL_REC *chanrec;
422 if (!IS_SILC_SERVER(server) || !server->connected)
423 cmd_return_error(CMDERR_NOT_CONNECTED);
426 if (!IS_SILC_CHANNEL(item))
427 cmd_return_error(CMDERR_NOT_JOINED);
431 chanrec = silc_channel_find(server, data);
433 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
435 signal_emit("message part", 5, server, chanrec->name,
436 server->nick, server->conn->local_entry->username, "");
438 silc_command_exec(server, "LEAVE", chanrec->name);
441 channel_destroy(CHANNEL(chanrec));
444 /* ME local command. */
446 static void command_me(const char *data, SILC_SERVER_REC *server,
449 SILC_CHANNEL_REC *chanrec;
450 char *tmpcmd = "ME", *tmp;
452 unsigned char **argv;
453 uint32 *argv_lens, *argv_types;
456 if (!IS_SILC_SERVER(server) || !server->connected)
457 cmd_return_error(CMDERR_NOT_CONNECTED);
459 if (!IS_SILC_CHANNEL(item))
460 cmd_return_error(CMDERR_NOT_JOINED);
462 /* Now parse all arguments */
463 tmp = g_strconcat(tmpcmd, " ", data, NULL);
464 silc_parse_command_line(tmp, &argv, &argv_lens,
465 &argv_types, &argc, 2);
469 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
471 chanrec = silc_channel_find(server, item->name);
473 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
475 /* Send the action message */
476 silc_client_send_channel_message(silc_client, server->conn,
477 chanrec->entry, NULL,
478 SILC_MESSAGE_FLAG_ACTION,
479 argv[1], argv_lens[1], TRUE);
481 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
482 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION, argv[1]);
484 for (i = 0; i < argc; i++)
486 silc_free(argv_lens);
487 silc_free(argv_types);
490 /* NOTICE local command. */
492 static void command_notice(const char *data, SILC_SERVER_REC *server,
495 SILC_CHANNEL_REC *chanrec;
496 char *tmpcmd = "ME", *tmp;
498 unsigned char **argv;
499 uint32 *argv_lens, *argv_types;
502 if (!IS_SILC_SERVER(server) || !server->connected)
503 cmd_return_error(CMDERR_NOT_CONNECTED);
505 if (!IS_SILC_CHANNEL(item))
506 cmd_return_error(CMDERR_NOT_JOINED);
508 /* Now parse all arguments */
509 tmp = g_strconcat(tmpcmd, " ", data, NULL);
510 silc_parse_command_line(tmp, &argv, &argv_lens,
511 &argv_types, &argc, 2);
515 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
517 chanrec = silc_channel_find(server, item->name);
519 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
521 /* Send the action message */
522 silc_client_send_channel_message(silc_client, server->conn,
523 chanrec->entry, NULL,
524 SILC_MESSAGE_FLAG_NOTICE,
525 argv[1], argv_lens[1], TRUE);
527 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
528 MSGLEVEL_NOTICES, SILCTXT_CHANNEL_OWNNOTICE, argv[1]);
530 for (i = 0; i < argc; i++)
532 silc_free(argv_lens);
533 silc_free(argv_types);
536 /* AWAY local command. Sends UMODE command that sets the SILC_UMODE_GONE
539 static void command_away(const char *data, SILC_SERVER_REC *server,
542 if (!IS_SILC_SERVER(server) || !server->connected)
543 cmd_return_error(CMDERR_NOT_CONNECTED);
549 int type; /* 1 = msg, 2 = channel */
550 SILC_SERVER_REC *server;
553 static SilcSKEKeyMaterial *curr_key = NULL;
555 /* Key agreement callback that is called after the key agreement protocol
556 has been performed. This is called also if error occured during the
557 key agreement protocol. The `key' is the allocated key material and
558 the caller is responsible of freeing it. The `key' is NULL if error
559 has occured. The application can freely use the `key' to whatever
560 purpose it needs. See lib/silcske/silcske.h for the definition of
561 the SilcSKEKeyMaterial structure. */
563 static void keyagr_completion(SilcClient client,
564 SilcClientConnection conn,
565 SilcClientEntry client_entry,
566 SilcKeyAgreementStatus status,
567 SilcSKEKeyMaterial *key,
570 KeyInternal i = (KeyInternal)context;
575 case SILC_KEY_AGREEMENT_OK:
576 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
577 SILCTXT_KEY_AGREEMENT_OK, client_entry->nickname);
580 /* Set the private key for this client */
581 silc_client_del_private_message_key(client, conn, client_entry);
582 silc_client_add_private_message_key_ske(client, conn, client_entry,
584 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
585 SILCTXT_KEY_AGREEMENT_PRIVMSG,
586 client_entry->nickname);
587 silc_ske_free_key_material(key);
592 case SILC_KEY_AGREEMENT_ERROR:
593 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
594 SILCTXT_KEY_AGREEMENT_ERROR, client_entry->nickname);
597 case SILC_KEY_AGREEMENT_FAILURE:
598 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
599 SILCTXT_KEY_AGREEMENT_FAILURE, client_entry->nickname);
602 case SILC_KEY_AGREEMENT_TIMEOUT:
603 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
604 SILCTXT_KEY_AGREEMENT_TIMEOUT, client_entry->nickname);
615 /* Local command KEY. This command is used to set and unset private
616 keys for channels, set and unset private keys for private messages
617 with remote clients and to send key agreement requests and
618 negotiate the key agreement protocol with remote client. The
619 key agreement is supported only to negotiate private message keys,
620 it currently cannot be used to negotiate private keys for channels,
621 as it is not convenient for that purpose. */
624 SILC_SERVER_REC *server;
629 /* Callback to be called after client information is resolved from the
632 SILC_CLIENT_CMD_FUNC(key_get_clients)
634 KeyGetClients internal = (KeyGetClients)context;
635 signal_emit("command key", 3, internal->data, internal->server,
637 silc_free(internal->data);
641 static void command_key(const char *data, SILC_SERVER_REC *server,
644 SilcClientConnection conn = server->conn;
645 SilcClientEntry client_entry = NULL;
646 SilcChannelEntry channel_entry = NULL;
648 char *nickname = NULL, *serv = NULL, *tmp;
649 int command = 0, port = 0, type = 0;
650 char *hostname = NULL;
651 KeyInternal internal = NULL;
653 unsigned char **argv;
654 uint32 *argv_lens, *argv_types;
656 if (!IS_SILC_SERVER(server) || !server->connected)
657 cmd_return_error(CMDERR_NOT_CONNECTED);
659 /* Now parse all arguments */
660 tmp = g_strconcat("KEY", " ", data, NULL);
661 silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 7);
665 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
666 "set|unset|agreement|negotiate [<arguments>]");
671 if (!strcasecmp(argv[1], "msg"))
673 if (!strcasecmp(argv[1], "channel"))
677 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
678 "set|unset|agreement|negotiate [<arguments>]");
683 if (argv[2][0] == '*') {
686 /* Parse the typed nickname. */
687 if (!silc_parse_nickname(argv[2], &nickname, &serv, &num)) {
688 printformat_module("fe-common/silc", server, NULL,
689 MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
693 /* Find client entry */
694 client_entry = silc_idlist_get_client(silc_client, conn, nickname,
697 KeyGetClients inter = silc_calloc(1, sizeof(*inter));
698 inter->server = server;
699 inter->data = strdup(data);
702 /* Client entry not found, it was requested thus mark this to be
704 silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
706 NULL, silc_client_command_key_get_clients,
714 /* Get channel entry */
717 if (argv[2][0] == '*') {
718 if (!conn->current_channel) {
723 cmd_return_error(CMDERR_NOT_JOINED);
725 name = conn->current_channel->channel_name;
730 channel_entry = silc_client_get_channel(silc_client, conn, name);
731 if (!channel_entry) {
736 cmd_return_error(CMDERR_NOT_JOINED);
741 if (!strcasecmp(argv[3], "set")) {
745 if (curr_key && type == 1 && client_entry) {
746 silc_client_del_private_message_key(silc_client, conn, client_entry);
747 silc_client_add_private_message_key_ske(silc_client, conn,
748 client_entry, NULL, curr_key);
754 if (type == 1 && client_entry) {
755 /* Set private message key */
757 silc_client_del_private_message_key(silc_client, conn, client_entry);
760 silc_client_add_private_message_key(silc_client, conn, client_entry,
766 silc_client_add_private_message_key(silc_client, conn, client_entry,
772 /* Send the key to the remote client so that it starts using it
774 silc_client_send_private_message_key(silc_client, conn,
776 } else if (type == 2) {
777 /* Set private channel key */
778 char *cipher = NULL, *hmac = NULL;
780 if (!(channel_entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
781 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
782 SILCTXT_CH_PRIVATE_KEY_NOMODE,
783 channel_entry->channel_name);
792 if (!silc_client_add_channel_private_key(silc_client, conn,
797 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
798 SILCTXT_CH_PRIVATE_KEY_ERROR,
799 channel_entry->channel_name);
803 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
804 SILCTXT_CH_PRIVATE_KEY_ADD,
805 channel_entry->channel_name);
813 if (!strcasecmp(argv[3], "unset")) {
816 if (type == 1 && client_entry) {
817 /* Unset private message key */
818 silc_client_del_private_message_key(silc_client, conn, client_entry);
819 } else if (type == 2) {
820 /* Unset channel key(s) */
821 SilcChannelPrivateKey *keys;
826 silc_client_del_channel_private_keys(silc_client, conn,
830 number = atoi(argv[4]);
831 keys = silc_client_list_channel_private_keys(silc_client, conn,
837 if (!number || number > keys_count) {
838 silc_client_free_channel_private_keys(keys, keys_count);
842 silc_client_del_channel_private_key(silc_client, conn, channel_entry,
844 silc_client_free_channel_private_keys(keys, keys_count);
852 if (!strcasecmp(argv[3], "list")) {
856 SilcPrivateMessageKeys keys;
861 keys = silc_client_list_private_message_keys(silc_client, conn,
866 /* list the private message key(s) */
867 if (nickname[0] == '*') {
868 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
869 SILCTXT_PRIVATE_KEY_LIST);
870 for (k = 0; k < keys_count; k++) {
871 memset(buf, 0, sizeof(buf));
872 strncat(buf, " ", 2);
873 len = strlen(keys[k].client_entry->nickname);
874 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
876 for (i = 0; i < 30 - len; i++)
880 len = strlen(keys[k].cipher);
881 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
883 for (i = 0; i < 14 - len; i++)
888 strcat(buf, "<hidden>");
890 strcat(buf, "*generated*");
892 silc_say(silc_client, conn, "%s", buf);
895 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
896 SILCTXT_PRIVATE_KEY_LIST_NICK,
897 client_entry->nickname);
898 for (k = 0; k < keys_count; k++) {
899 if (keys[k].client_entry != client_entry)
902 memset(buf, 0, sizeof(buf));
903 strncat(buf, " ", 2);
904 len = strlen(keys[k].client_entry->nickname);
905 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
907 for (i = 0; i < 30 - len; i++)
911 len = strlen(keys[k].cipher);
912 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
914 for (i = 0; i < 14 - len; i++)
919 strcat(buf, "<hidden>");
921 strcat(buf, "*generated*");
923 silc_say(silc_client, conn, "%s", buf);
927 silc_client_free_private_message_keys(keys, keys_count);
928 } else if (type == 2) {
929 SilcChannelPrivateKey *keys;
934 keys = silc_client_list_channel_private_keys(silc_client, conn,
940 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
941 SILCTXT_CH_PRIVATE_KEY_LIST,
942 channel_entry->channel_name);
943 for (k = 0; k < keys_count; k++) {
944 memset(buf, 0, sizeof(buf));
945 strncat(buf, " ", 2);
947 len = strlen(keys[k]->cipher->cipher->name);
948 strncat(buf, keys[k]->cipher->cipher->name, len > 16 ? 16 : len);
950 for (i = 0; i < 16 - len; i++)
954 len = strlen(keys[k]->hmac->hmac->name);
955 strncat(buf, keys[k]->hmac->hmac->name, len > 16 ? 16 : len);
957 for (i = 0; i < 16 - len; i++)
961 strcat(buf, "<hidden>");
963 silc_say(silc_client, conn, "%s", buf);
966 silc_client_free_channel_private_keys(keys, keys_count);
972 /* Send command is used to send key agreement */
973 if (!strcasecmp(argv[3], "agreement")) {
979 port = atoi(argv[5]);
981 internal = silc_calloc(1, sizeof(*internal));
982 internal->type = type;
983 internal->server = server;
986 /* Start command is used to start key agreement (after receiving the
987 key_agreement client operation). */
988 if (!strcasecmp(argv[3], "negotiate")) {
994 port = atoi(argv[5]);
996 internal = silc_calloc(1, sizeof(*internal));
997 internal->type = type;
998 internal->server = server;
1002 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
1003 "set|unset|agreement|negotiate [<arguments>]");
1007 if (command == 4 && client_entry) {
1008 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
1009 SILCTXT_KEY_AGREEMENT, argv[2]);
1010 silc_client_send_key_agreement(silc_client, conn, client_entry, hostname,
1011 port, 120, keyagr_completion, internal);
1015 if (command == 5 && client_entry && hostname) {
1016 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
1017 SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
1018 silc_client_perform_key_agreement(silc_client, conn, client_entry,
1019 hostname, port, keyagr_completion,
1026 silc_free(nickname);
1031 void silc_channels_init(void)
1033 signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1034 signal_add("server connected", (SIGNAL_FUNC) sig_connected);
1035 signal_add("server quit", (SIGNAL_FUNC) sig_server_quit);
1037 signal_add("silc event join", (SIGNAL_FUNC) event_join);
1038 signal_add("silc event leave", (SIGNAL_FUNC) event_leave);
1039 signal_add("silc event signoff", (SIGNAL_FUNC) event_signoff);
1040 signal_add("silc event topic", (SIGNAL_FUNC) event_topic);
1041 signal_add("silc event invite", (SIGNAL_FUNC) event_invite);
1042 signal_add("silc event nick", (SIGNAL_FUNC) event_nick);
1043 signal_add("silc event cmode", (SIGNAL_FUNC) event_cmode);
1044 signal_add("silc event cumode", (SIGNAL_FUNC) event_cumode);
1045 signal_add("silc event motd", (SIGNAL_FUNC) event_motd);
1046 signal_add("silc event channel_change", (SIGNAL_FUNC) event_channel_change);
1047 signal_add("silc event server_signoff", (SIGNAL_FUNC) event_server_signoff);
1048 signal_add("silc event kick", (SIGNAL_FUNC) event_kick);
1049 signal_add("silc event kill", (SIGNAL_FUNC) event_kill);
1050 signal_add("silc event ban", (SIGNAL_FUNC) event_ban);
1052 command_bind("part", MODULE_NAME, (SIGNAL_FUNC) command_part);
1053 command_bind("me", MODULE_NAME, (SIGNAL_FUNC) command_me);
1054 command_bind("notice", MODULE_NAME, (SIGNAL_FUNC) command_notice);
1055 command_bind("away", MODULE_NAME, (SIGNAL_FUNC) command_away);
1056 command_bind("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
1058 silc_nicklist_init();
1061 void silc_channels_deinit(void)
1063 signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1064 signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
1065 signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit);
1067 signal_remove("silc event join", (SIGNAL_FUNC) event_join);
1068 signal_remove("silc event leave", (SIGNAL_FUNC) event_leave);
1069 signal_remove("silc event signoff", (SIGNAL_FUNC) event_signoff);
1070 signal_remove("silc event topic", (SIGNAL_FUNC) event_topic);
1071 signal_remove("silc event invite", (SIGNAL_FUNC) event_invite);
1072 signal_remove("silc event nick", (SIGNAL_FUNC) event_nick);
1073 signal_remove("silc event cmode", (SIGNAL_FUNC) event_cmode);
1074 signal_remove("silc event cumode", (SIGNAL_FUNC) event_cumode);
1075 signal_remove("silc event motd", (SIGNAL_FUNC) event_motd);
1076 signal_remove("silc event channel_change",
1077 (SIGNAL_FUNC) event_channel_change);
1078 signal_remove("silc event server_signoff",
1079 (SIGNAL_FUNC) event_server_signoff);
1080 signal_remove("silc event kick", (SIGNAL_FUNC) event_kick);
1081 signal_remove("silc event kill", (SIGNAL_FUNC) event_kill);
1082 signal_remove("silc event ban", (SIGNAL_FUNC) event_ban);
1084 command_unbind("part", (SIGNAL_FUNC) command_part);
1085 command_unbind("me", (SIGNAL_FUNC) command_me);
1086 command_unbind("notice", (SIGNAL_FUNC) command_notice);
1087 command_unbind("away", (SIGNAL_FUNC) command_away);
1088 command_unbind("key", (SIGNAL_FUNC) command_key);
1090 silc_nicklist_deinit();