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)
389 /* Nothing interesting to do */
393 * "event server_signoff". Server has quit the network.
396 static void event_server_signoff(SILC_SERVER_REC *server, va_list va)
398 SilcClientEntry *clients;
399 uint32 clients_count;
402 (void)va_arg(va, void *);
403 clients = va_arg(va, SilcClientEntry *);
404 clients_count = va_arg(va, uint32);
406 for (i = 0; i < clients_count; i++)
407 signal_emit("message quit", 4, server, clients[i]->nickname,
408 clients[i]->username ? clients[i]->username : "",
413 * "event kick". Someone was kicked from channel.
416 static void event_kick(SILC_SERVER_REC *server, va_list va)
418 SilcClientConnection conn = server->conn;
419 SilcClientEntry client_entry;
420 SilcChannelEntry channel_entry;
423 client_entry = va_arg(va, SilcClientEntry);
424 tmp = va_arg(va, char *);
425 channel_entry = va_arg(va, SilcChannelEntry);
427 if (client_entry == conn->local_entry) {
428 printformat_module("fe-common/silc", server, channel_entry->channel_name,
429 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KICKED_YOU,
430 channel_entry->channel_name, tmp ? tmp : "");
432 printformat_module("fe-common/silc", server, channel_entry->channel_name,
433 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KICKED,
434 client_entry->nickname,
435 channel_entry->channel_name, tmp ? tmp : "");
440 * "event kill". Someone was killed from the network.
443 static void event_kill(SILC_SERVER_REC *server, va_list va)
445 SilcClientConnection conn = server->conn;
446 SilcClientEntry client_entry;
449 client_entry = va_arg(va, SilcClientEntry);
450 tmp = va_arg(va, char *);
452 if (client_entry == conn->local_entry) {
453 printformat_module("fe-common/silc", server, NULL,
454 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU,
457 printformat_module("fe-common/silc", server, NULL,
458 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED,
459 client_entry->nickname,
464 /* PART (LEAVE) command. */
466 static void command_part(const char *data, SILC_SERVER_REC *server,
469 SILC_CHANNEL_REC *chanrec;
471 if (!IS_SILC_SERVER(server) || !server->connected)
472 cmd_return_error(CMDERR_NOT_CONNECTED);
475 if (!IS_SILC_CHANNEL(item))
476 cmd_return_error(CMDERR_NOT_JOINED);
480 chanrec = silc_channel_find(server, data);
482 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
484 signal_emit("message part", 5, server, chanrec->name,
485 server->nick, server->conn->local_entry->username, "");
487 silc_command_exec(server, "LEAVE", chanrec->name);
490 channel_destroy(CHANNEL(chanrec));
493 /* ME local command. */
495 static void command_me(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, 2);
518 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
520 chanrec = silc_channel_find(server, item->name);
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[1], argv_lens[1], 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[1]);
534 for (i = 0; i < argc; i++)
536 silc_free(argv_lens);
537 silc_free(argv_types);
540 /* ACTION local command. Same as ME but takes the channel as mandatory
543 static void command_action(const char *data, SILC_SERVER_REC *server,
546 SILC_CHANNEL_REC *chanrec;
547 char *tmpcmd = "ME", *tmp;
549 unsigned char **argv;
550 uint32 *argv_lens, *argv_types;
553 if (!IS_SILC_SERVER(server) || !server->connected)
554 cmd_return_error(CMDERR_NOT_CONNECTED);
556 if (!IS_SILC_CHANNEL(item))
557 cmd_return_error(CMDERR_NOT_JOINED);
559 /* Now parse all arguments */
560 tmp = g_strconcat(tmpcmd, " ", data, NULL);
561 silc_parse_command_line(tmp, &argv, &argv_lens,
562 &argv_types, &argc, 3);
566 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
568 chanrec = silc_channel_find(server, argv[1]);
570 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
572 /* Send the action message */
573 silc_client_send_channel_message(silc_client, server->conn,
574 chanrec->entry, NULL,
575 SILC_MESSAGE_FLAG_ACTION,
576 argv[2], argv_lens[2], TRUE);
578 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
579 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION,
580 server->conn->local_entry->nickname, argv[2]);
582 for (i = 0; i < argc; i++)
584 silc_free(argv_lens);
585 silc_free(argv_types);
588 /* NOTICE local command. */
590 static void command_notice(const char *data, SILC_SERVER_REC *server,
593 SILC_CHANNEL_REC *chanrec;
594 char *tmpcmd = "ME", *tmp;
596 unsigned char **argv;
597 uint32 *argv_lens, *argv_types;
600 if (!IS_SILC_SERVER(server) || !server->connected)
601 cmd_return_error(CMDERR_NOT_CONNECTED);
603 if (!IS_SILC_CHANNEL(item))
604 cmd_return_error(CMDERR_NOT_JOINED);
606 /* Now parse all arguments */
607 tmp = g_strconcat(tmpcmd, " ", data, NULL);
608 silc_parse_command_line(tmp, &argv, &argv_lens,
609 &argv_types, &argc, 2);
613 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
615 chanrec = silc_channel_find(server, item->name);
617 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
619 /* Send the action message */
620 silc_client_send_channel_message(silc_client, server->conn,
621 chanrec->entry, NULL,
622 SILC_MESSAGE_FLAG_NOTICE,
623 argv[1], argv_lens[1], TRUE);
625 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
626 MSGLEVEL_NOTICES, SILCTXT_CHANNEL_OWNNOTICE,
627 server->conn->local_entry->nickname, argv[1]);
629 for (i = 0; i < argc; i++)
631 silc_free(argv_lens);
632 silc_free(argv_types);
635 /* AWAY local command. Sends UMODE command that sets the SILC_UMODE_GONE
638 static void command_away(const char *data, SILC_SERVER_REC *server,
643 if (!IS_SILC_SERVER(server) || !server->connected)
644 cmd_return_error(CMDERR_NOT_CONNECTED);
647 /* Remove any possible away message */
648 silc_client_set_away_message(silc_client, server->conn, NULL);
651 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
654 /* Set the away message */
655 silc_client_set_away_message(silc_client, server->conn, (char *)data);
658 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
659 SILCTXT_SET_AWAY, data);
662 signal_emit("away mode changed", 1, server);
664 silc_command_exec(server, "UMODE", set ? "+g" : "-g");
668 int type; /* 1 = msg, 2 = channel */
669 SILC_SERVER_REC *server;
672 /* Key agreement callback that is called after the key agreement protocol
673 has been performed. This is called also if error occured during the
674 key agreement protocol. The `key' is the allocated key material and
675 the caller is responsible of freeing it. The `key' is NULL if error
676 has occured. The application can freely use the `key' to whatever
677 purpose it needs. See lib/silcske/silcske.h for the definition of
678 the SilcSKEKeyMaterial structure. */
680 static void keyagr_completion(SilcClient client,
681 SilcClientConnection conn,
682 SilcClientEntry client_entry,
683 SilcKeyAgreementStatus status,
684 SilcSKEKeyMaterial *key,
687 KeyInternal i = (KeyInternal)context;
690 case SILC_KEY_AGREEMENT_OK:
691 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
692 SILCTXT_KEY_AGREEMENT_OK, client_entry->nickname);
695 /* Set the private key for this client */
696 silc_client_del_private_message_key(client, conn, client_entry);
697 silc_client_add_private_message_key_ske(client, conn, client_entry,
699 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
700 SILCTXT_KEY_AGREEMENT_PRIVMSG,
701 client_entry->nickname);
702 silc_ske_free_key_material(key);
707 case SILC_KEY_AGREEMENT_ERROR:
708 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
709 SILCTXT_KEY_AGREEMENT_ERROR, client_entry->nickname);
712 case SILC_KEY_AGREEMENT_FAILURE:
713 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
714 SILCTXT_KEY_AGREEMENT_FAILURE, client_entry->nickname);
717 case SILC_KEY_AGREEMENT_TIMEOUT:
718 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
719 SILCTXT_KEY_AGREEMENT_TIMEOUT, client_entry->nickname);
730 /* Local command KEY. This command is used to set and unset private
731 keys for channels, set and unset private keys for private messages
732 with remote clients and to send key agreement requests and
733 negotiate the key agreement protocol with remote client. The
734 key agreement is supported only to negotiate private message keys,
735 it currently cannot be used to negotiate private keys for channels,
736 as it is not convenient for that purpose. */
739 SILC_SERVER_REC *server;
744 /* Callback to be called after client information is resolved from the
747 SILC_CLIENT_CMD_FUNC(key_get_clients)
749 KeyGetClients internal = (KeyGetClients)context;
750 signal_emit("command key", 3, internal->data, internal->server,
752 silc_free(internal->data);
756 static void command_key(const char *data, SILC_SERVER_REC *server,
759 SilcClientConnection conn = server->conn;
760 SilcClientEntry client_entry = NULL;
761 SilcChannelEntry channel_entry = NULL;
763 char *nickname = NULL, *serv = NULL, *tmp;
764 int command = 0, port = 0, type = 0;
765 char *hostname = NULL;
766 KeyInternal internal = NULL;
768 unsigned char **argv;
769 uint32 *argv_lens, *argv_types;
771 if (!IS_SILC_SERVER(server) || !server->connected)
772 cmd_return_error(CMDERR_NOT_CONNECTED);
774 /* Now parse all arguments */
775 tmp = g_strconcat("KEY", " ", data, NULL);
776 silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 7);
780 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
781 "set|unset|agreement|negotiate [<arguments>]");
786 if (!strcasecmp(argv[1], "msg"))
788 if (!strcasecmp(argv[1], "channel"))
792 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
793 "set|unset|agreement|negotiate [<arguments>]");
798 if (argv[2][0] == '*') {
801 /* Parse the typed nickname. */
802 if (!silc_parse_nickname(argv[2], &nickname, &serv, &num)) {
803 printformat_module("fe-common/silc", server, NULL,
804 MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
808 /* Find client entry */
809 client_entry = silc_idlist_get_client(silc_client, conn, nickname,
812 KeyGetClients inter = silc_calloc(1, sizeof(*inter));
813 inter->server = server;
814 inter->data = strdup(data);
817 /* Client entry not found, it was requested thus mark this to be
819 silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
821 NULL, silc_client_command_key_get_clients,
829 /* Get channel entry */
832 if (argv[2][0] == '*') {
833 if (!conn->current_channel) {
838 cmd_return_error(CMDERR_NOT_JOINED);
840 name = conn->current_channel->channel_name;
845 channel_entry = silc_client_get_channel(silc_client, conn, name);
846 if (!channel_entry) {
851 cmd_return_error(CMDERR_NOT_JOINED);
856 if (!strcasecmp(argv[3], "set")) {
860 if (type == 1 && client_entry) {
861 /* Set private message key */
863 silc_client_del_private_message_key(silc_client, conn, client_entry);
866 silc_client_add_private_message_key(silc_client, conn, client_entry,
872 silc_client_add_private_message_key(silc_client, conn, client_entry,
878 /* Send the key to the remote client so that it starts using it
880 silc_client_send_private_message_key(silc_client, conn,
882 } else if (type == 2) {
883 /* Set private channel key */
884 char *cipher = NULL, *hmac = NULL;
886 if (!(channel_entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
887 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
888 SILCTXT_CH_PRIVATE_KEY_NOMODE,
889 channel_entry->channel_name);
898 if (!silc_client_add_channel_private_key(silc_client, conn,
903 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
904 SILCTXT_CH_PRIVATE_KEY_ERROR,
905 channel_entry->channel_name);
909 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
910 SILCTXT_CH_PRIVATE_KEY_ADD,
911 channel_entry->channel_name);
919 if (!strcasecmp(argv[3], "unset")) {
922 if (type == 1 && client_entry) {
923 /* Unset private message key */
924 silc_client_del_private_message_key(silc_client, conn, client_entry);
925 } else if (type == 2) {
926 /* Unset channel key(s) */
927 SilcChannelPrivateKey *keys;
932 silc_client_del_channel_private_keys(silc_client, conn,
936 number = atoi(argv[4]);
937 keys = silc_client_list_channel_private_keys(silc_client, conn,
943 if (!number || number > keys_count) {
944 silc_client_free_channel_private_keys(keys, keys_count);
948 silc_client_del_channel_private_key(silc_client, conn, channel_entry,
950 silc_client_free_channel_private_keys(keys, keys_count);
958 if (!strcasecmp(argv[3], "list")) {
962 SilcPrivateMessageKeys keys;
967 keys = silc_client_list_private_message_keys(silc_client, conn,
972 /* list the private message key(s) */
973 if (nickname[0] == '*') {
974 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
975 SILCTXT_PRIVATE_KEY_LIST);
976 for (k = 0; k < keys_count; k++) {
977 memset(buf, 0, sizeof(buf));
978 strncat(buf, " ", 2);
979 len = strlen(keys[k].client_entry->nickname);
980 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
982 for (i = 0; i < 30 - len; i++)
986 len = strlen(keys[k].cipher);
987 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
989 for (i = 0; i < 14 - len; i++)
994 strcat(buf, "<hidden>");
996 strcat(buf, "*generated*");
998 silc_say(silc_client, conn, "%s", buf);
1001 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1002 SILCTXT_PRIVATE_KEY_LIST_NICK,
1003 client_entry->nickname);
1004 for (k = 0; k < keys_count; k++) {
1005 if (keys[k].client_entry != client_entry)
1008 memset(buf, 0, sizeof(buf));
1009 strncat(buf, " ", 2);
1010 len = strlen(keys[k].client_entry->nickname);
1011 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
1013 for (i = 0; i < 30 - len; i++)
1017 len = strlen(keys[k].cipher);
1018 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
1020 for (i = 0; i < 14 - len; i++)
1025 strcat(buf, "<hidden>");
1027 strcat(buf, "*generated*");
1029 silc_say(silc_client, conn, "%s", buf);
1033 silc_client_free_private_message_keys(keys, keys_count);
1034 } else if (type == 2) {
1035 SilcChannelPrivateKey *keys;
1040 keys = silc_client_list_channel_private_keys(silc_client, conn,
1046 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1047 SILCTXT_CH_PRIVATE_KEY_LIST,
1048 channel_entry->channel_name);
1049 for (k = 0; k < keys_count; k++) {
1050 memset(buf, 0, sizeof(buf));
1051 strncat(buf, " ", 2);
1053 len = strlen(keys[k]->cipher->cipher->name);
1054 strncat(buf, keys[k]->cipher->cipher->name, len > 16 ? 16 : len);
1056 for (i = 0; i < 16 - len; i++)
1060 len = strlen(keys[k]->hmac->hmac->name);
1061 strncat(buf, keys[k]->hmac->hmac->name, len > 16 ? 16 : len);
1063 for (i = 0; i < 16 - len; i++)
1067 strcat(buf, "<hidden>");
1069 silc_say(silc_client, conn, "%s", buf);
1072 silc_client_free_channel_private_keys(keys, keys_count);
1078 /* Send command is used to send key agreement */
1079 if (!strcasecmp(argv[3], "agreement")) {
1085 port = atoi(argv[5]);
1087 internal = silc_calloc(1, sizeof(*internal));
1088 internal->type = type;
1089 internal->server = server;
1092 /* Start command is used to start key agreement (after receiving the
1093 key_agreement client operation). */
1094 if (!strcasecmp(argv[3], "negotiate")) {
1100 port = atoi(argv[5]);
1102 internal = silc_calloc(1, sizeof(*internal));
1103 internal->type = type;
1104 internal->server = server;
1108 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
1109 "set|unset|agreement|negotiate [<arguments>]");
1113 if (command == 4 && client_entry) {
1114 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
1115 SILCTXT_KEY_AGREEMENT, argv[2]);
1116 silc_client_send_key_agreement(silc_client, conn, client_entry, hostname,
1117 port, 120, keyagr_completion, internal);
1121 if (command == 5 && client_entry && hostname) {
1122 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
1123 SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
1124 silc_client_perform_key_agreement(silc_client, conn, client_entry,
1125 hostname, port, keyagr_completion,
1132 silc_free(nickname);
1137 void silc_channels_init(void)
1139 signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1140 signal_add("server connected", (SIGNAL_FUNC) sig_connected);
1141 signal_add("server quit", (SIGNAL_FUNC) sig_server_quit);
1143 signal_add("silc event join", (SIGNAL_FUNC) event_join);
1144 signal_add("silc event leave", (SIGNAL_FUNC) event_leave);
1145 signal_add("silc event signoff", (SIGNAL_FUNC) event_signoff);
1146 signal_add("silc event topic", (SIGNAL_FUNC) event_topic);
1147 signal_add("silc event invite", (SIGNAL_FUNC) event_invite);
1148 signal_add("silc event nick", (SIGNAL_FUNC) event_nick);
1149 signal_add("silc event cmode", (SIGNAL_FUNC) event_cmode);
1150 signal_add("silc event cumode", (SIGNAL_FUNC) event_cumode);
1151 signal_add("silc event motd", (SIGNAL_FUNC) event_motd);
1152 signal_add("silc event channel_change", (SIGNAL_FUNC) event_channel_change);
1153 signal_add("silc event server_signoff", (SIGNAL_FUNC) event_server_signoff);
1154 signal_add("silc event kick", (SIGNAL_FUNC) event_kick);
1155 signal_add("silc event kill", (SIGNAL_FUNC) event_kill);
1157 command_bind("part", MODULE_NAME, (SIGNAL_FUNC) command_part);
1158 command_bind("me", MODULE_NAME, (SIGNAL_FUNC) command_me);
1159 command_bind("action", MODULE_NAME, (SIGNAL_FUNC) command_action);
1160 command_bind("notice", MODULE_NAME, (SIGNAL_FUNC) command_notice);
1161 command_bind("away", MODULE_NAME, (SIGNAL_FUNC) command_away);
1162 command_bind("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
1164 silc_nicklist_init();
1167 void silc_channels_deinit(void)
1169 signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1170 signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
1171 signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit);
1173 signal_remove("silc event join", (SIGNAL_FUNC) event_join);
1174 signal_remove("silc event leave", (SIGNAL_FUNC) event_leave);
1175 signal_remove("silc event signoff", (SIGNAL_FUNC) event_signoff);
1176 signal_remove("silc event topic", (SIGNAL_FUNC) event_topic);
1177 signal_remove("silc event invite", (SIGNAL_FUNC) event_invite);
1178 signal_remove("silc event nick", (SIGNAL_FUNC) event_nick);
1179 signal_remove("silc event cmode", (SIGNAL_FUNC) event_cmode);
1180 signal_remove("silc event cumode", (SIGNAL_FUNC) event_cumode);
1181 signal_remove("silc event motd", (SIGNAL_FUNC) event_motd);
1182 signal_remove("silc event channel_change",
1183 (SIGNAL_FUNC) event_channel_change);
1184 signal_remove("silc event server_signoff",
1185 (SIGNAL_FUNC) event_server_signoff);
1186 signal_remove("silc event kick", (SIGNAL_FUNC) event_kick);
1187 signal_remove("silc event kill", (SIGNAL_FUNC) event_kill);
1189 command_unbind("part", (SIGNAL_FUNC) command_part);
1190 command_unbind("me", (SIGNAL_FUNC) command_me);
1191 command_unbind("action", (SIGNAL_FUNC) command_action);
1192 command_unbind("notice", (SIGNAL_FUNC) command_notice);
1193 command_unbind("away", (SIGNAL_FUNC) command_away);
1194 command_unbind("key", (SIGNAL_FUNC) command_key);
1196 silc_nicklist_deinit();