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;
79 SILC_CHANNEL_REC *chanrec;
81 list = g_strsplit(channels, ",", -1);
82 for (tmp = list; *tmp != NULL; tmp++) {
83 channel = **tmp == '#' ? g_strdup(*tmp) :
84 g_strconcat("#", *tmp, NULL);
86 chanrec = silc_channel_find(server, channel);
92 silc_channel_create(server, channel, FALSE);
93 silc_command_exec(server, "JOIN", channel);
100 static void sig_connected(SILC_SERVER_REC *server)
102 if (IS_SILC_SERVER(server))
103 server->channels_join = (void *) silc_channels_join;
106 /* "server quit" signal from the core to indicate that QUIT command
109 static void sig_server_quit(SILC_SERVER_REC *server, const char *msg)
111 if (IS_SILC_SERVER(server) && server->conn && server->conn->sock)
112 silc_command_exec(server, "QUIT", msg);
116 * "event join". Joined to a channel.
119 SILC_CHANNEL_REC *silc_channel_find_entry(SILC_SERVER_REC *server,
120 SilcChannelEntry entry)
124 g_return_val_if_fail(IS_SILC_SERVER(server), NULL);
126 for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
127 SILC_CHANNEL_REC *rec = tmp->data;
129 if (rec->entry == entry)
136 static void event_join(SILC_SERVER_REC *server, va_list va)
138 SILC_CHANNEL_REC *chanrec;
139 SILC_NICK_REC *nickrec;
140 SilcClientEntry client;
141 SilcChannelEntry channel;
143 client = va_arg(va, SilcClientEntry);
144 channel = va_arg(va, SilcChannelEntry);
146 if (client == server->conn->local_entry) {
147 /* You joined to channel */
148 chanrec = silc_channel_find(server, channel->channel_name);
149 if (chanrec != NULL && !chanrec->joined)
150 chanrec->entry = channel;
152 chanrec = silc_channel_find_entry(server, channel);
153 if (chanrec != NULL) {
154 SilcChannelUser user;
156 silc_list_start(chanrec->entry->clients);
157 while ((user = silc_list_get(chanrec->entry->clients)) != NULL)
158 if (user->client == client) {
159 nickrec = silc_nicklist_insert(chanrec, user, TRUE);
165 signal_emit("message join", 4, server, channel->channel_name,
167 client->username == NULL ? "" : client->username);
171 * "event leave". Left a channel.
174 static void event_leave(SILC_SERVER_REC *server, va_list va)
176 SILC_CHANNEL_REC *chanrec;
177 SILC_NICK_REC *nickrec;
178 SilcClientEntry client;
179 SilcChannelEntry channel;
181 client = va_arg(va, SilcClientEntry);
182 channel = va_arg(va, SilcChannelEntry);
184 signal_emit("message part", 5, server, channel->channel_name,
185 client->nickname, client->username ? client->username : "",
188 chanrec = silc_channel_find_entry(server, channel);
189 if (chanrec != NULL) {
190 nickrec = silc_nicklist_find(chanrec, client);
192 nicklist_remove(CHANNEL(chanrec), NICK(nickrec));
197 * "event signoff". Left the network.
200 static void event_signoff(SILC_SERVER_REC *server, va_list va)
202 SilcClientEntry client;
206 client = va_arg(va, SilcClientEntry);
207 message = va_arg(va, char *);
209 signal_emit("message quit", 4, server, client->nickname,
210 client->username ? client->username : "",
211 message ? message : "");
213 nicks = nicklist_get_same_unique(SERVER(server), client);
214 for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) {
215 CHANNEL_REC *channel = tmp->data;
216 NICK_REC *nickrec = tmp->next->data;
218 nicklist_remove(channel, nickrec);
223 * "event topic". Changed topic.
226 static void event_topic(SILC_SERVER_REC *server, va_list va)
228 SILC_CHANNEL_REC *chanrec;
229 SilcClientEntry client;
230 SilcChannelEntry channel;
233 client = va_arg(va, SilcClientEntry);
234 topic = va_arg(va, char *);
235 channel = va_arg(va, SilcChannelEntry);
237 chanrec = silc_channel_find_entry(server, channel);
238 if (chanrec != NULL) {
239 g_free_not_null(chanrec->topic);
240 chanrec->topic = *topic == '\0' ? NULL : g_strdup(topic);
241 signal_emit("channel topic changed", 1, chanrec);
244 signal_emit("message topic", 5, server, channel->channel_name,
245 topic, client->nickname, client->username);
249 * "event invite". Invited or modified invite list.
252 static void event_invite(SILC_SERVER_REC *server, va_list va)
254 SilcClientEntry client;
255 SilcChannelEntry channel;
258 channel = va_arg(va, SilcChannelEntry);
259 channel_name = va_arg(va, char *);
260 client = va_arg(va, SilcClientEntry);
262 signal_emit("message invite", 4, server, channel ? channel->channel_name :
263 channel_name, client->nickname, client->username);
267 * "event nick". Changed nickname.
270 static void event_nick(SILC_SERVER_REC *server, va_list va)
272 SilcClientEntry oldclient, newclient;
274 oldclient = va_arg(va, SilcClientEntry);
275 newclient = va_arg(va, SilcClientEntry);
277 nicklist_rename_unique(SERVER(server),
278 oldclient, oldclient->nickname,
279 newclient, newclient->nickname);
281 signal_emit("message nick", 4, server, newclient->nickname,
282 oldclient->nickname, newclient->username);
286 * "event cmode". Changed channel mode.
289 static void event_cmode(SILC_SERVER_REC *server, va_list va)
291 SILC_CHANNEL_REC *chanrec;
292 SilcClientEntry client;
293 SilcChannelEntry channel;
297 client = va_arg(va, SilcClientEntry);
298 modei = va_arg(va, uint32);
299 (void)va_arg(va, char *);
300 (void)va_arg(va, char *);
301 channel = va_arg(va, SilcChannelEntry);
303 mode = silc_client_chmode(modei,
304 channel->channel_key->cipher->name,
305 channel->hmac->hmac->name);
307 chanrec = silc_channel_find_entry(server, channel);
308 if (chanrec != NULL) {
309 g_free_not_null(chanrec->mode);
310 chanrec->mode = g_strdup(mode == NULL ? "" : mode);
311 signal_emit("channel mode changed", 1, chanrec);
314 printformat_module("fe-common/silc", server, channel->channel_name,
315 MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE,
316 channel->channel_name, mode ? mode : "removed all",
323 * "event cumode". Changed user's mode on channel.
326 static void event_cumode(SILC_SERVER_REC *server, va_list va)
328 SILC_CHANNEL_REC *chanrec;
329 SilcClientEntry client, destclient;
330 SilcChannelEntry channel;
334 client = va_arg(va, SilcClientEntry);
335 mode = va_arg(va, uint32);
336 destclient = va_arg(va, SilcClientEntry);
337 channel = va_arg(va, SilcChannelEntry);
339 modestr = silc_client_chumode(mode);
340 chanrec = silc_channel_find_entry(server, channel);
341 if (chanrec != NULL) {
344 if (destclient == server->conn->local_entry) {
346 (mode & SILC_CHANNEL_UMODE_CHANOP) != 0;
349 nick = silc_nicklist_find(chanrec, destclient);
351 nick->op = (mode & SILC_CHANNEL_UMODE_CHANOP) != 0;
352 signal_emit("nick mode changed", 2, chanrec, nick);
356 printformat_module("fe-common/silc", server, channel->channel_name,
357 MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
358 channel->channel_name, destclient->nickname,
359 modestr ? modestr : "removed all",
362 if (mode & SILC_CHANNEL_UMODE_CHANFO)
363 printformat_module("fe-common/silc",
364 server, channel->channel_name, MSGLEVEL_CRAP,
365 SILCTXT_CHANNEL_FOUNDER,
366 channel->channel_name, destclient->nickname);
372 * "event motd". Received MOTD.
375 static void event_motd(SILC_SERVER_REC *server, va_list va)
377 char *text = va_arg(va, char *);
379 if (!settings_get_bool("skip_motd"))
380 printtext_multiline(server, NULL, MSGLEVEL_CRAP, "%s", text);
384 * "event channel_change". Channel ID has changed.
387 static void event_channel_change(SILC_SERVER_REC *server, va_list va)
393 * "event server_signoff". Server has quit the network.
396 static void event_server_signoff(SILC_SERVER_REC *server, va_list va)
402 * "event kick". Someone was kicked from channel.
405 static void event_kick(SILC_SERVER_REC *server, va_list va)
411 * "event kill". Someone was killed from the network.
414 static void event_kill(SILC_SERVER_REC *server, va_list va)
420 * "event ban". Someone was banned or ban list was modified.
423 static void event_ban(SILC_SERVER_REC *server, va_list va)
428 /* PART (LEAVE) command. */
430 static void command_part(const char *data, SILC_SERVER_REC *server,
433 SILC_CHANNEL_REC *chanrec;
435 if (!IS_SILC_SERVER(server) || !server->connected)
436 cmd_return_error(CMDERR_NOT_CONNECTED);
439 if (!IS_SILC_CHANNEL(item))
440 cmd_return_error(CMDERR_NOT_JOINED);
444 chanrec = silc_channel_find(server, data);
446 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
448 signal_emit("message part", 5, server, chanrec->name,
449 server->nick, server->conn->local_entry->username, "");
451 silc_command_exec(server, "LEAVE", chanrec->name);
454 channel_destroy(CHANNEL(chanrec));
457 /* ME local command. */
459 static void command_me(const char *data, SILC_SERVER_REC *server,
462 SILC_CHANNEL_REC *chanrec;
463 char *tmpcmd = "ME", *tmp;
465 unsigned char **argv;
466 uint32 *argv_lens, *argv_types;
469 if (!IS_SILC_SERVER(server) || !server->connected)
470 cmd_return_error(CMDERR_NOT_CONNECTED);
472 if (!IS_SILC_CHANNEL(item))
473 cmd_return_error(CMDERR_NOT_JOINED);
475 /* Now parse all arguments */
476 tmp = g_strconcat(tmpcmd, " ", data, NULL);
477 silc_parse_command_line(tmp, &argv, &argv_lens,
478 &argv_types, &argc, 2);
482 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
484 chanrec = silc_channel_find(server, item->name);
486 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
488 /* Send the action message */
489 silc_client_send_channel_message(silc_client, server->conn,
490 chanrec->entry, NULL,
491 SILC_MESSAGE_FLAG_ACTION,
492 argv[1], argv_lens[1], TRUE);
494 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
495 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION,
496 server->conn->local_entry->nickname, argv[1]);
498 for (i = 0; i < argc; i++)
500 silc_free(argv_lens);
501 silc_free(argv_types);
504 /* ACTION local command. Same as ME but takes the channel as mandatory
507 static void command_action(const char *data, SILC_SERVER_REC *server,
510 SILC_CHANNEL_REC *chanrec;
511 char *tmpcmd = "ME", *tmp;
513 unsigned char **argv;
514 uint32 *argv_lens, *argv_types;
517 if (!IS_SILC_SERVER(server) || !server->connected)
518 cmd_return_error(CMDERR_NOT_CONNECTED);
520 if (!IS_SILC_CHANNEL(item))
521 cmd_return_error(CMDERR_NOT_JOINED);
523 /* Now parse all arguments */
524 tmp = g_strconcat(tmpcmd, " ", data, NULL);
525 silc_parse_command_line(tmp, &argv, &argv_lens,
526 &argv_types, &argc, 3);
530 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
532 chanrec = silc_channel_find(server, argv[1]);
534 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
536 /* Send the action message */
537 silc_client_send_channel_message(silc_client, server->conn,
538 chanrec->entry, NULL,
539 SILC_MESSAGE_FLAG_ACTION,
540 argv[2], argv_lens[2], TRUE);
542 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
543 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION,
544 server->conn->local_entry->nickname, argv[2]);
546 for (i = 0; i < argc; i++)
548 silc_free(argv_lens);
549 silc_free(argv_types);
552 /* NOTICE local command. */
554 static void command_notice(const char *data, SILC_SERVER_REC *server,
557 SILC_CHANNEL_REC *chanrec;
558 char *tmpcmd = "ME", *tmp;
560 unsigned char **argv;
561 uint32 *argv_lens, *argv_types;
564 if (!IS_SILC_SERVER(server) || !server->connected)
565 cmd_return_error(CMDERR_NOT_CONNECTED);
567 if (!IS_SILC_CHANNEL(item))
568 cmd_return_error(CMDERR_NOT_JOINED);
570 /* Now parse all arguments */
571 tmp = g_strconcat(tmpcmd, " ", data, NULL);
572 silc_parse_command_line(tmp, &argv, &argv_lens,
573 &argv_types, &argc, 2);
577 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
579 chanrec = silc_channel_find(server, item->name);
581 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
583 /* Send the action message */
584 silc_client_send_channel_message(silc_client, server->conn,
585 chanrec->entry, NULL,
586 SILC_MESSAGE_FLAG_NOTICE,
587 argv[1], argv_lens[1], TRUE);
589 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
590 MSGLEVEL_NOTICES, SILCTXT_CHANNEL_OWNNOTICE,
591 server->conn->local_entry->nickname, argv[1]);
593 for (i = 0; i < argc; i++)
595 silc_free(argv_lens);
596 silc_free(argv_types);
599 /* AWAY local command. Sends UMODE command that sets the SILC_UMODE_GONE
602 static void command_away(const char *data, SILC_SERVER_REC *server,
607 if (!IS_SILC_SERVER(server) || !server->connected)
608 cmd_return_error(CMDERR_NOT_CONNECTED);
611 /* Remove any possible away message */
612 silc_client_set_away_message(silc_client, server->conn, NULL);
615 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
618 /* Set the away message */
619 silc_client_set_away_message(silc_client, server->conn, (char *)data);
622 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
623 SILCTXT_SET_AWAY, data);
626 signal_emit("away mode changed", 1, server);
628 silc_command_exec(server, "UMODE", set ? "+g" : "-g");
632 int type; /* 1 = msg, 2 = channel */
633 SILC_SERVER_REC *server;
636 /* Key agreement callback that is called after the key agreement protocol
637 has been performed. This is called also if error occured during the
638 key agreement protocol. The `key' is the allocated key material and
639 the caller is responsible of freeing it. The `key' is NULL if error
640 has occured. The application can freely use the `key' to whatever
641 purpose it needs. See lib/silcske/silcske.h for the definition of
642 the SilcSKEKeyMaterial structure. */
644 static void keyagr_completion(SilcClient client,
645 SilcClientConnection conn,
646 SilcClientEntry client_entry,
647 SilcKeyAgreementStatus status,
648 SilcSKEKeyMaterial *key,
651 KeyInternal i = (KeyInternal)context;
654 case SILC_KEY_AGREEMENT_OK:
655 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
656 SILCTXT_KEY_AGREEMENT_OK, client_entry->nickname);
659 /* Set the private key for this client */
660 silc_client_del_private_message_key(client, conn, client_entry);
661 silc_client_add_private_message_key_ske(client, conn, client_entry,
663 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
664 SILCTXT_KEY_AGREEMENT_PRIVMSG,
665 client_entry->nickname);
666 silc_ske_free_key_material(key);
671 case SILC_KEY_AGREEMENT_ERROR:
672 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
673 SILCTXT_KEY_AGREEMENT_ERROR, client_entry->nickname);
676 case SILC_KEY_AGREEMENT_FAILURE:
677 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
678 SILCTXT_KEY_AGREEMENT_FAILURE, client_entry->nickname);
681 case SILC_KEY_AGREEMENT_TIMEOUT:
682 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
683 SILCTXT_KEY_AGREEMENT_TIMEOUT, client_entry->nickname);
694 /* Local command KEY. This command is used to set and unset private
695 keys for channels, set and unset private keys for private messages
696 with remote clients and to send key agreement requests and
697 negotiate the key agreement protocol with remote client. The
698 key agreement is supported only to negotiate private message keys,
699 it currently cannot be used to negotiate private keys for channels,
700 as it is not convenient for that purpose. */
703 SILC_SERVER_REC *server;
708 /* Callback to be called after client information is resolved from the
711 SILC_CLIENT_CMD_FUNC(key_get_clients)
713 KeyGetClients internal = (KeyGetClients)context;
714 signal_emit("command key", 3, internal->data, internal->server,
716 silc_free(internal->data);
720 static void command_key(const char *data, SILC_SERVER_REC *server,
723 SilcClientConnection conn = server->conn;
724 SilcClientEntry client_entry = NULL;
725 SilcChannelEntry channel_entry = NULL;
727 char *nickname = NULL, *serv = NULL, *tmp;
728 int command = 0, port = 0, type = 0;
729 char *hostname = NULL;
730 KeyInternal internal = NULL;
732 unsigned char **argv;
733 uint32 *argv_lens, *argv_types;
735 if (!IS_SILC_SERVER(server) || !server->connected)
736 cmd_return_error(CMDERR_NOT_CONNECTED);
738 /* Now parse all arguments */
739 tmp = g_strconcat("KEY", " ", data, NULL);
740 silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 7);
744 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
745 "set|unset|agreement|negotiate [<arguments>]");
750 if (!strcasecmp(argv[1], "msg"))
752 if (!strcasecmp(argv[1], "channel"))
756 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
757 "set|unset|agreement|negotiate [<arguments>]");
762 if (argv[2][0] == '*') {
765 /* Parse the typed nickname. */
766 if (!silc_parse_nickname(argv[2], &nickname, &serv, &num)) {
767 printformat_module("fe-common/silc", server, NULL,
768 MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
772 /* Find client entry */
773 client_entry = silc_idlist_get_client(silc_client, conn, nickname,
776 KeyGetClients inter = silc_calloc(1, sizeof(*inter));
777 inter->server = server;
778 inter->data = strdup(data);
781 /* Client entry not found, it was requested thus mark this to be
783 silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
785 NULL, silc_client_command_key_get_clients,
793 /* Get channel entry */
796 if (argv[2][0] == '*') {
797 if (!conn->current_channel) {
802 cmd_return_error(CMDERR_NOT_JOINED);
804 name = conn->current_channel->channel_name;
809 channel_entry = silc_client_get_channel(silc_client, conn, name);
810 if (!channel_entry) {
815 cmd_return_error(CMDERR_NOT_JOINED);
820 if (!strcasecmp(argv[3], "set")) {
824 if (type == 1 && client_entry) {
825 /* Set private message key */
827 silc_client_del_private_message_key(silc_client, conn, client_entry);
830 silc_client_add_private_message_key(silc_client, conn, client_entry,
836 silc_client_add_private_message_key(silc_client, conn, client_entry,
842 /* Send the key to the remote client so that it starts using it
844 silc_client_send_private_message_key(silc_client, conn,
846 } else if (type == 2) {
847 /* Set private channel key */
848 char *cipher = NULL, *hmac = NULL;
850 if (!(channel_entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
851 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
852 SILCTXT_CH_PRIVATE_KEY_NOMODE,
853 channel_entry->channel_name);
862 if (!silc_client_add_channel_private_key(silc_client, conn,
867 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
868 SILCTXT_CH_PRIVATE_KEY_ERROR,
869 channel_entry->channel_name);
873 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
874 SILCTXT_CH_PRIVATE_KEY_ADD,
875 channel_entry->channel_name);
883 if (!strcasecmp(argv[3], "unset")) {
886 if (type == 1 && client_entry) {
887 /* Unset private message key */
888 silc_client_del_private_message_key(silc_client, conn, client_entry);
889 } else if (type == 2) {
890 /* Unset channel key(s) */
891 SilcChannelPrivateKey *keys;
896 silc_client_del_channel_private_keys(silc_client, conn,
900 number = atoi(argv[4]);
901 keys = silc_client_list_channel_private_keys(silc_client, conn,
907 if (!number || number > keys_count) {
908 silc_client_free_channel_private_keys(keys, keys_count);
912 silc_client_del_channel_private_key(silc_client, conn, channel_entry,
914 silc_client_free_channel_private_keys(keys, keys_count);
922 if (!strcasecmp(argv[3], "list")) {
926 SilcPrivateMessageKeys keys;
931 keys = silc_client_list_private_message_keys(silc_client, conn,
936 /* list the private message key(s) */
937 if (nickname[0] == '*') {
938 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
939 SILCTXT_PRIVATE_KEY_LIST);
940 for (k = 0; k < keys_count; k++) {
941 memset(buf, 0, sizeof(buf));
942 strncat(buf, " ", 2);
943 len = strlen(keys[k].client_entry->nickname);
944 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
946 for (i = 0; i < 30 - len; i++)
950 len = strlen(keys[k].cipher);
951 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
953 for (i = 0; i < 14 - len; i++)
958 strcat(buf, "<hidden>");
960 strcat(buf, "*generated*");
962 silc_say(silc_client, conn, "%s", buf);
965 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
966 SILCTXT_PRIVATE_KEY_LIST_NICK,
967 client_entry->nickname);
968 for (k = 0; k < keys_count; k++) {
969 if (keys[k].client_entry != client_entry)
972 memset(buf, 0, sizeof(buf));
973 strncat(buf, " ", 2);
974 len = strlen(keys[k].client_entry->nickname);
975 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
977 for (i = 0; i < 30 - len; i++)
981 len = strlen(keys[k].cipher);
982 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
984 for (i = 0; i < 14 - len; i++)
989 strcat(buf, "<hidden>");
991 strcat(buf, "*generated*");
993 silc_say(silc_client, conn, "%s", buf);
997 silc_client_free_private_message_keys(keys, keys_count);
998 } else if (type == 2) {
999 SilcChannelPrivateKey *keys;
1004 keys = silc_client_list_channel_private_keys(silc_client, conn,
1010 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1011 SILCTXT_CH_PRIVATE_KEY_LIST,
1012 channel_entry->channel_name);
1013 for (k = 0; k < keys_count; k++) {
1014 memset(buf, 0, sizeof(buf));
1015 strncat(buf, " ", 2);
1017 len = strlen(keys[k]->cipher->cipher->name);
1018 strncat(buf, keys[k]->cipher->cipher->name, len > 16 ? 16 : len);
1020 for (i = 0; i < 16 - len; i++)
1024 len = strlen(keys[k]->hmac->hmac->name);
1025 strncat(buf, keys[k]->hmac->hmac->name, len > 16 ? 16 : len);
1027 for (i = 0; i < 16 - len; i++)
1031 strcat(buf, "<hidden>");
1033 silc_say(silc_client, conn, "%s", buf);
1036 silc_client_free_channel_private_keys(keys, keys_count);
1042 /* Send command is used to send key agreement */
1043 if (!strcasecmp(argv[3], "agreement")) {
1049 port = atoi(argv[5]);
1051 internal = silc_calloc(1, sizeof(*internal));
1052 internal->type = type;
1053 internal->server = server;
1056 /* Start command is used to start key agreement (after receiving the
1057 key_agreement client operation). */
1058 if (!strcasecmp(argv[3], "negotiate")) {
1064 port = atoi(argv[5]);
1066 internal = silc_calloc(1, sizeof(*internal));
1067 internal->type = type;
1068 internal->server = server;
1072 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
1073 "set|unset|agreement|negotiate [<arguments>]");
1077 if (command == 4 && client_entry) {
1078 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
1079 SILCTXT_KEY_AGREEMENT, argv[2]);
1080 silc_client_send_key_agreement(silc_client, conn, client_entry, hostname,
1081 port, 120, keyagr_completion, internal);
1085 if (command == 5 && client_entry && hostname) {
1086 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
1087 SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
1088 silc_client_perform_key_agreement(silc_client, conn, client_entry,
1089 hostname, port, keyagr_completion,
1096 silc_free(nickname);
1101 void silc_channels_init(void)
1103 signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1104 signal_add("server connected", (SIGNAL_FUNC) sig_connected);
1105 signal_add("server quit", (SIGNAL_FUNC) sig_server_quit);
1107 signal_add("silc event join", (SIGNAL_FUNC) event_join);
1108 signal_add("silc event leave", (SIGNAL_FUNC) event_leave);
1109 signal_add("silc event signoff", (SIGNAL_FUNC) event_signoff);
1110 signal_add("silc event topic", (SIGNAL_FUNC) event_topic);
1111 signal_add("silc event invite", (SIGNAL_FUNC) event_invite);
1112 signal_add("silc event nick", (SIGNAL_FUNC) event_nick);
1113 signal_add("silc event cmode", (SIGNAL_FUNC) event_cmode);
1114 signal_add("silc event cumode", (SIGNAL_FUNC) event_cumode);
1115 signal_add("silc event motd", (SIGNAL_FUNC) event_motd);
1116 signal_add("silc event channel_change", (SIGNAL_FUNC) event_channel_change);
1117 signal_add("silc event server_signoff", (SIGNAL_FUNC) event_server_signoff);
1118 signal_add("silc event kick", (SIGNAL_FUNC) event_kick);
1119 signal_add("silc event kill", (SIGNAL_FUNC) event_kill);
1120 signal_add("silc event ban", (SIGNAL_FUNC) event_ban);
1122 command_bind("part", MODULE_NAME, (SIGNAL_FUNC) command_part);
1123 command_bind("me", MODULE_NAME, (SIGNAL_FUNC) command_me);
1124 command_bind("action", MODULE_NAME, (SIGNAL_FUNC) command_action);
1125 command_bind("notice", MODULE_NAME, (SIGNAL_FUNC) command_notice);
1126 command_bind("away", MODULE_NAME, (SIGNAL_FUNC) command_away);
1127 command_bind("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
1129 silc_nicklist_init();
1132 void silc_channels_deinit(void)
1134 signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1135 signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
1136 signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit);
1138 signal_remove("silc event join", (SIGNAL_FUNC) event_join);
1139 signal_remove("silc event leave", (SIGNAL_FUNC) event_leave);
1140 signal_remove("silc event signoff", (SIGNAL_FUNC) event_signoff);
1141 signal_remove("silc event topic", (SIGNAL_FUNC) event_topic);
1142 signal_remove("silc event invite", (SIGNAL_FUNC) event_invite);
1143 signal_remove("silc event nick", (SIGNAL_FUNC) event_nick);
1144 signal_remove("silc event cmode", (SIGNAL_FUNC) event_cmode);
1145 signal_remove("silc event cumode", (SIGNAL_FUNC) event_cumode);
1146 signal_remove("silc event motd", (SIGNAL_FUNC) event_motd);
1147 signal_remove("silc event channel_change",
1148 (SIGNAL_FUNC) event_channel_change);
1149 signal_remove("silc event server_signoff",
1150 (SIGNAL_FUNC) event_server_signoff);
1151 signal_remove("silc event kick", (SIGNAL_FUNC) event_kick);
1152 signal_remove("silc event kill", (SIGNAL_FUNC) event_kill);
1153 signal_remove("silc event ban", (SIGNAL_FUNC) event_ban);
1155 command_unbind("part", (SIGNAL_FUNC) command_part);
1156 command_unbind("me", (SIGNAL_FUNC) command_me);
1157 command_unbind("action", (SIGNAL_FUNC) command_action);
1158 command_unbind("notice", (SIGNAL_FUNC) command_notice);
1159 command_unbind("away", (SIGNAL_FUNC) command_away);
1160 command_unbind("key", (SIGNAL_FUNC) command_key);
1162 silc_nicklist_deinit();