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 nick->founder = (mode & SILC_CHANNEL_UMODE_CHANFO) != 0;
353 signal_emit("nick mode changed", 2, chanrec, nick);
357 printformat_module("fe-common/silc", server, channel->channel_name,
358 MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
359 channel->channel_name, destclient->nickname,
360 modestr ? modestr : "removed all",
363 if (mode & SILC_CHANNEL_UMODE_CHANFO)
364 printformat_module("fe-common/silc",
365 server, channel->channel_name, MSGLEVEL_CRAP,
366 SILCTXT_CHANNEL_FOUNDER,
367 channel->channel_name, destclient->nickname);
373 * "event motd". Received MOTD.
376 static void event_motd(SILC_SERVER_REC *server, va_list va)
378 char *text = va_arg(va, char *);
380 if (!settings_get_bool("skip_motd"))
381 printtext_multiline(server, NULL, MSGLEVEL_CRAP, "%s", text);
385 * "event channel_change". Channel ID has changed.
388 static void event_channel_change(SILC_SERVER_REC *server, va_list va)
390 /* Nothing interesting to do */
394 * "event server_signoff". Server has quit the network.
397 static void event_server_signoff(SILC_SERVER_REC *server, va_list va)
399 SilcClientEntry *clients;
400 uint32 clients_count;
403 (void)va_arg(va, void *);
404 clients = va_arg(va, SilcClientEntry *);
405 clients_count = va_arg(va, uint32);
407 for (i = 0; i < clients_count; i++)
408 signal_emit("message quit", 4, server, clients[i]->nickname,
409 clients[i]->username ? clients[i]->username : "",
414 * "event kick". Someone was kicked from channel.
417 static void event_kick(SILC_SERVER_REC *server, va_list va)
419 SilcClientConnection conn = server->conn;
420 SilcClientEntry client_entry;
421 SilcChannelEntry channel_entry;
424 client_entry = va_arg(va, SilcClientEntry);
425 tmp = va_arg(va, char *);
426 channel_entry = va_arg(va, SilcChannelEntry);
428 if (client_entry == conn->local_entry) {
429 printformat_module("fe-common/silc", server, channel_entry->channel_name,
430 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KICKED_YOU,
431 channel_entry->channel_name, tmp ? tmp : "");
433 printformat_module("fe-common/silc", server, channel_entry->channel_name,
434 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KICKED,
435 client_entry->nickname,
436 channel_entry->channel_name, tmp ? tmp : "");
441 * "event kill". Someone was killed from the network.
444 static void event_kill(SILC_SERVER_REC *server, va_list va)
446 SilcClientConnection conn = server->conn;
447 SilcClientEntry client_entry;
450 client_entry = va_arg(va, SilcClientEntry);
451 tmp = va_arg(va, char *);
453 if (client_entry == conn->local_entry) {
454 printformat_module("fe-common/silc", server, NULL,
455 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU,
458 printformat_module("fe-common/silc", server, NULL,
459 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED,
460 client_entry->nickname,
465 /* PART (LEAVE) command. */
467 static void command_part(const char *data, SILC_SERVER_REC *server,
470 SILC_CHANNEL_REC *chanrec;
472 if (!IS_SILC_SERVER(server) || !server->connected)
473 cmd_return_error(CMDERR_NOT_CONNECTED);
476 if (!IS_SILC_CHANNEL(item))
477 cmd_return_error(CMDERR_NOT_JOINED);
481 chanrec = silc_channel_find(server, data);
483 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
485 signal_emit("message part", 5, server, chanrec->name,
486 server->nick, server->conn->local_entry->username, "");
488 silc_command_exec(server, "LEAVE", chanrec->name);
491 channel_destroy(CHANNEL(chanrec));
494 /* ME local command. */
496 static void command_me(const char *data, SILC_SERVER_REC *server,
499 SILC_CHANNEL_REC *chanrec;
500 char *tmpcmd = "ME", *tmp;
502 unsigned char **argv;
503 uint32 *argv_lens, *argv_types;
506 if (!IS_SILC_SERVER(server) || !server->connected)
507 cmd_return_error(CMDERR_NOT_CONNECTED);
509 if (!IS_SILC_CHANNEL(item))
510 cmd_return_error(CMDERR_NOT_JOINED);
512 /* Now parse all arguments */
513 tmp = g_strconcat(tmpcmd, " ", data, NULL);
514 silc_parse_command_line(tmp, &argv, &argv_lens,
515 &argv_types, &argc, 2);
519 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
521 chanrec = silc_channel_find(server, item->name);
523 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
525 /* Send the action message */
526 silc_client_send_channel_message(silc_client, server->conn,
527 chanrec->entry, NULL,
528 SILC_MESSAGE_FLAG_ACTION,
529 argv[1], argv_lens[1], TRUE);
531 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
532 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION,
533 server->conn->local_entry->nickname, argv[1]);
535 for (i = 0; i < argc; i++)
537 silc_free(argv_lens);
538 silc_free(argv_types);
541 /* ACTION local command. Same as ME but takes the channel as mandatory
544 static void command_action(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, 3);
567 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
569 chanrec = silc_channel_find(server, argv[1]);
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_ACTION,
577 argv[2], argv_lens[2], TRUE);
579 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
580 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION,
581 server->conn->local_entry->nickname, argv[2]);
583 for (i = 0; i < argc; i++)
585 silc_free(argv_lens);
586 silc_free(argv_types);
589 /* NOTICE local command. */
591 static void command_notice(const char *data, SILC_SERVER_REC *server,
594 SILC_CHANNEL_REC *chanrec;
595 char *tmpcmd = "ME", *tmp;
597 unsigned char **argv;
598 uint32 *argv_lens, *argv_types;
601 if (!IS_SILC_SERVER(server) || !server->connected)
602 cmd_return_error(CMDERR_NOT_CONNECTED);
604 if (!IS_SILC_CHANNEL(item))
605 cmd_return_error(CMDERR_NOT_JOINED);
607 /* Now parse all arguments */
608 tmp = g_strconcat(tmpcmd, " ", data, NULL);
609 silc_parse_command_line(tmp, &argv, &argv_lens,
610 &argv_types, &argc, 2);
614 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
616 chanrec = silc_channel_find(server, item->name);
618 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
620 /* Send the action message */
621 silc_client_send_channel_message(silc_client, server->conn,
622 chanrec->entry, NULL,
623 SILC_MESSAGE_FLAG_NOTICE,
624 argv[1], argv_lens[1], TRUE);
626 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
627 MSGLEVEL_NOTICES, SILCTXT_CHANNEL_OWNNOTICE,
628 server->conn->local_entry->nickname, argv[1]);
630 for (i = 0; i < argc; i++)
632 silc_free(argv_lens);
633 silc_free(argv_types);
636 /* AWAY local command. Sends UMODE command that sets the SILC_UMODE_GONE
639 static void command_away(const char *data, SILC_SERVER_REC *server,
644 if (!IS_SILC_SERVER(server) || !server->connected)
645 cmd_return_error(CMDERR_NOT_CONNECTED);
648 /* Remove any possible away message */
649 silc_client_set_away_message(silc_client, server->conn, NULL);
652 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
655 /* Set the away message */
656 silc_client_set_away_message(silc_client, server->conn, (char *)data);
659 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
660 SILCTXT_SET_AWAY, data);
663 signal_emit("away mode changed", 1, server);
665 silc_command_exec(server, "UMODE", set ? "+g" : "-g");
669 int type; /* 1 = msg, 2 = channel */
670 SILC_SERVER_REC *server;
673 /* Key agreement callback that is called after the key agreement protocol
674 has been performed. This is called also if error occured during the
675 key agreement protocol. The `key' is the allocated key material and
676 the caller is responsible of freeing it. The `key' is NULL if error
677 has occured. The application can freely use the `key' to whatever
678 purpose it needs. See lib/silcske/silcske.h for the definition of
679 the SilcSKEKeyMaterial structure. */
681 static void keyagr_completion(SilcClient client,
682 SilcClientConnection conn,
683 SilcClientEntry client_entry,
684 SilcKeyAgreementStatus status,
685 SilcSKEKeyMaterial *key,
688 KeyInternal i = (KeyInternal)context;
691 case SILC_KEY_AGREEMENT_OK:
692 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
693 SILCTXT_KEY_AGREEMENT_OK, client_entry->nickname);
696 /* Set the private key for this client */
697 silc_client_del_private_message_key(client, conn, client_entry);
698 silc_client_add_private_message_key_ske(client, conn, client_entry,
700 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
701 SILCTXT_KEY_AGREEMENT_PRIVMSG,
702 client_entry->nickname);
703 silc_ske_free_key_material(key);
708 case SILC_KEY_AGREEMENT_ERROR:
709 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
710 SILCTXT_KEY_AGREEMENT_ERROR, client_entry->nickname);
713 case SILC_KEY_AGREEMENT_FAILURE:
714 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
715 SILCTXT_KEY_AGREEMENT_FAILURE, client_entry->nickname);
718 case SILC_KEY_AGREEMENT_TIMEOUT:
719 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
720 SILCTXT_KEY_AGREEMENT_TIMEOUT, client_entry->nickname);
731 /* Local command KEY. This command is used to set and unset private
732 keys for channels, set and unset private keys for private messages
733 with remote clients and to send key agreement requests and
734 negotiate the key agreement protocol with remote client. The
735 key agreement is supported only to negotiate private message keys,
736 it currently cannot be used to negotiate private keys for channels,
737 as it is not convenient for that purpose. */
740 SILC_SERVER_REC *server;
745 /* Callback to be called after client information is resolved from the
748 SILC_CLIENT_CMD_FUNC(key_get_clients)
750 KeyGetClients internal = (KeyGetClients)context;
751 signal_emit("command key", 3, internal->data, internal->server,
753 silc_free(internal->data);
757 static void command_key(const char *data, SILC_SERVER_REC *server,
760 SilcClientConnection conn = server->conn;
761 SilcClientEntry client_entry = NULL;
762 SilcChannelEntry channel_entry = NULL;
764 char *nickname = NULL, *serv = NULL, *tmp;
765 int command = 0, port = 0, type = 0;
766 char *hostname = NULL;
767 KeyInternal internal = NULL;
769 unsigned char **argv;
770 uint32 *argv_lens, *argv_types;
772 if (!IS_SILC_SERVER(server) || !server->connected)
773 cmd_return_error(CMDERR_NOT_CONNECTED);
775 /* Now parse all arguments */
776 tmp = g_strconcat("KEY", " ", data, NULL);
777 silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 7);
781 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
782 "set|unset|agreement|negotiate [<arguments>]");
787 if (!strcasecmp(argv[1], "msg"))
789 if (!strcasecmp(argv[1], "channel"))
793 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
794 "set|unset|agreement|negotiate [<arguments>]");
799 if (argv[2][0] == '*') {
802 /* Parse the typed nickname. */
803 if (!silc_parse_nickname(argv[2], &nickname, &serv, &num)) {
804 printformat_module("fe-common/silc", server, NULL,
805 MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
809 /* Find client entry */
810 client_entry = silc_idlist_get_client(silc_client, conn, nickname,
813 KeyGetClients inter = silc_calloc(1, sizeof(*inter));
814 inter->server = server;
815 inter->data = strdup(data);
818 /* Client entry not found, it was requested thus mark this to be
820 silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
822 NULL, silc_client_command_key_get_clients,
830 /* Get channel entry */
833 if (argv[2][0] == '*') {
834 if (!conn->current_channel) {
839 cmd_return_error(CMDERR_NOT_JOINED);
841 name = conn->current_channel->channel_name;
846 channel_entry = silc_client_get_channel(silc_client, conn, name);
847 if (!channel_entry) {
852 cmd_return_error(CMDERR_NOT_JOINED);
857 if (!strcasecmp(argv[3], "set")) {
861 if (type == 1 && client_entry) {
862 /* Set private message key */
864 silc_client_del_private_message_key(silc_client, conn, client_entry);
867 silc_client_add_private_message_key(silc_client, conn, client_entry,
873 silc_client_add_private_message_key(silc_client, conn, client_entry,
879 /* Send the key to the remote client so that it starts using it
881 silc_client_send_private_message_key(silc_client, conn,
883 } else if (type == 2) {
884 /* Set private channel key */
885 char *cipher = NULL, *hmac = NULL;
887 if (!(channel_entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
888 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
889 SILCTXT_CH_PRIVATE_KEY_NOMODE,
890 channel_entry->channel_name);
899 if (!silc_client_add_channel_private_key(silc_client, conn,
904 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
905 SILCTXT_CH_PRIVATE_KEY_ERROR,
906 channel_entry->channel_name);
910 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
911 SILCTXT_CH_PRIVATE_KEY_ADD,
912 channel_entry->channel_name);
920 if (!strcasecmp(argv[3], "unset")) {
923 if (type == 1 && client_entry) {
924 /* Unset private message key */
925 silc_client_del_private_message_key(silc_client, conn, client_entry);
926 } else if (type == 2) {
927 /* Unset channel key(s) */
928 SilcChannelPrivateKey *keys;
933 silc_client_del_channel_private_keys(silc_client, conn,
937 number = atoi(argv[4]);
938 keys = silc_client_list_channel_private_keys(silc_client, conn,
944 if (!number || number > keys_count) {
945 silc_client_free_channel_private_keys(keys, keys_count);
949 silc_client_del_channel_private_key(silc_client, conn, channel_entry,
951 silc_client_free_channel_private_keys(keys, keys_count);
959 if (!strcasecmp(argv[3], "list")) {
963 SilcPrivateMessageKeys keys;
968 keys = silc_client_list_private_message_keys(silc_client, conn,
973 /* list the private message key(s) */
974 if (nickname[0] == '*') {
975 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
976 SILCTXT_PRIVATE_KEY_LIST);
977 for (k = 0; k < keys_count; k++) {
978 memset(buf, 0, sizeof(buf));
979 strncat(buf, " ", 2);
980 len = strlen(keys[k].client_entry->nickname);
981 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
983 for (i = 0; i < 30 - len; i++)
987 len = strlen(keys[k].cipher);
988 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
990 for (i = 0; i < 14 - len; i++)
995 strcat(buf, "<hidden>");
997 strcat(buf, "*generated*");
999 silc_say(silc_client, conn, "%s", buf);
1002 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1003 SILCTXT_PRIVATE_KEY_LIST_NICK,
1004 client_entry->nickname);
1005 for (k = 0; k < keys_count; k++) {
1006 if (keys[k].client_entry != client_entry)
1009 memset(buf, 0, sizeof(buf));
1010 strncat(buf, " ", 2);
1011 len = strlen(keys[k].client_entry->nickname);
1012 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
1014 for (i = 0; i < 30 - len; i++)
1018 len = strlen(keys[k].cipher);
1019 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
1021 for (i = 0; i < 14 - len; i++)
1026 strcat(buf, "<hidden>");
1028 strcat(buf, "*generated*");
1030 silc_say(silc_client, conn, "%s", buf);
1034 silc_client_free_private_message_keys(keys, keys_count);
1035 } else if (type == 2) {
1036 SilcChannelPrivateKey *keys;
1041 keys = silc_client_list_channel_private_keys(silc_client, conn,
1047 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1048 SILCTXT_CH_PRIVATE_KEY_LIST,
1049 channel_entry->channel_name);
1050 for (k = 0; k < keys_count; k++) {
1051 memset(buf, 0, sizeof(buf));
1052 strncat(buf, " ", 2);
1054 len = strlen(keys[k]->cipher->cipher->name);
1055 strncat(buf, keys[k]->cipher->cipher->name, len > 16 ? 16 : len);
1057 for (i = 0; i < 16 - len; i++)
1061 len = strlen(keys[k]->hmac->hmac->name);
1062 strncat(buf, keys[k]->hmac->hmac->name, len > 16 ? 16 : len);
1064 for (i = 0; i < 16 - len; i++)
1068 strcat(buf, "<hidden>");
1070 silc_say(silc_client, conn, "%s", buf);
1073 silc_client_free_channel_private_keys(keys, keys_count);
1079 /* Send command is used to send key agreement */
1080 if (!strcasecmp(argv[3], "agreement")) {
1086 port = atoi(argv[5]);
1088 internal = silc_calloc(1, sizeof(*internal));
1089 internal->type = type;
1090 internal->server = server;
1093 /* Start command is used to start key agreement (after receiving the
1094 key_agreement client operation). */
1095 if (!strcasecmp(argv[3], "negotiate")) {
1101 port = atoi(argv[5]);
1103 internal = silc_calloc(1, sizeof(*internal));
1104 internal->type = type;
1105 internal->server = server;
1109 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
1110 "set|unset|agreement|negotiate [<arguments>]");
1114 if (command == 4 && client_entry) {
1115 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
1116 SILCTXT_KEY_AGREEMENT, argv[2]);
1117 silc_client_send_key_agreement(silc_client, conn, client_entry, hostname,
1118 port, 120, keyagr_completion, internal);
1122 if (command == 5 && client_entry && hostname) {
1123 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
1124 SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
1125 silc_client_perform_key_agreement(silc_client, conn, client_entry,
1126 hostname, port, keyagr_completion,
1133 silc_free(nickname);
1138 void silc_channels_init(void)
1140 signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1141 signal_add("server connected", (SIGNAL_FUNC) sig_connected);
1142 signal_add("server quit", (SIGNAL_FUNC) sig_server_quit);
1144 signal_add("silc event join", (SIGNAL_FUNC) event_join);
1145 signal_add("silc event leave", (SIGNAL_FUNC) event_leave);
1146 signal_add("silc event signoff", (SIGNAL_FUNC) event_signoff);
1147 signal_add("silc event topic", (SIGNAL_FUNC) event_topic);
1148 signal_add("silc event invite", (SIGNAL_FUNC) event_invite);
1149 signal_add("silc event nick", (SIGNAL_FUNC) event_nick);
1150 signal_add("silc event cmode", (SIGNAL_FUNC) event_cmode);
1151 signal_add("silc event cumode", (SIGNAL_FUNC) event_cumode);
1152 signal_add("silc event motd", (SIGNAL_FUNC) event_motd);
1153 signal_add("silc event channel_change", (SIGNAL_FUNC) event_channel_change);
1154 signal_add("silc event server_signoff", (SIGNAL_FUNC) event_server_signoff);
1155 signal_add("silc event kick", (SIGNAL_FUNC) event_kick);
1156 signal_add("silc event kill", (SIGNAL_FUNC) event_kill);
1158 command_bind("part", MODULE_NAME, (SIGNAL_FUNC) command_part);
1159 command_bind("me", MODULE_NAME, (SIGNAL_FUNC) command_me);
1160 command_bind("action", MODULE_NAME, (SIGNAL_FUNC) command_action);
1161 command_bind("notice", MODULE_NAME, (SIGNAL_FUNC) command_notice);
1162 command_bind("away", MODULE_NAME, (SIGNAL_FUNC) command_away);
1163 command_bind("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
1165 silc_nicklist_init();
1168 void silc_channels_deinit(void)
1170 signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1171 signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
1172 signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit);
1174 signal_remove("silc event join", (SIGNAL_FUNC) event_join);
1175 signal_remove("silc event leave", (SIGNAL_FUNC) event_leave);
1176 signal_remove("silc event signoff", (SIGNAL_FUNC) event_signoff);
1177 signal_remove("silc event topic", (SIGNAL_FUNC) event_topic);
1178 signal_remove("silc event invite", (SIGNAL_FUNC) event_invite);
1179 signal_remove("silc event nick", (SIGNAL_FUNC) event_nick);
1180 signal_remove("silc event cmode", (SIGNAL_FUNC) event_cmode);
1181 signal_remove("silc event cumode", (SIGNAL_FUNC) event_cumode);
1182 signal_remove("silc event motd", (SIGNAL_FUNC) event_motd);
1183 signal_remove("silc event channel_change",
1184 (SIGNAL_FUNC) event_channel_change);
1185 signal_remove("silc event server_signoff",
1186 (SIGNAL_FUNC) event_server_signoff);
1187 signal_remove("silc event kick", (SIGNAL_FUNC) event_kick);
1188 signal_remove("silc event kill", (SIGNAL_FUNC) event_kill);
1190 command_unbind("part", (SIGNAL_FUNC) command_part);
1191 command_unbind("me", (SIGNAL_FUNC) command_me);
1192 command_unbind("action", (SIGNAL_FUNC) command_action);
1193 command_unbind("notice", (SIGNAL_FUNC) command_notice);
1194 command_unbind("away", (SIGNAL_FUNC) command_away);
1195 command_unbind("key", (SIGNAL_FUNC) command_key);
1197 silc_nicklist_deinit();