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);
92 static void sig_connected(SILC_SERVER_REC *server)
94 if (IS_SILC_SERVER(server))
95 server->channels_join = (void *) silc_channels_join;
98 /* "server quit" signal from the core to indicate that QUIT command
101 static void sig_server_quit(SILC_SERVER_REC *server, const char *msg)
103 if (IS_SILC_SERVER(server) && server->conn && server->conn->sock)
104 silc_command_exec(server, "QUIT", msg);
108 * "event join". Joined to a channel.
111 SILC_CHANNEL_REC *silc_channel_find_entry(SILC_SERVER_REC *server,
112 SilcChannelEntry entry)
116 g_return_val_if_fail(IS_SILC_SERVER(server), NULL);
118 for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
119 SILC_CHANNEL_REC *rec = tmp->data;
121 if (rec->entry == entry)
128 static void event_join(SILC_SERVER_REC *server, va_list va)
130 SILC_CHANNEL_REC *chanrec;
131 SILC_NICK_REC *nickrec;
132 SilcClientEntry client;
133 SilcChannelEntry channel;
135 client = va_arg(va, SilcClientEntry);
136 channel = va_arg(va, SilcChannelEntry);
138 if (client == server->conn->local_entry) {
139 /* You joined to channel */
140 chanrec = silc_channel_find(server, channel->channel_name);
141 if (chanrec != NULL && !chanrec->joined)
142 chanrec->entry = channel;
144 chanrec = silc_channel_find_entry(server, channel);
145 if (chanrec != NULL) {
146 SilcChannelUser user;
148 silc_list_start(chanrec->entry->clients);
149 while ((user = silc_list_get(chanrec->entry->clients)) != NULL)
150 if (user->client == client) {
151 nickrec = silc_nicklist_insert(chanrec, user, TRUE);
157 signal_emit("message join", 4, server, channel->channel_name,
159 client->username == NULL ? "" : client->username);
163 * "event leave". Left a channel.
166 static void event_leave(SILC_SERVER_REC *server, va_list va)
168 SILC_CHANNEL_REC *chanrec;
169 SILC_NICK_REC *nickrec;
170 SilcClientEntry client;
171 SilcChannelEntry channel;
173 client = va_arg(va, SilcClientEntry);
174 channel = va_arg(va, SilcChannelEntry);
176 signal_emit("message part", 5, server, channel->channel_name,
177 client->nickname, client->username ? client->username : "",
180 chanrec = silc_channel_find_entry(server, channel);
181 if (chanrec != NULL) {
182 nickrec = silc_nicklist_find(chanrec, client);
184 nicklist_remove(CHANNEL(chanrec), NICK(nickrec));
189 * "event signoff". Left the network.
192 static void event_signoff(SILC_SERVER_REC *server, va_list va)
194 SilcClientEntry client;
198 client = va_arg(va, SilcClientEntry);
199 message = va_arg(va, char *);
201 signal_emit("message quit", 4, server, client->nickname,
202 client->username ? client->username : "",
203 message ? message : "");
205 nicks = nicklist_get_same_unique(SERVER(server), client);
206 for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) {
207 CHANNEL_REC *channel = tmp->data;
208 NICK_REC *nickrec = tmp->next->data;
210 nicklist_remove(channel, nickrec);
215 * "event topic". Changed topic.
218 static void event_topic(SILC_SERVER_REC *server, va_list va)
220 SILC_CHANNEL_REC *chanrec;
221 SilcClientEntry client;
222 SilcChannelEntry channel;
225 client = va_arg(va, SilcClientEntry);
226 topic = va_arg(va, char *);
227 channel = va_arg(va, SilcChannelEntry);
229 chanrec = silc_channel_find_entry(server, channel);
230 if (chanrec != NULL) {
231 g_free_not_null(chanrec->topic);
232 chanrec->topic = *topic == '\0' ? NULL : g_strdup(topic);
233 signal_emit("channel topic changed", 1, chanrec);
236 signal_emit("message topic", 5, server, channel->channel_name,
237 topic, client->nickname, client->username);
241 * "event invite". Invited or modified invite list.
244 static void event_invite(SILC_SERVER_REC *server, va_list va)
246 SilcClientEntry client;
247 SilcChannelEntry channel;
249 client = va_arg(va, SilcClientEntry);
250 channel = va_arg(va, SilcChannelEntry);
252 signal_emit("message invite", 4, server, channel->channel_name,
253 client->nickname, client->username);
257 * "event nick". Changed nickname.
260 static void event_nick(SILC_SERVER_REC *server, va_list va)
262 SilcClientEntry oldclient, newclient;
264 oldclient = va_arg(va, SilcClientEntry);
265 newclient = va_arg(va, SilcClientEntry);
267 nicklist_rename_unique(SERVER(server),
268 oldclient, oldclient->nickname,
269 newclient, newclient->nickname);
271 signal_emit("message nick", 4, server, newclient->nickname,
272 oldclient->nickname, newclient->username);
276 * "event cmode". Changed channel mode.
279 static void event_cmode(SILC_SERVER_REC *server, va_list va)
281 SILC_CHANNEL_REC *chanrec;
282 SilcClientEntry client;
283 SilcChannelEntry channel;
287 client = va_arg(va, SilcClientEntry);
288 modei = va_arg(va, uint32);
289 (void)va_arg(va, char *);
290 (void)va_arg(va, char *);
291 channel = va_arg(va, SilcChannelEntry);
293 mode = silc_client_chmode(modei, channel);
295 chanrec = silc_channel_find_entry(server, channel);
296 if (chanrec != NULL) {
297 g_free_not_null(chanrec->mode);
298 chanrec->mode = g_strdup(mode == NULL ? "" : mode);
299 signal_emit("channel mode changed", 1, chanrec);
302 printformat_module("fe-common/silc", server, channel->channel_name,
303 MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE,
304 channel->channel_name, mode ? mode : "removed all",
311 * "event cumode". Changed user's mode on channel.
314 static void event_cumode(SILC_SERVER_REC *server, va_list va)
316 SILC_CHANNEL_REC *chanrec;
317 SilcClientEntry client, destclient;
318 SilcChannelEntry channel;
322 client = va_arg(va, SilcClientEntry);
323 mode = va_arg(va, uint32);
324 destclient = va_arg(va, SilcClientEntry);
325 channel = va_arg(va, SilcChannelEntry);
327 modestr = silc_client_chumode(mode);
328 chanrec = silc_channel_find_entry(server, channel);
329 if (chanrec != NULL) {
332 if (destclient == server->conn->local_entry) {
334 (mode & SILC_CHANNEL_UMODE_CHANOP) != 0;
337 nick = silc_nicklist_find(chanrec, destclient);
339 nick->op = (mode & SILC_CHANNEL_UMODE_CHANOP) != 0;
340 signal_emit("nick mode changed", 2, chanrec, nick);
344 printformat_module("fe-common/silc", server, channel->channel_name,
345 MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
346 channel->channel_name, destclient->nickname,
347 modestr ? modestr : "removed all",
350 if (mode & SILC_CHANNEL_UMODE_CHANFO)
351 printformat_module("fe-common/silc",
352 server, channel->channel_name, MSGLEVEL_CRAP,
353 SILCTXT_CHANNEL_FOUNDER,
354 channel->channel_name, destclient->nickname);
360 * "event motd". Received MOTD.
363 static void event_motd(SILC_SERVER_REC *server, va_list va)
365 char *text = va_arg(va, char *);
367 if (!settings_get_bool("skip_motd"))
368 printtext_multiline(server, NULL, MSGLEVEL_CRAP, "%s", text);
372 * "event channel_change". Channel ID has changed.
375 static void event_channel_change(SILC_SERVER_REC *server, va_list va)
381 * "event server_signoff". Server has quit the network.
384 static void event_server_signoff(SILC_SERVER_REC *server, va_list va)
390 * "event kick". Someone was kicked from channel.
393 static void event_kick(SILC_SERVER_REC *server, va_list va)
399 * "event kill". Someone was killed from the network.
402 static void event_kill(SILC_SERVER_REC *server, va_list va)
408 * "event ban". Someone was banned or ban list was modified.
411 static void event_ban(SILC_SERVER_REC *server, va_list va)
416 /* PART (LEAVE) command. */
418 static void command_part(const char *data, SILC_SERVER_REC *server,
421 SILC_CHANNEL_REC *chanrec;
423 if (!IS_SILC_SERVER(server) || !server->connected)
424 cmd_return_error(CMDERR_NOT_CONNECTED);
427 if (!IS_SILC_CHANNEL(item))
428 cmd_return_error(CMDERR_NOT_JOINED);
432 chanrec = silc_channel_find(server, data);
434 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
436 signal_emit("message part", 5, server, chanrec->name,
437 server->nick, server->conn->local_entry->username, "");
439 silc_command_exec(server, "LEAVE", chanrec->name);
442 channel_destroy(CHANNEL(chanrec));
445 /* ME local command. */
447 static void command_me(const char *data, SILC_SERVER_REC *server,
450 SILC_CHANNEL_REC *chanrec;
451 char *tmpcmd = "ME", *tmp;
453 unsigned char **argv;
454 uint32 *argv_lens, *argv_types;
457 if (!IS_SILC_SERVER(server) || !server->connected)
458 cmd_return_error(CMDERR_NOT_CONNECTED);
460 if (!IS_SILC_CHANNEL(item))
461 cmd_return_error(CMDERR_NOT_JOINED);
463 /* Now parse all arguments */
464 tmp = g_strconcat(tmpcmd, " ", data, NULL);
465 silc_parse_command_line(tmp, &argv, &argv_lens,
466 &argv_types, &argc, 2);
470 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
472 chanrec = silc_channel_find(server, item->name);
474 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
476 /* Send the action message */
477 silc_client_send_channel_message(silc_client, server->conn,
478 chanrec->entry, NULL,
479 SILC_MESSAGE_FLAG_ACTION,
480 argv[1], argv_lens[1], TRUE);
482 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
483 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION,
484 server->conn->local_entry->nickname, argv[1]);
486 for (i = 0; i < argc; i++)
488 silc_free(argv_lens);
489 silc_free(argv_types);
492 /* ACTION local command. Same as ME but takes the channel as mandatory
495 static void command_action(const char *data, SILC_SERVER_REC *server,
498 SILC_CHANNEL_REC *chanrec;
499 char *tmpcmd = "ME", *tmp;
501 unsigned char **argv;
502 uint32 *argv_lens, *argv_types;
505 if (!IS_SILC_SERVER(server) || !server->connected)
506 cmd_return_error(CMDERR_NOT_CONNECTED);
508 if (!IS_SILC_CHANNEL(item))
509 cmd_return_error(CMDERR_NOT_JOINED);
511 /* Now parse all arguments */
512 tmp = g_strconcat(tmpcmd, " ", data, NULL);
513 silc_parse_command_line(tmp, &argv, &argv_lens,
514 &argv_types, &argc, 3);
518 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
520 chanrec = silc_channel_find(server, argv[1]);
522 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
524 /* Send the action message */
525 silc_client_send_channel_message(silc_client, server->conn,
526 chanrec->entry, NULL,
527 SILC_MESSAGE_FLAG_ACTION,
528 argv[2], argv_lens[2], TRUE);
530 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
531 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION,
532 server->conn->local_entry->nickname, argv[2]);
534 for (i = 0; i < argc; i++)
536 silc_free(argv_lens);
537 silc_free(argv_types);
540 /* NOTICE local command. */
542 static void command_notice(const char *data, SILC_SERVER_REC *server,
545 SILC_CHANNEL_REC *chanrec;
546 char *tmpcmd = "ME", *tmp;
548 unsigned char **argv;
549 uint32 *argv_lens, *argv_types;
552 if (!IS_SILC_SERVER(server) || !server->connected)
553 cmd_return_error(CMDERR_NOT_CONNECTED);
555 if (!IS_SILC_CHANNEL(item))
556 cmd_return_error(CMDERR_NOT_JOINED);
558 /* Now parse all arguments */
559 tmp = g_strconcat(tmpcmd, " ", data, NULL);
560 silc_parse_command_line(tmp, &argv, &argv_lens,
561 &argv_types, &argc, 2);
565 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
567 chanrec = silc_channel_find(server, item->name);
569 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
571 /* Send the action message */
572 silc_client_send_channel_message(silc_client, server->conn,
573 chanrec->entry, NULL,
574 SILC_MESSAGE_FLAG_NOTICE,
575 argv[1], argv_lens[1], TRUE);
577 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
578 MSGLEVEL_NOTICES, SILCTXT_CHANNEL_OWNNOTICE,
579 server->conn->local_entry->nickname, argv[1]);
581 for (i = 0; i < argc; i++)
583 silc_free(argv_lens);
584 silc_free(argv_types);
587 /* AWAY local command. Sends UMODE command that sets the SILC_UMODE_GONE
590 static void command_away(const char *data, SILC_SERVER_REC *server,
595 if (!IS_SILC_SERVER(server) || !server->connected)
596 cmd_return_error(CMDERR_NOT_CONNECTED);
599 /* Remove any possible away message */
600 silc_client_set_away_message(silc_client, server->conn, NULL);
603 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
606 /* Set the away message */
607 silc_client_set_away_message(silc_client, server->conn, (char *)data);
610 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
611 SILCTXT_SET_AWAY, data);
614 signal_emit("away mode changed", 1, server);
616 silc_command_exec(server, "UMODE", set ? "+g" : "-g");
620 int type; /* 1 = msg, 2 = channel */
621 SILC_SERVER_REC *server;
624 /* Key agreement callback that is called after the key agreement protocol
625 has been performed. This is called also if error occured during the
626 key agreement protocol. The `key' is the allocated key material and
627 the caller is responsible of freeing it. The `key' is NULL if error
628 has occured. The application can freely use the `key' to whatever
629 purpose it needs. See lib/silcske/silcske.h for the definition of
630 the SilcSKEKeyMaterial structure. */
632 static void keyagr_completion(SilcClient client,
633 SilcClientConnection conn,
634 SilcClientEntry client_entry,
635 SilcKeyAgreementStatus status,
636 SilcSKEKeyMaterial *key,
639 KeyInternal i = (KeyInternal)context;
642 case SILC_KEY_AGREEMENT_OK:
643 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
644 SILCTXT_KEY_AGREEMENT_OK, client_entry->nickname);
647 /* Set the private key for this client */
648 silc_client_del_private_message_key(client, conn, client_entry);
649 silc_client_add_private_message_key_ske(client, conn, client_entry,
651 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
652 SILCTXT_KEY_AGREEMENT_PRIVMSG,
653 client_entry->nickname);
654 silc_ske_free_key_material(key);
659 case SILC_KEY_AGREEMENT_ERROR:
660 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
661 SILCTXT_KEY_AGREEMENT_ERROR, client_entry->nickname);
664 case SILC_KEY_AGREEMENT_FAILURE:
665 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
666 SILCTXT_KEY_AGREEMENT_FAILURE, client_entry->nickname);
669 case SILC_KEY_AGREEMENT_TIMEOUT:
670 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
671 SILCTXT_KEY_AGREEMENT_TIMEOUT, client_entry->nickname);
682 /* Local command KEY. This command is used to set and unset private
683 keys for channels, set and unset private keys for private messages
684 with remote clients and to send key agreement requests and
685 negotiate the key agreement protocol with remote client. The
686 key agreement is supported only to negotiate private message keys,
687 it currently cannot be used to negotiate private keys for channels,
688 as it is not convenient for that purpose. */
691 SILC_SERVER_REC *server;
696 /* Callback to be called after client information is resolved from the
699 SILC_CLIENT_CMD_FUNC(key_get_clients)
701 KeyGetClients internal = (KeyGetClients)context;
702 signal_emit("command key", 3, internal->data, internal->server,
704 silc_free(internal->data);
708 static void command_key(const char *data, SILC_SERVER_REC *server,
711 SilcClientConnection conn = server->conn;
712 SilcClientEntry client_entry = NULL;
713 SilcChannelEntry channel_entry = NULL;
715 char *nickname = NULL, *serv = NULL, *tmp;
716 int command = 0, port = 0, type = 0;
717 char *hostname = NULL;
718 KeyInternal internal = NULL;
720 unsigned char **argv;
721 uint32 *argv_lens, *argv_types;
723 if (!IS_SILC_SERVER(server) || !server->connected)
724 cmd_return_error(CMDERR_NOT_CONNECTED);
726 /* Now parse all arguments */
727 tmp = g_strconcat("KEY", " ", data, NULL);
728 silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 7);
732 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
733 "set|unset|agreement|negotiate [<arguments>]");
738 if (!strcasecmp(argv[1], "msg"))
740 if (!strcasecmp(argv[1], "channel"))
744 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
745 "set|unset|agreement|negotiate [<arguments>]");
750 if (argv[2][0] == '*') {
753 /* Parse the typed nickname. */
754 if (!silc_parse_nickname(argv[2], &nickname, &serv, &num)) {
755 printformat_module("fe-common/silc", server, NULL,
756 MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
760 /* Find client entry */
761 client_entry = silc_idlist_get_client(silc_client, conn, nickname,
764 KeyGetClients inter = silc_calloc(1, sizeof(*inter));
765 inter->server = server;
766 inter->data = strdup(data);
769 /* Client entry not found, it was requested thus mark this to be
771 silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
773 NULL, silc_client_command_key_get_clients,
781 /* Get channel entry */
784 if (argv[2][0] == '*') {
785 if (!conn->current_channel) {
790 cmd_return_error(CMDERR_NOT_JOINED);
792 name = conn->current_channel->channel_name;
797 channel_entry = silc_client_get_channel(silc_client, conn, name);
798 if (!channel_entry) {
803 cmd_return_error(CMDERR_NOT_JOINED);
808 if (!strcasecmp(argv[3], "set")) {
812 if (type == 1 && client_entry) {
813 /* Set private message key */
815 silc_client_del_private_message_key(silc_client, conn, client_entry);
818 silc_client_add_private_message_key(silc_client, conn, client_entry,
824 silc_client_add_private_message_key(silc_client, conn, client_entry,
830 /* Send the key to the remote client so that it starts using it
832 silc_client_send_private_message_key(silc_client, conn,
834 } else if (type == 2) {
835 /* Set private channel key */
836 char *cipher = NULL, *hmac = NULL;
838 if (!(channel_entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
839 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
840 SILCTXT_CH_PRIVATE_KEY_NOMODE,
841 channel_entry->channel_name);
850 if (!silc_client_add_channel_private_key(silc_client, conn,
855 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
856 SILCTXT_CH_PRIVATE_KEY_ERROR,
857 channel_entry->channel_name);
861 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
862 SILCTXT_CH_PRIVATE_KEY_ADD,
863 channel_entry->channel_name);
871 if (!strcasecmp(argv[3], "unset")) {
874 if (type == 1 && client_entry) {
875 /* Unset private message key */
876 silc_client_del_private_message_key(silc_client, conn, client_entry);
877 } else if (type == 2) {
878 /* Unset channel key(s) */
879 SilcChannelPrivateKey *keys;
884 silc_client_del_channel_private_keys(silc_client, conn,
888 number = atoi(argv[4]);
889 keys = silc_client_list_channel_private_keys(silc_client, conn,
895 if (!number || number > keys_count) {
896 silc_client_free_channel_private_keys(keys, keys_count);
900 silc_client_del_channel_private_key(silc_client, conn, channel_entry,
902 silc_client_free_channel_private_keys(keys, keys_count);
910 if (!strcasecmp(argv[3], "list")) {
914 SilcPrivateMessageKeys keys;
919 keys = silc_client_list_private_message_keys(silc_client, conn,
924 /* list the private message key(s) */
925 if (nickname[0] == '*') {
926 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
927 SILCTXT_PRIVATE_KEY_LIST);
928 for (k = 0; k < keys_count; k++) {
929 memset(buf, 0, sizeof(buf));
930 strncat(buf, " ", 2);
931 len = strlen(keys[k].client_entry->nickname);
932 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
934 for (i = 0; i < 30 - len; i++)
938 len = strlen(keys[k].cipher);
939 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
941 for (i = 0; i < 14 - len; i++)
946 strcat(buf, "<hidden>");
948 strcat(buf, "*generated*");
950 silc_say(silc_client, conn, "%s", buf);
953 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
954 SILCTXT_PRIVATE_KEY_LIST_NICK,
955 client_entry->nickname);
956 for (k = 0; k < keys_count; k++) {
957 if (keys[k].client_entry != client_entry)
960 memset(buf, 0, sizeof(buf));
961 strncat(buf, " ", 2);
962 len = strlen(keys[k].client_entry->nickname);
963 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
965 for (i = 0; i < 30 - len; i++)
969 len = strlen(keys[k].cipher);
970 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
972 for (i = 0; i < 14 - len; i++)
977 strcat(buf, "<hidden>");
979 strcat(buf, "*generated*");
981 silc_say(silc_client, conn, "%s", buf);
985 silc_client_free_private_message_keys(keys, keys_count);
986 } else if (type == 2) {
987 SilcChannelPrivateKey *keys;
992 keys = silc_client_list_channel_private_keys(silc_client, conn,
998 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
999 SILCTXT_CH_PRIVATE_KEY_LIST,
1000 channel_entry->channel_name);
1001 for (k = 0; k < keys_count; k++) {
1002 memset(buf, 0, sizeof(buf));
1003 strncat(buf, " ", 2);
1005 len = strlen(keys[k]->cipher->cipher->name);
1006 strncat(buf, keys[k]->cipher->cipher->name, len > 16 ? 16 : len);
1008 for (i = 0; i < 16 - len; i++)
1012 len = strlen(keys[k]->hmac->hmac->name);
1013 strncat(buf, keys[k]->hmac->hmac->name, len > 16 ? 16 : len);
1015 for (i = 0; i < 16 - len; i++)
1019 strcat(buf, "<hidden>");
1021 silc_say(silc_client, conn, "%s", buf);
1024 silc_client_free_channel_private_keys(keys, keys_count);
1030 /* Send command is used to send key agreement */
1031 if (!strcasecmp(argv[3], "agreement")) {
1037 port = atoi(argv[5]);
1039 internal = silc_calloc(1, sizeof(*internal));
1040 internal->type = type;
1041 internal->server = server;
1044 /* Start command is used to start key agreement (after receiving the
1045 key_agreement client operation). */
1046 if (!strcasecmp(argv[3], "negotiate")) {
1052 port = atoi(argv[5]);
1054 internal = silc_calloc(1, sizeof(*internal));
1055 internal->type = type;
1056 internal->server = server;
1060 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
1061 "set|unset|agreement|negotiate [<arguments>]");
1065 if (command == 4 && client_entry) {
1066 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
1067 SILCTXT_KEY_AGREEMENT, argv[2]);
1068 silc_client_send_key_agreement(silc_client, conn, client_entry, hostname,
1069 port, 120, keyagr_completion, internal);
1073 if (command == 5 && client_entry && hostname) {
1074 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
1075 SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
1076 silc_client_perform_key_agreement(silc_client, conn, client_entry,
1077 hostname, port, keyagr_completion,
1084 silc_free(nickname);
1089 void silc_channels_init(void)
1091 signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1092 signal_add("server connected", (SIGNAL_FUNC) sig_connected);
1093 signal_add("server quit", (SIGNAL_FUNC) sig_server_quit);
1095 signal_add("silc event join", (SIGNAL_FUNC) event_join);
1096 signal_add("silc event leave", (SIGNAL_FUNC) event_leave);
1097 signal_add("silc event signoff", (SIGNAL_FUNC) event_signoff);
1098 signal_add("silc event topic", (SIGNAL_FUNC) event_topic);
1099 signal_add("silc event invite", (SIGNAL_FUNC) event_invite);
1100 signal_add("silc event nick", (SIGNAL_FUNC) event_nick);
1101 signal_add("silc event cmode", (SIGNAL_FUNC) event_cmode);
1102 signal_add("silc event cumode", (SIGNAL_FUNC) event_cumode);
1103 signal_add("silc event motd", (SIGNAL_FUNC) event_motd);
1104 signal_add("silc event channel_change", (SIGNAL_FUNC) event_channel_change);
1105 signal_add("silc event server_signoff", (SIGNAL_FUNC) event_server_signoff);
1106 signal_add("silc event kick", (SIGNAL_FUNC) event_kick);
1107 signal_add("silc event kill", (SIGNAL_FUNC) event_kill);
1108 signal_add("silc event ban", (SIGNAL_FUNC) event_ban);
1110 command_bind("part", MODULE_NAME, (SIGNAL_FUNC) command_part);
1111 command_bind("me", MODULE_NAME, (SIGNAL_FUNC) command_me);
1112 command_bind("action", MODULE_NAME, (SIGNAL_FUNC) command_action);
1113 command_bind("notice", MODULE_NAME, (SIGNAL_FUNC) command_notice);
1114 command_bind("away", MODULE_NAME, (SIGNAL_FUNC) command_away);
1115 command_bind("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
1117 silc_nicklist_init();
1120 void silc_channels_deinit(void)
1122 signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1123 signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
1124 signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit);
1126 signal_remove("silc event join", (SIGNAL_FUNC) event_join);
1127 signal_remove("silc event leave", (SIGNAL_FUNC) event_leave);
1128 signal_remove("silc event signoff", (SIGNAL_FUNC) event_signoff);
1129 signal_remove("silc event topic", (SIGNAL_FUNC) event_topic);
1130 signal_remove("silc event invite", (SIGNAL_FUNC) event_invite);
1131 signal_remove("silc event nick", (SIGNAL_FUNC) event_nick);
1132 signal_remove("silc event cmode", (SIGNAL_FUNC) event_cmode);
1133 signal_remove("silc event cumode", (SIGNAL_FUNC) event_cumode);
1134 signal_remove("silc event motd", (SIGNAL_FUNC) event_motd);
1135 signal_remove("silc event channel_change",
1136 (SIGNAL_FUNC) event_channel_change);
1137 signal_remove("silc event server_signoff",
1138 (SIGNAL_FUNC) event_server_signoff);
1139 signal_remove("silc event kick", (SIGNAL_FUNC) event_kick);
1140 signal_remove("silc event kill", (SIGNAL_FUNC) event_kill);
1141 signal_remove("silc event ban", (SIGNAL_FUNC) event_ban);
1143 command_unbind("part", (SIGNAL_FUNC) command_part);
1144 command_unbind("me", (SIGNAL_FUNC) command_me);
1145 command_unbind("action", (SIGNAL_FUNC) command_action);
1146 command_unbind("notice", (SIGNAL_FUNC) command_notice);
1147 command_unbind("away", (SIGNAL_FUNC) command_away);
1148 command_unbind("key", (SIGNAL_FUNC) command_key);
1150 silc_nicklist_deinit();