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,
294 channel->channel_key->cipher->name,
295 channel->hmac->hmac->name);
297 chanrec = silc_channel_find_entry(server, channel);
298 if (chanrec != NULL) {
299 g_free_not_null(chanrec->mode);
300 chanrec->mode = g_strdup(mode == NULL ? "" : mode);
301 signal_emit("channel mode changed", 1, chanrec);
304 printformat_module("fe-common/silc", server, channel->channel_name,
305 MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE,
306 channel->channel_name, mode ? mode : "removed all",
313 * "event cumode". Changed user's mode on channel.
316 static void event_cumode(SILC_SERVER_REC *server, va_list va)
318 SILC_CHANNEL_REC *chanrec;
319 SilcClientEntry client, destclient;
320 SilcChannelEntry channel;
324 client = va_arg(va, SilcClientEntry);
325 mode = va_arg(va, uint32);
326 destclient = va_arg(va, SilcClientEntry);
327 channel = va_arg(va, SilcChannelEntry);
329 modestr = silc_client_chumode(mode);
330 chanrec = silc_channel_find_entry(server, channel);
331 if (chanrec != NULL) {
334 if (destclient == server->conn->local_entry) {
336 (mode & SILC_CHANNEL_UMODE_CHANOP) != 0;
339 nick = silc_nicklist_find(chanrec, destclient);
341 nick->op = (mode & SILC_CHANNEL_UMODE_CHANOP) != 0;
342 signal_emit("nick mode changed", 2, chanrec, nick);
346 printformat_module("fe-common/silc", server, channel->channel_name,
347 MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
348 channel->channel_name, destclient->nickname,
349 modestr ? modestr : "removed all",
352 if (mode & SILC_CHANNEL_UMODE_CHANFO)
353 printformat_module("fe-common/silc",
354 server, channel->channel_name, MSGLEVEL_CRAP,
355 SILCTXT_CHANNEL_FOUNDER,
356 channel->channel_name, destclient->nickname);
362 * "event motd". Received MOTD.
365 static void event_motd(SILC_SERVER_REC *server, va_list va)
367 char *text = va_arg(va, char *);
369 if (!settings_get_bool("skip_motd"))
370 printtext_multiline(server, NULL, MSGLEVEL_CRAP, "%s", text);
374 * "event channel_change". Channel ID has changed.
377 static void event_channel_change(SILC_SERVER_REC *server, va_list va)
383 * "event server_signoff". Server has quit the network.
386 static void event_server_signoff(SILC_SERVER_REC *server, va_list va)
392 * "event kick". Someone was kicked from channel.
395 static void event_kick(SILC_SERVER_REC *server, va_list va)
401 * "event kill". Someone was killed from the network.
404 static void event_kill(SILC_SERVER_REC *server, va_list va)
410 * "event ban". Someone was banned or ban list was modified.
413 static void event_ban(SILC_SERVER_REC *server, va_list va)
418 /* PART (LEAVE) command. */
420 static void command_part(const char *data, SILC_SERVER_REC *server,
423 SILC_CHANNEL_REC *chanrec;
425 if (!IS_SILC_SERVER(server) || !server->connected)
426 cmd_return_error(CMDERR_NOT_CONNECTED);
429 if (!IS_SILC_CHANNEL(item))
430 cmd_return_error(CMDERR_NOT_JOINED);
434 chanrec = silc_channel_find(server, data);
436 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
438 signal_emit("message part", 5, server, chanrec->name,
439 server->nick, server->conn->local_entry->username, "");
441 silc_command_exec(server, "LEAVE", chanrec->name);
444 channel_destroy(CHANNEL(chanrec));
447 /* ME local command. */
449 static void command_me(const char *data, SILC_SERVER_REC *server,
452 SILC_CHANNEL_REC *chanrec;
453 char *tmpcmd = "ME", *tmp;
455 unsigned char **argv;
456 uint32 *argv_lens, *argv_types;
459 if (!IS_SILC_SERVER(server) || !server->connected)
460 cmd_return_error(CMDERR_NOT_CONNECTED);
462 if (!IS_SILC_CHANNEL(item))
463 cmd_return_error(CMDERR_NOT_JOINED);
465 /* Now parse all arguments */
466 tmp = g_strconcat(tmpcmd, " ", data, NULL);
467 silc_parse_command_line(tmp, &argv, &argv_lens,
468 &argv_types, &argc, 2);
472 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
474 chanrec = silc_channel_find(server, item->name);
476 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
478 /* Send the action message */
479 silc_client_send_channel_message(silc_client, server->conn,
480 chanrec->entry, NULL,
481 SILC_MESSAGE_FLAG_ACTION,
482 argv[1], argv_lens[1], TRUE);
484 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
485 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION,
486 server->conn->local_entry->nickname, argv[1]);
488 for (i = 0; i < argc; i++)
490 silc_free(argv_lens);
491 silc_free(argv_types);
494 /* ACTION local command. Same as ME but takes the channel as mandatory
497 static void command_action(const char *data, SILC_SERVER_REC *server,
500 SILC_CHANNEL_REC *chanrec;
501 char *tmpcmd = "ME", *tmp;
503 unsigned char **argv;
504 uint32 *argv_lens, *argv_types;
507 if (!IS_SILC_SERVER(server) || !server->connected)
508 cmd_return_error(CMDERR_NOT_CONNECTED);
510 if (!IS_SILC_CHANNEL(item))
511 cmd_return_error(CMDERR_NOT_JOINED);
513 /* Now parse all arguments */
514 tmp = g_strconcat(tmpcmd, " ", data, NULL);
515 silc_parse_command_line(tmp, &argv, &argv_lens,
516 &argv_types, &argc, 3);
520 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
522 chanrec = silc_channel_find(server, argv[1]);
524 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
526 /* Send the action message */
527 silc_client_send_channel_message(silc_client, server->conn,
528 chanrec->entry, NULL,
529 SILC_MESSAGE_FLAG_ACTION,
530 argv[2], argv_lens[2], TRUE);
532 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
533 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION,
534 server->conn->local_entry->nickname, argv[2]);
536 for (i = 0; i < argc; i++)
538 silc_free(argv_lens);
539 silc_free(argv_types);
542 /* NOTICE local command. */
544 static void command_notice(const char *data, SILC_SERVER_REC *server,
547 SILC_CHANNEL_REC *chanrec;
548 char *tmpcmd = "ME", *tmp;
550 unsigned char **argv;
551 uint32 *argv_lens, *argv_types;
554 if (!IS_SILC_SERVER(server) || !server->connected)
555 cmd_return_error(CMDERR_NOT_CONNECTED);
557 if (!IS_SILC_CHANNEL(item))
558 cmd_return_error(CMDERR_NOT_JOINED);
560 /* Now parse all arguments */
561 tmp = g_strconcat(tmpcmd, " ", data, NULL);
562 silc_parse_command_line(tmp, &argv, &argv_lens,
563 &argv_types, &argc, 2);
567 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
569 chanrec = silc_channel_find(server, item->name);
571 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
573 /* Send the action message */
574 silc_client_send_channel_message(silc_client, server->conn,
575 chanrec->entry, NULL,
576 SILC_MESSAGE_FLAG_NOTICE,
577 argv[1], argv_lens[1], TRUE);
579 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
580 MSGLEVEL_NOTICES, SILCTXT_CHANNEL_OWNNOTICE,
581 server->conn->local_entry->nickname, argv[1]);
583 for (i = 0; i < argc; i++)
585 silc_free(argv_lens);
586 silc_free(argv_types);
589 /* AWAY local command. Sends UMODE command that sets the SILC_UMODE_GONE
592 static void command_away(const char *data, SILC_SERVER_REC *server,
597 if (!IS_SILC_SERVER(server) || !server->connected)
598 cmd_return_error(CMDERR_NOT_CONNECTED);
601 /* Remove any possible away message */
602 silc_client_set_away_message(silc_client, server->conn, NULL);
605 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
608 /* Set the away message */
609 silc_client_set_away_message(silc_client, server->conn, (char *)data);
612 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
613 SILCTXT_SET_AWAY, data);
616 signal_emit("away mode changed", 1, server);
618 silc_command_exec(server, "UMODE", set ? "+g" : "-g");
622 int type; /* 1 = msg, 2 = channel */
623 SILC_SERVER_REC *server;
626 /* Key agreement callback that is called after the key agreement protocol
627 has been performed. This is called also if error occured during the
628 key agreement protocol. The `key' is the allocated key material and
629 the caller is responsible of freeing it. The `key' is NULL if error
630 has occured. The application can freely use the `key' to whatever
631 purpose it needs. See lib/silcske/silcske.h for the definition of
632 the SilcSKEKeyMaterial structure. */
634 static void keyagr_completion(SilcClient client,
635 SilcClientConnection conn,
636 SilcClientEntry client_entry,
637 SilcKeyAgreementStatus status,
638 SilcSKEKeyMaterial *key,
641 KeyInternal i = (KeyInternal)context;
644 case SILC_KEY_AGREEMENT_OK:
645 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
646 SILCTXT_KEY_AGREEMENT_OK, client_entry->nickname);
649 /* Set the private key for this client */
650 silc_client_del_private_message_key(client, conn, client_entry);
651 silc_client_add_private_message_key_ske(client, conn, client_entry,
653 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
654 SILCTXT_KEY_AGREEMENT_PRIVMSG,
655 client_entry->nickname);
656 silc_ske_free_key_material(key);
661 case SILC_KEY_AGREEMENT_ERROR:
662 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
663 SILCTXT_KEY_AGREEMENT_ERROR, client_entry->nickname);
666 case SILC_KEY_AGREEMENT_FAILURE:
667 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
668 SILCTXT_KEY_AGREEMENT_FAILURE, client_entry->nickname);
671 case SILC_KEY_AGREEMENT_TIMEOUT:
672 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
673 SILCTXT_KEY_AGREEMENT_TIMEOUT, client_entry->nickname);
684 /* Local command KEY. This command is used to set and unset private
685 keys for channels, set and unset private keys for private messages
686 with remote clients and to send key agreement requests and
687 negotiate the key agreement protocol with remote client. The
688 key agreement is supported only to negotiate private message keys,
689 it currently cannot be used to negotiate private keys for channels,
690 as it is not convenient for that purpose. */
693 SILC_SERVER_REC *server;
698 /* Callback to be called after client information is resolved from the
701 SILC_CLIENT_CMD_FUNC(key_get_clients)
703 KeyGetClients internal = (KeyGetClients)context;
704 signal_emit("command key", 3, internal->data, internal->server,
706 silc_free(internal->data);
710 static void command_key(const char *data, SILC_SERVER_REC *server,
713 SilcClientConnection conn = server->conn;
714 SilcClientEntry client_entry = NULL;
715 SilcChannelEntry channel_entry = NULL;
717 char *nickname = NULL, *serv = NULL, *tmp;
718 int command = 0, port = 0, type = 0;
719 char *hostname = NULL;
720 KeyInternal internal = NULL;
722 unsigned char **argv;
723 uint32 *argv_lens, *argv_types;
725 if (!IS_SILC_SERVER(server) || !server->connected)
726 cmd_return_error(CMDERR_NOT_CONNECTED);
728 /* Now parse all arguments */
729 tmp = g_strconcat("KEY", " ", data, NULL);
730 silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 7);
734 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
735 "set|unset|agreement|negotiate [<arguments>]");
740 if (!strcasecmp(argv[1], "msg"))
742 if (!strcasecmp(argv[1], "channel"))
746 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
747 "set|unset|agreement|negotiate [<arguments>]");
752 if (argv[2][0] == '*') {
755 /* Parse the typed nickname. */
756 if (!silc_parse_nickname(argv[2], &nickname, &serv, &num)) {
757 printformat_module("fe-common/silc", server, NULL,
758 MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
762 /* Find client entry */
763 client_entry = silc_idlist_get_client(silc_client, conn, nickname,
766 KeyGetClients inter = silc_calloc(1, sizeof(*inter));
767 inter->server = server;
768 inter->data = strdup(data);
771 /* Client entry not found, it was requested thus mark this to be
773 silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
775 NULL, silc_client_command_key_get_clients,
783 /* Get channel entry */
786 if (argv[2][0] == '*') {
787 if (!conn->current_channel) {
792 cmd_return_error(CMDERR_NOT_JOINED);
794 name = conn->current_channel->channel_name;
799 channel_entry = silc_client_get_channel(silc_client, conn, name);
800 if (!channel_entry) {
805 cmd_return_error(CMDERR_NOT_JOINED);
810 if (!strcasecmp(argv[3], "set")) {
814 if (type == 1 && client_entry) {
815 /* Set private message key */
817 silc_client_del_private_message_key(silc_client, conn, client_entry);
820 silc_client_add_private_message_key(silc_client, conn, client_entry,
826 silc_client_add_private_message_key(silc_client, conn, client_entry,
832 /* Send the key to the remote client so that it starts using it
834 silc_client_send_private_message_key(silc_client, conn,
836 } else if (type == 2) {
837 /* Set private channel key */
838 char *cipher = NULL, *hmac = NULL;
840 if (!(channel_entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
841 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
842 SILCTXT_CH_PRIVATE_KEY_NOMODE,
843 channel_entry->channel_name);
852 if (!silc_client_add_channel_private_key(silc_client, conn,
857 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
858 SILCTXT_CH_PRIVATE_KEY_ERROR,
859 channel_entry->channel_name);
863 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
864 SILCTXT_CH_PRIVATE_KEY_ADD,
865 channel_entry->channel_name);
873 if (!strcasecmp(argv[3], "unset")) {
876 if (type == 1 && client_entry) {
877 /* Unset private message key */
878 silc_client_del_private_message_key(silc_client, conn, client_entry);
879 } else if (type == 2) {
880 /* Unset channel key(s) */
881 SilcChannelPrivateKey *keys;
886 silc_client_del_channel_private_keys(silc_client, conn,
890 number = atoi(argv[4]);
891 keys = silc_client_list_channel_private_keys(silc_client, conn,
897 if (!number || number > keys_count) {
898 silc_client_free_channel_private_keys(keys, keys_count);
902 silc_client_del_channel_private_key(silc_client, conn, channel_entry,
904 silc_client_free_channel_private_keys(keys, keys_count);
912 if (!strcasecmp(argv[3], "list")) {
916 SilcPrivateMessageKeys keys;
921 keys = silc_client_list_private_message_keys(silc_client, conn,
926 /* list the private message key(s) */
927 if (nickname[0] == '*') {
928 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
929 SILCTXT_PRIVATE_KEY_LIST);
930 for (k = 0; k < keys_count; k++) {
931 memset(buf, 0, sizeof(buf));
932 strncat(buf, " ", 2);
933 len = strlen(keys[k].client_entry->nickname);
934 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
936 for (i = 0; i < 30 - len; i++)
940 len = strlen(keys[k].cipher);
941 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
943 for (i = 0; i < 14 - len; i++)
948 strcat(buf, "<hidden>");
950 strcat(buf, "*generated*");
952 silc_say(silc_client, conn, "%s", buf);
955 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
956 SILCTXT_PRIVATE_KEY_LIST_NICK,
957 client_entry->nickname);
958 for (k = 0; k < keys_count; k++) {
959 if (keys[k].client_entry != client_entry)
962 memset(buf, 0, sizeof(buf));
963 strncat(buf, " ", 2);
964 len = strlen(keys[k].client_entry->nickname);
965 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
967 for (i = 0; i < 30 - len; i++)
971 len = strlen(keys[k].cipher);
972 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
974 for (i = 0; i < 14 - len; i++)
979 strcat(buf, "<hidden>");
981 strcat(buf, "*generated*");
983 silc_say(silc_client, conn, "%s", buf);
987 silc_client_free_private_message_keys(keys, keys_count);
988 } else if (type == 2) {
989 SilcChannelPrivateKey *keys;
994 keys = silc_client_list_channel_private_keys(silc_client, conn,
1000 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1001 SILCTXT_CH_PRIVATE_KEY_LIST,
1002 channel_entry->channel_name);
1003 for (k = 0; k < keys_count; k++) {
1004 memset(buf, 0, sizeof(buf));
1005 strncat(buf, " ", 2);
1007 len = strlen(keys[k]->cipher->cipher->name);
1008 strncat(buf, keys[k]->cipher->cipher->name, len > 16 ? 16 : len);
1010 for (i = 0; i < 16 - len; i++)
1014 len = strlen(keys[k]->hmac->hmac->name);
1015 strncat(buf, keys[k]->hmac->hmac->name, len > 16 ? 16 : len);
1017 for (i = 0; i < 16 - len; i++)
1021 strcat(buf, "<hidden>");
1023 silc_say(silc_client, conn, "%s", buf);
1026 silc_client_free_channel_private_keys(keys, keys_count);
1032 /* Send command is used to send key agreement */
1033 if (!strcasecmp(argv[3], "agreement")) {
1039 port = atoi(argv[5]);
1041 internal = silc_calloc(1, sizeof(*internal));
1042 internal->type = type;
1043 internal->server = server;
1046 /* Start command is used to start key agreement (after receiving the
1047 key_agreement client operation). */
1048 if (!strcasecmp(argv[3], "negotiate")) {
1054 port = atoi(argv[5]);
1056 internal = silc_calloc(1, sizeof(*internal));
1057 internal->type = type;
1058 internal->server = server;
1062 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
1063 "set|unset|agreement|negotiate [<arguments>]");
1067 if (command == 4 && client_entry) {
1068 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
1069 SILCTXT_KEY_AGREEMENT, argv[2]);
1070 silc_client_send_key_agreement(silc_client, conn, client_entry, hostname,
1071 port, 120, keyagr_completion, internal);
1075 if (command == 5 && client_entry && hostname) {
1076 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
1077 SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
1078 silc_client_perform_key_agreement(silc_client, conn, client_entry,
1079 hostname, port, keyagr_completion,
1086 silc_free(nickname);
1091 void silc_channels_init(void)
1093 signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1094 signal_add("server connected", (SIGNAL_FUNC) sig_connected);
1095 signal_add("server quit", (SIGNAL_FUNC) sig_server_quit);
1097 signal_add("silc event join", (SIGNAL_FUNC) event_join);
1098 signal_add("silc event leave", (SIGNAL_FUNC) event_leave);
1099 signal_add("silc event signoff", (SIGNAL_FUNC) event_signoff);
1100 signal_add("silc event topic", (SIGNAL_FUNC) event_topic);
1101 signal_add("silc event invite", (SIGNAL_FUNC) event_invite);
1102 signal_add("silc event nick", (SIGNAL_FUNC) event_nick);
1103 signal_add("silc event cmode", (SIGNAL_FUNC) event_cmode);
1104 signal_add("silc event cumode", (SIGNAL_FUNC) event_cumode);
1105 signal_add("silc event motd", (SIGNAL_FUNC) event_motd);
1106 signal_add("silc event channel_change", (SIGNAL_FUNC) event_channel_change);
1107 signal_add("silc event server_signoff", (SIGNAL_FUNC) event_server_signoff);
1108 signal_add("silc event kick", (SIGNAL_FUNC) event_kick);
1109 signal_add("silc event kill", (SIGNAL_FUNC) event_kill);
1110 signal_add("silc event ban", (SIGNAL_FUNC) event_ban);
1112 command_bind("part", MODULE_NAME, (SIGNAL_FUNC) command_part);
1113 command_bind("me", MODULE_NAME, (SIGNAL_FUNC) command_me);
1114 command_bind("action", MODULE_NAME, (SIGNAL_FUNC) command_action);
1115 command_bind("notice", MODULE_NAME, (SIGNAL_FUNC) command_notice);
1116 command_bind("away", MODULE_NAME, (SIGNAL_FUNC) command_away);
1117 command_bind("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
1119 silc_nicklist_init();
1122 void silc_channels_deinit(void)
1124 signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1125 signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
1126 signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit);
1128 signal_remove("silc event join", (SIGNAL_FUNC) event_join);
1129 signal_remove("silc event leave", (SIGNAL_FUNC) event_leave);
1130 signal_remove("silc event signoff", (SIGNAL_FUNC) event_signoff);
1131 signal_remove("silc event topic", (SIGNAL_FUNC) event_topic);
1132 signal_remove("silc event invite", (SIGNAL_FUNC) event_invite);
1133 signal_remove("silc event nick", (SIGNAL_FUNC) event_nick);
1134 signal_remove("silc event cmode", (SIGNAL_FUNC) event_cmode);
1135 signal_remove("silc event cumode", (SIGNAL_FUNC) event_cumode);
1136 signal_remove("silc event motd", (SIGNAL_FUNC) event_motd);
1137 signal_remove("silc event channel_change",
1138 (SIGNAL_FUNC) event_channel_change);
1139 signal_remove("silc event server_signoff",
1140 (SIGNAL_FUNC) event_server_signoff);
1141 signal_remove("silc event kick", (SIGNAL_FUNC) event_kick);
1142 signal_remove("silc event kill", (SIGNAL_FUNC) event_kill);
1143 signal_remove("silc event ban", (SIGNAL_FUNC) event_ban);
1145 command_unbind("part", (SIGNAL_FUNC) command_part);
1146 command_unbind("me", (SIGNAL_FUNC) command_me);
1147 command_unbind("action", (SIGNAL_FUNC) command_action);
1148 command_unbind("notice", (SIGNAL_FUNC) command_notice);
1149 command_unbind("away", (SIGNAL_FUNC) command_away);
1150 command_unbind("key", (SIGNAL_FUNC) command_key);
1152 silc_nicklist_deinit();