5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "chat-protocols.h"
26 #include "servers-setup.h"
27 #include "channels-setup.h"
28 #include "silc-servers.h"
29 #include "silc-channels.h"
30 #include "silc-queries.h"
31 #include "silc-nicklist.h"
36 #include "fe-common/core/printtext.h"
37 #include "fe-common/core/fe-channels.h"
38 #include "fe-common/core/keyboard.h"
39 #include "fe-common/silc/module-formats.h"
44 silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
45 const char *name, SilcSocketType conn_type,
46 unsigned char *pk, SilcUInt32 pk_len,
47 SilcSKEPKType pk_type,
48 SilcVerifyPublicKey completion, void *context);
50 static void silc_get_umode_string(SilcUInt32 mode, char *buf,
53 if ((mode & SILC_UMODE_SERVER_OPERATOR) ||
54 (mode & SILC_UMODE_ROUTER_OPERATOR)) {
55 strcat(buf, (mode & SILC_UMODE_SERVER_OPERATOR) ?
57 (mode & SILC_UMODE_ROUTER_OPERATOR) ?
58 "[SILC operator]" : "[unknown mode]");
60 if (mode & SILC_UMODE_GONE)
61 strcat(buf, " [away]");
62 if (mode & SILC_UMODE_INDISPOSED)
63 strcat(buf, " [indisposed]");
64 if (mode & SILC_UMODE_BUSY)
65 strcat(buf, " [busy]");
66 if (mode & SILC_UMODE_PAGE)
67 strcat(buf, " [page to reach]");
68 if (mode & SILC_UMODE_HYPER)
69 strcat(buf, " [hyper active]");
70 if (mode & SILC_UMODE_ROBOT)
71 strcat(buf, " [robot]");
72 if (mode & SILC_UMODE_ANONYMOUS)
73 strcat(buf, " [anonymous]");
74 if (mode & SILC_UMODE_BLOCK_PRIVMSG)
75 strcat(buf, " [blocks private messages]");
76 if (mode & SILC_UMODE_DETACHED)
77 strcat(buf, " [detached]");
78 if (mode & SILC_UMODE_REJECT_WATCHING)
79 strcat(buf, " [rejects watching]");
80 if (mode & SILC_UMODE_BLOCK_INVITE)
81 strcat(buf, " [blocks invites]");
84 void silc_say(SilcClient client, SilcClientConnection conn,
85 SilcClientMessageType type, char *msg, ...)
87 SILC_SERVER_REC *server;
91 server = conn == NULL ? NULL : conn->context;
94 str = g_strdup_vprintf(msg, va);
95 printtext(server, NULL, MSGLEVEL_CRAP, "%s", str);
100 void silc_say_error(char *msg, ...)
106 str = g_strdup_vprintf(msg, va);
107 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "%s", str);
113 /* Message for a channel. The `sender' is the nickname of the sender
114 received in the packet. The `channel_name' is the name of the channel. */
116 void silc_channel_message(SilcClient client, SilcClientConnection conn,
117 SilcClientEntry sender, SilcChannelEntry channel,
118 SilcMessageFlags flags, const unsigned char *message,
119 SilcUInt32 message_len)
121 SILC_SERVER_REC *server;
123 SILC_CHANNEL_REC *chanrec;
125 SILC_LOG_DEBUG(("Start"));
130 server = conn == NULL ? NULL : conn->context;
131 chanrec = silc_channel_find_entry(server, channel);
135 nick = silc_nicklist_find(chanrec, sender);
137 /* We didn't find client but it clearly exists, add it. */
138 SilcChannelUser chu = silc_client_on_channel(channel, sender);
140 nick = silc_nicklist_insert(chanrec, chu, FALSE);
143 if (flags & SILC_MESSAGE_FLAG_DATA) {
144 /* MIME object received, try to display it as well as we can */
145 char type[128], enc[128];
149 memset(type, 0, sizeof(type));
150 memset(enc, 0, sizeof(enc));
151 if (!silc_mime_parse(message, message_len, NULL, 0, type, sizeof(type) - 1,
152 enc, sizeof(enc) - 1, &data, &data_len))
155 /* Then figure out what we can display */
156 if (strstr(type, "text/") && !strstr(type, "text/t140") &&
157 !strstr(type, "text/vnd")) {
158 /* It is something textual, display it */
159 message = (const unsigned char *)data;
161 printformat_module("fe-common/silc", server, channel->channel_name,
162 MSGLEVEL_CRAP, SILCTXT_MESSAGE_DATA,
163 nick == NULL ? "[<unknown>]" : nick->nick, type);
171 if (flags & SILC_MESSAGE_FLAG_ACTION)
172 printformat_module("fe-common/silc", server, channel->channel_name,
173 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_ACTION,
174 nick == NULL ? "[<unknown>]" : nick->nick, message);
175 else if (flags & SILC_MESSAGE_FLAG_NOTICE)
176 printformat_module("fe-common/silc", server, channel->channel_name,
177 MSGLEVEL_NOTICES, SILCTXT_CHANNEL_NOTICE,
178 nick == NULL ? "[<unknown>]" : nick->nick, message);
180 if (flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
181 char tmp[256], *cp, *dm = NULL;
183 memset(tmp, 0, sizeof(tmp));
185 if (message_len > sizeof(tmp) - 1) {
186 dm = silc_calloc(message_len + 1, sizeof(*dm));
190 silc_utf8_decode(message, message_len, SILC_STRING_LANGUAGE,
192 signal_emit("message public", 6, server, cp,
193 nick == NULL ? "[<unknown>]" : nick->nick,
194 nick == NULL ? "" : nick->host == NULL ? "" : nick->host,
195 chanrec->name, nick);
200 signal_emit("message public", 6, server, message,
201 nick == NULL ? "[<unknown>]" : nick->nick,
202 nick == NULL ? "" : nick->host == NULL ? "" : nick->host,
203 chanrec->name, nick);
207 /* Private message to the client. The `sender' is the nickname of the
208 sender received in the packet. */
210 void silc_private_message(SilcClient client, SilcClientConnection conn,
211 SilcClientEntry sender, SilcMessageFlags flags,
212 const unsigned char *message,
213 SilcUInt32 message_len)
215 SILC_SERVER_REC *server;
218 SILC_LOG_DEBUG(("Start"));
220 server = conn == NULL ? NULL : conn->context;
221 memset(userhost, 0, sizeof(userhost));
222 if (sender->username)
223 snprintf(userhost, sizeof(userhost) - 1, "%s@%s",
224 sender->username, sender->hostname);
226 if (flags & SILC_MESSAGE_FLAG_DATA) {
227 /* MIME object received, try to display it as well as we can */
228 char type[128], enc[128];
232 memset(type, 0, sizeof(type));
233 memset(enc, 0, sizeof(enc));
234 if (!silc_mime_parse(message, message_len, NULL, 0, type, sizeof(type) - 1,
235 enc, sizeof(enc) - 1, &data, &data_len))
238 /* Then figure out what we can display */
239 if (strstr(type, "text/") && !strstr(type, "text/t140") &&
240 !strstr(type, "text/vnd")) {
241 /* It is something textual, display it */
242 message = (const unsigned char *)data;
244 printformat_module("fe-common/silc", server, NULL,
245 MSGLEVEL_CRAP, SILCTXT_MESSAGE_DATA,
246 sender->nickname ? sender->nickname : "[<unknown>]",
255 if (flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
256 char tmp[256], *cp, *dm = NULL;
258 memset(tmp, 0, sizeof(tmp));
260 if (message_len > sizeof(tmp) - 1) {
261 dm = silc_calloc(message_len + 1, sizeof(*dm));
265 silc_utf8_decode(message, message_len, SILC_STRING_LANGUAGE,
267 signal_emit("message private", 4, server, cp,
268 sender->nickname ? sender->nickname : "[<unknown>]",
269 sender->username ? userhost : NULL);
274 signal_emit("message private", 4, server, message,
275 sender->nickname ? sender->nickname : "[<unknown>]",
276 sender->username ? userhost : NULL);
279 /* Notify message to the client. The notify arguments are sent in the
280 same order as servers sends them. The arguments are same as received
281 from the server except for ID's. If ID is received application receives
282 the corresponding entry to the ID. For example, if Client ID is received
283 application receives SilcClientEntry. Also, if the notify type is
284 for channel the channel entry is sent to application (even if server
285 does not send it). */
287 void silc_notify(SilcClient client, SilcClientConnection conn,
288 SilcNotifyType type, ...)
291 SILC_SERVER_REC *server;
292 SILC_CHANNEL_REC *chanrec;
293 SILC_NICK_REC *nickrec;
294 SilcClientEntry client_entry, client_entry2;
295 SilcChannelEntry channel, channel2;
296 SilcServerEntry server_entry;
302 GSList *list1, *list_tmp;
304 SILC_LOG_DEBUG(("Start"));
308 server = conn == NULL ? NULL : conn->context;
311 case SILC_NOTIFY_TYPE_NONE:
312 /* Some generic notice from server */
313 printtext(server, NULL, MSGLEVEL_CRAP, "%s", (char *)va_arg(va, char *));
316 case SILC_NOTIFY_TYPE_INVITE:
318 * Invited or modified invite list.
321 SILC_LOG_DEBUG(("Notify: INVITE"));
323 channel = va_arg(va, SilcChannelEntry);
324 name = va_arg(va, char *);
325 client_entry = va_arg(va, SilcClientEntry);
327 memset(buf, 0, sizeof(buf));
328 snprintf(buf, sizeof(buf) - 1, "%s@%s",
329 client_entry->username, client_entry->hostname);
330 signal_emit("message invite", 4, server, channel ? channel->channel_name :
331 name, client_entry->nickname, buf);
334 case SILC_NOTIFY_TYPE_JOIN:
339 SILC_LOG_DEBUG(("Notify: JOIN"));
341 client_entry = va_arg(va, SilcClientEntry);
342 channel = va_arg(va, SilcChannelEntry);
344 if (client_entry == server->conn->local_entry) {
345 /* You joined to channel */
346 chanrec = silc_channel_find(server, channel->channel_name);
347 if (chanrec != NULL && !chanrec->joined)
348 chanrec->entry = channel;
350 chanrec = silc_channel_find_entry(server, channel);
351 if (chanrec != NULL) {
352 SilcChannelUser chu = silc_client_on_channel(channel, client_entry);
354 nickrec = silc_nicklist_insert(chanrec, chu, TRUE);
358 memset(buf, 0, sizeof(buf));
359 if (client_entry->username)
360 snprintf(buf, sizeof(buf) - 1, "%s@%s",
361 client_entry->username, client_entry->hostname);
362 signal_emit("message join", 4, server, channel->channel_name,
363 client_entry->nickname,
364 client_entry->username == NULL ? "" : buf);
367 case SILC_NOTIFY_TYPE_LEAVE:
372 SILC_LOG_DEBUG(("Notify: LEAVE"));
374 client_entry = va_arg(va, SilcClientEntry);
375 channel = va_arg(va, SilcChannelEntry);
377 memset(buf, 0, sizeof(buf));
378 if (client_entry->username)
379 snprintf(buf, sizeof(buf) - 1, "%s@%s",
380 client_entry->username, client_entry->hostname);
381 signal_emit("message part", 5, server, channel->channel_name,
382 client_entry->nickname, client_entry->username ?
383 buf : "", client_entry->nickname);
385 chanrec = silc_channel_find_entry(server, channel);
386 if (chanrec != NULL) {
387 nickrec = silc_nicklist_find(chanrec, client_entry);
389 nicklist_remove(CHANNEL(chanrec), NICK(nickrec));
393 case SILC_NOTIFY_TYPE_SIGNOFF:
398 SILC_LOG_DEBUG(("Notify: SIGNOFF"));
400 client_entry = va_arg(va, SilcClientEntry);
401 tmp = va_arg(va, char *);
403 silc_server_free_ftp(server, client_entry);
405 memset(buf, 0, sizeof(buf));
406 if (client_entry->username)
407 snprintf(buf, sizeof(buf) - 1, "%s@%s",
408 client_entry->username, client_entry->hostname);
409 signal_emit("message quit", 4, server, client_entry->nickname,
410 client_entry->username ? buf : "",
413 list1 = nicklist_get_same_unique(SERVER(server), client_entry);
414 for (list_tmp = list1; list_tmp != NULL; list_tmp =
415 list_tmp->next->next) {
416 CHANNEL_REC *channel = list_tmp->data;
417 NICK_REC *nickrec = list_tmp->next->data;
419 nicklist_remove(channel, nickrec);
423 case SILC_NOTIFY_TYPE_TOPIC_SET:
428 SILC_LOG_DEBUG(("Notify: TOPIC_SET"));
430 idtype = va_arg(va, int);
431 entry = va_arg(va, void *);
432 tmp = va_arg(va, char *);
433 channel = va_arg(va, SilcChannelEntry);
435 chanrec = silc_channel_find_entry(server, channel);
436 if (chanrec != NULL) {
437 g_free_not_null(chanrec->topic);
438 chanrec->topic = *tmp == '\0' ? NULL : g_strdup(tmp);
439 signal_emit("channel topic changed", 1, chanrec);
442 if (idtype == SILC_ID_CLIENT) {
443 client_entry = (SilcClientEntry)entry;
444 memset(buf, 0, sizeof(buf));
445 snprintf(buf, sizeof(buf) - 1, "%s@%s",
446 client_entry->username, client_entry->hostname);
447 signal_emit("message topic", 5, server, channel->channel_name,
448 tmp, client_entry->nickname, buf);
449 } else if (idtype == SILC_ID_SERVER) {
450 server_entry = (SilcServerEntry)entry;
451 signal_emit("message topic", 5, server, channel->channel_name,
452 tmp, server_entry->server_name,
453 server_entry->server_name);
454 } else if (idtype == SILC_ID_CHANNEL) {
455 channel = (SilcChannelEntry)entry;
456 signal_emit("message topic", 5, server, channel->channel_name,
457 tmp, channel->channel_name, channel->channel_name);
461 case SILC_NOTIFY_TYPE_NICK_CHANGE:
466 SILC_LOG_DEBUG(("Notify: NICK_CHANGE"));
468 client_entry = va_arg(va, SilcClientEntry);
469 client_entry2 = va_arg(va, SilcClientEntry);
471 if (!strcmp(client_entry->nickname, client_entry2->nickname))
474 memset(buf, 0, sizeof(buf));
475 snprintf(buf, sizeof(buf) - 1, "%s@%s",
476 client_entry2->username, client_entry2->hostname);
477 nicklist_rename_unique(SERVER(server),
478 client_entry, client_entry->nickname,
479 client_entry2, client_entry2->nickname);
480 signal_emit("message nick", 4, server, client_entry2->nickname,
481 client_entry->nickname, buf);
484 case SILC_NOTIFY_TYPE_CMODE_CHANGE:
486 * Changed channel mode.
489 SILC_LOG_DEBUG(("Notify: CMODE_CHANGE"));
491 idtype = va_arg(va, int);
492 entry = va_arg(va, void *);
493 mode = va_arg(va, SilcUInt32);
494 (void)va_arg(va, char *);
495 (void)va_arg(va, char *);
496 channel = va_arg(va, SilcChannelEntry);
498 tmp = silc_client_chmode(mode,
499 channel->channel_key ?
500 silc_cipher_get_name(channel->channel_key) : "",
502 silc_hmac_get_name(channel->hmac) : "");
504 chanrec = silc_channel_find_entry(server, channel);
505 if (chanrec != NULL) {
506 g_free_not_null(chanrec->mode);
507 chanrec->mode = g_strdup(tmp == NULL ? "" : tmp);
508 signal_emit("channel mode changed", 1, chanrec);
511 if (idtype == SILC_ID_CLIENT) {
512 client_entry = (SilcClientEntry)entry;
513 printformat_module("fe-common/silc", server, channel->channel_name,
514 MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE,
515 channel->channel_name, tmp ? tmp : "removed all",
516 client_entry->nickname);
517 } else if (idtype == SILC_ID_SERVER) {
518 server_entry = (SilcServerEntry)entry;
519 printformat_module("fe-common/silc", server, channel->channel_name,
520 MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE,
521 channel->channel_name, tmp ? tmp : "removed all",
522 server_entry->server_name);
523 } else if (idtype == SILC_ID_CHANNEL) {
524 channel2 = (SilcChannelEntry)entry;
525 printformat_module("fe-common/silc", server, channel->channel_name,
526 MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE,
527 channel->channel_name, tmp ? tmp : "removed all",
528 channel2->channel_name);
534 case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
536 * Changed user's mode on channel.
539 SILC_LOG_DEBUG(("Notify: CUMODE_CHANGE"));
541 idtype = va_arg(va, int);
542 entry = va_arg(va, void *);
543 mode = va_arg(va, SilcUInt32);
544 client_entry2 = va_arg(va, SilcClientEntry);
545 channel = va_arg(va, SilcChannelEntry);
547 tmp = silc_client_chumode(mode);
548 chanrec = silc_channel_find_entry(server, channel);
549 if (chanrec != NULL) {
552 if (client_entry2 == server->conn->local_entry)
553 chanrec->chanop = (mode & SILC_CHANNEL_UMODE_CHANOP) != 0;
555 nick = silc_nicklist_find(chanrec, client_entry2);
557 nick->op = (mode & SILC_CHANNEL_UMODE_CHANOP) != 0;
558 nick->founder = (mode & SILC_CHANNEL_UMODE_CHANFO) != 0;
559 signal_emit("nick mode changed", 2, chanrec, nick);
563 if (idtype == SILC_ID_CLIENT) {
564 client_entry = (SilcClientEntry)entry;
565 printformat_module("fe-common/silc", server, channel->channel_name,
566 MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
567 channel->channel_name, client_entry2->nickname,
568 tmp ? tmp : "removed all",
569 client_entry->nickname);
570 } else if (idtype == SILC_ID_SERVER) {
571 server_entry = (SilcServerEntry)entry;
572 printformat_module("fe-common/silc", server, channel->channel_name,
573 MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
574 channel->channel_name, client_entry2->nickname,
575 tmp ? tmp : "removed all",
576 server_entry->server_name);
577 } else if (idtype == SILC_ID_CHANNEL) {
578 channel2 = (SilcChannelEntry)entry;
579 printformat_module("fe-common/silc", server, channel->channel_name,
580 MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
581 channel->channel_name, client_entry2->nickname,
582 tmp ? tmp : "removed all",
583 channel2->channel_name);
586 if (mode & SILC_CHANNEL_UMODE_CHANFO)
587 printformat_module("fe-common/silc",
588 server, channel->channel_name, MSGLEVEL_CRAP,
589 SILCTXT_CHANNEL_FOUNDER,
590 channel->channel_name, client_entry2->nickname);
592 if (mode & SILC_CHANNEL_UMODE_QUIET && conn->local_entry == client_entry2)
593 printformat_module("fe-common/silc",
594 server, channel->channel_name, MSGLEVEL_CRAP,
595 SILCTXT_CHANNEL_QUIETED, channel->channel_name);
600 case SILC_NOTIFY_TYPE_MOTD:
605 SILC_LOG_DEBUG(("Notify: MOTD"));
607 tmp = va_arg(va, char *);
609 if (!settings_get_bool("skip_motd"))
610 printtext_multiline(server, NULL, MSGLEVEL_CRAP, "%s", tmp);
613 case SILC_NOTIFY_TYPE_KICKED:
615 * Someone was kicked from channel.
618 SILC_LOG_DEBUG(("Notify: KICKED"));
620 client_entry = va_arg(va, SilcClientEntry);
621 tmp = va_arg(va, char *);
622 client_entry2 = va_arg(va, SilcClientEntry);
623 channel = va_arg(va, SilcChannelEntry);
625 chanrec = silc_channel_find_entry(server, channel);
627 if (client_entry == conn->local_entry) {
628 printformat_module("fe-common/silc", server, channel->channel_name,
629 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KICKED_YOU,
630 channel->channel_name,
631 client_entry ? client_entry2->nickname : "",
634 chanrec->kicked = TRUE;
635 channel_destroy((CHANNEL_REC *)chanrec);
638 printformat_module("fe-common/silc", server, channel->channel_name,
639 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KICKED,
640 client_entry->nickname, channel->channel_name,
641 client_entry2 ? client_entry2->nickname : "",
645 SILC_NICK_REC *nickrec = silc_nicklist_find(chanrec, client_entry);
647 nicklist_remove(CHANNEL(chanrec), NICK(nickrec));
652 case SILC_NOTIFY_TYPE_KILLED:
654 * Someone was killed from the network.
657 SILC_LOG_DEBUG(("Notify: KILLED"));
659 client_entry = va_arg(va, SilcClientEntry);
660 tmp = va_arg(va, char *);
661 idtype = va_arg(va, int);
662 entry = va_arg(va, SilcClientEntry);
664 if (client_entry == conn->local_entry) {
665 if (idtype == SILC_ID_CLIENT) {
666 client_entry2 = (SilcClientEntry)entry;
667 printformat_module("fe-common/silc", server, NULL,
668 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU,
669 client_entry2 ? client_entry2->nickname : "",
671 } else if (idtype == SILC_ID_SERVER) {
672 server_entry = (SilcServerEntry)entry;
673 printformat_module("fe-common/silc", server, NULL,
674 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU,
675 server_entry->server_name, tmp ? tmp : "");
676 } else if (idtype == SILC_ID_CHANNEL) {
677 channel = (SilcChannelEntry)entry;
678 printformat_module("fe-common/silc", server, NULL,
679 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU,
680 channel->channel_name, tmp ? tmp : "");
683 list1 = nicklist_get_same_unique(SERVER(server), client_entry);
684 for (list_tmp = list1; list_tmp != NULL; list_tmp =
685 list_tmp->next->next) {
686 CHANNEL_REC *channel = list_tmp->data;
687 NICK_REC *nickrec = list_tmp->next->data;
688 nicklist_remove(channel, nickrec);
691 if (idtype == SILC_ID_CLIENT) {
692 client_entry2 = (SilcClientEntry)entry;
693 printformat_module("fe-common/silc", server, NULL,
694 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED,
695 client_entry->nickname,
696 client_entry2 ? client_entry2->nickname : "",
698 } else if (idtype == SILC_ID_SERVER) {
699 server_entry = (SilcServerEntry)entry;
700 printformat_module("fe-common/silc", server, NULL,
701 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED,
702 client_entry->nickname,
703 server_entry->server_name, tmp ? tmp : "");
704 } else if (idtype == SILC_ID_CHANNEL) {
705 channel = (SilcChannelEntry)entry;
706 printformat_module("fe-common/silc", server, NULL,
707 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED,
708 client_entry->nickname,
709 channel->channel_name, tmp ? tmp : "");
714 case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
717 case SILC_NOTIFY_TYPE_SERVER_SIGNOFF:
720 * Server has quit the network.
723 SilcClientEntry *clients;
724 SilcUInt32 clients_count;
726 SILC_LOG_DEBUG(("Notify: SIGNOFF"));
728 (void)va_arg(va, void *);
729 clients = va_arg(va, SilcClientEntry *);
730 clients_count = va_arg(va, SilcUInt32);
732 for (i = 0; i < clients_count; i++) {
733 memset(buf, 0, sizeof(buf));
734 if (clients[i]->username)
735 snprintf(buf, sizeof(buf) - 1, "%s@%s",
736 clients[i]->username, clients[i]->hostname);
737 signal_emit("message quit", 4, server, clients[i]->nickname,
738 clients[i]->username ? buf : "",
741 silc_server_free_ftp(server, clients[i]);
743 list1 = nicklist_get_same_unique(SERVER(server), clients[i]);
744 for (list_tmp = list1; list_tmp != NULL; list_tmp =
745 list_tmp->next->next) {
746 CHANNEL_REC *channel = list_tmp->data;
747 NICK_REC *nickrec = list_tmp->next->data;
748 nicklist_remove(channel, nickrec);
754 case SILC_NOTIFY_TYPE_ERROR:
756 SilcStatus error = va_arg(va, int);
758 silc_say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
759 "%s", silc_get_status_message(error));
763 case SILC_NOTIFY_TYPE_WATCH:
765 SilcNotifyType notify;
767 client_entry = va_arg(va, SilcClientEntry);
768 name = va_arg(va, char *); /* Maybe NULL */
769 mode = va_arg(va, SilcUInt32);
770 notify = va_arg(va, int);
772 if (notify == SILC_NOTIFY_TYPE_NICK_CHANGE) {
774 printformat_module("fe-common/silc", server, NULL,
775 MSGLEVEL_CRAP, SILCTXT_WATCH_NICK_CHANGE,
776 client_entry->nickname, name);
778 printformat_module("fe-common/silc", server, NULL,
779 MSGLEVEL_CRAP, SILCTXT_WATCH_PRESENT,
780 client_entry->nickname);
781 } else if (notify == SILC_NOTIFY_TYPE_UMODE_CHANGE) {
782 /* See if client was away and is now present */
783 if (!(mode & (SILC_UMODE_GONE | SILC_UMODE_INDISPOSED |
784 SILC_UMODE_BUSY | SILC_UMODE_PAGE |
785 SILC_UMODE_DETACHED)) &&
786 (client_entry->mode & SILC_UMODE_GONE ||
787 client_entry->mode & SILC_UMODE_INDISPOSED ||
788 client_entry->mode & SILC_UMODE_BUSY ||
789 client_entry->mode & SILC_UMODE_PAGE ||
790 client_entry->mode & SILC_UMODE_DETACHED)) {
791 printformat_module("fe-common/silc", server, NULL,
792 MSGLEVEL_CRAP, SILCTXT_WATCH_PRESENT,
793 client_entry->nickname);
797 memset(buf, 0, sizeof(buf));
798 silc_get_umode_string(mode, buf, sizeof(buf) - 1);
799 printformat_module("fe-common/silc", server, NULL,
800 MSGLEVEL_CRAP, SILCTXT_WATCH_UMODE_CHANGE,
801 client_entry->nickname, buf);
803 } else if (notify == SILC_NOTIFY_TYPE_KILLED) {
804 printformat_module("fe-common/silc", server, NULL,
805 MSGLEVEL_CRAP, SILCTXT_WATCH_KILLED,
806 client_entry->nickname);
807 } else if (notify == SILC_NOTIFY_TYPE_SIGNOFF ||
808 notify == SILC_NOTIFY_TYPE_SERVER_SIGNOFF) {
809 printformat_module("fe-common/silc", server, NULL,
810 MSGLEVEL_CRAP, SILCTXT_WATCH_SIGNOFF,
811 client_entry->nickname);
812 } else if (notify == SILC_NOTIFY_TYPE_NONE) {
813 /* Client logged in to the network */
814 printformat_module("fe-common/silc", server, NULL,
815 MSGLEVEL_CRAP, SILCTXT_WATCH_PRESENT,
816 client_entry->nickname);
823 printformat_module("fe-common/silc", server, NULL,
824 MSGLEVEL_CRAP, SILCTXT_UNKNOWN_NOTIFY, type);
831 /* Called to indicate that connection was either successfully established
832 or connecting failed. This is also the first time application receives
833 the SilcClientConnection object which it should save somewhere. */
835 void silc_connect(SilcClient client, SilcClientConnection conn,
836 SilcClientConnectionStatus status)
838 SILC_SERVER_REC *server = conn->context;
840 if (!server || server->disconnected) {
841 silc_client_close_connection(client, conn);
846 case SILC_CLIENT_CONN_SUCCESS:
847 /* We have successfully connected to server */
848 server->connected = TRUE;
849 signal_emit("event connected", 1, server);
852 case SILC_CLIENT_CONN_SUCCESS_RESUME:
853 /* We have successfully resumed old detached session */
854 server->connected = TRUE;
855 signal_emit("event connected", 1, server);
857 /* If we resumed old session check whether we need to update
859 if (strcmp(server->nick, conn->local_entry->nickname)) {
861 old = g_strdup(server->nick);
862 server_change_nick(SERVER(server), conn->local_entry->nickname);
863 nicklist_rename_unique(SERVER(server),
864 conn->local_entry, server->nick,
865 conn->local_entry, conn->local_entry->nickname);
866 signal_emit("message own_nick", 4, server, server->nick, old, "");
872 server->connection_lost = TRUE;
874 server->conn->context = NULL;
875 server_disconnect(SERVER(server));
880 /* Called to indicate that connection was disconnected to the server. */
882 void silc_disconnect(SilcClient client, SilcClientConnection conn,
883 SilcStatus status, const char *message)
885 SILC_SERVER_REC *server = conn->context;
887 SILC_LOG_DEBUG(("Start"));
889 if (!server || server->connection_lost)
892 if (server->conn && server->conn->local_entry) {
893 nicklist_rename_unique(SERVER(server),
894 server->conn->local_entry, server->nick,
895 server->conn->local_entry,
896 silc_client->username);
897 silc_change_nick(server, silc_client->username);
901 silc_say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
902 "Server closed connection: %s (%d) %s",
903 silc_get_status_message(status), status,
904 message ? message : "");
906 server->conn->context = NULL;
908 server->connection_lost = TRUE;
909 server_disconnect(SERVER(server));
912 /* Command handler. This function is called always in the command function.
913 If error occurs it will be called as well. `conn' is the associated
914 client connection. `cmd_context' is the command context that was
915 originally sent to the command. `success' is FALSE if error occured
916 during command. `command' is the command being processed. It must be
917 noted that this is not reply from server. This is merely called just
918 after application has called the command. Just to tell application
919 that the command really was processed. */
921 void silc_command(SilcClient client, SilcClientConnection conn,
922 SilcClientCommandContext cmd_context, bool success,
923 SilcCommand command, SilcStatus status)
925 SILC_SERVER_REC *server = conn->context;
927 SILC_LOG_DEBUG(("Start"));
930 silc_say_error("%s", silc_get_status_message(status));
936 case SILC_COMMAND_INVITE:
937 if (cmd_context->argc > 2)
938 printformat_module("fe-common/silc", server, NULL,
939 MSGLEVEL_CRAP, SILCTXT_CHANNEL_INVITING,
940 cmd_context->argv[2],
941 (cmd_context->argv[1][0] == '*' ?
942 (char *)conn->current_channel->channel_name :
943 (char *)cmd_context->argv[1]));
946 case SILC_COMMAND_DETACH:
947 server->no_reconnect = TRUE;
955 /* Client info resolving callback when JOIN command reply is received.
956 This will cache all users on the channel. */
958 static void silc_client_join_get_users(SilcClient client,
959 SilcClientConnection conn,
960 SilcClientEntry *clients,
961 SilcUInt32 clients_count,
964 SilcChannelEntry channel = (SilcChannelEntry)context;
965 SilcHashTableList htl;
967 SILC_SERVER_REC *server = conn->context;
968 SILC_CHANNEL_REC *chanrec;
969 SilcClientEntry founder = NULL;
972 SILC_LOG_DEBUG(("Start, channel %s, %d users", channel->channel_name,
973 silc_hash_table_count(channel->user_list)));
978 chanrec = silc_channel_find(server, channel->channel_name);
982 silc_hash_table_list(channel->user_list, &htl);
983 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
984 if (!chu->client->nickname)
986 if (chu->mode & SILC_CHANNEL_UMODE_CHANFO)
987 founder = chu->client;
988 silc_nicklist_insert(chanrec, chu, FALSE);
990 silc_hash_table_list_reset(&htl);
992 ownnick = NICK(silc_nicklist_find(chanrec, conn->local_entry));
993 nicklist_set_own(CHANNEL(chanrec), ownnick);
994 signal_emit("channel joined", 1, chanrec);
995 chanrec->entry = channel;
998 printformat_module("fe-common/silc", server, channel->channel_name,
999 MSGLEVEL_CRAP, SILCTXT_CHANNEL_TOPIC,
1000 channel->channel_name, chanrec->topic);
1003 if (founder == conn->local_entry)
1004 printformat_module("fe-common/silc",
1005 server, channel->channel_name, MSGLEVEL_CRAP,
1006 SILCTXT_CHANNEL_FOUNDER_YOU,
1007 channel->channel_name);
1009 printformat_module("fe-common/silc",
1010 server, channel->channel_name, MSGLEVEL_CRAP,
1011 SILCTXT_CHANNEL_FOUNDER,
1012 channel->channel_name, founder->nickname);
1018 SilcClientConnection conn;
1024 void silc_getkey_cb(bool success, void *context)
1026 GetkeyContext getkey = (GetkeyContext)context;
1027 char *entity = (getkey->id_type == SILC_ID_CLIENT ? "user" : "server");
1028 char *name = (getkey->id_type == SILC_ID_CLIENT ?
1029 ((SilcClientEntry)getkey->entry)->nickname :
1030 ((SilcServerEntry)getkey->entry)->server_name);
1033 printformat_module("fe-common/silc", NULL, NULL,
1034 MSGLEVEL_CRAP, SILCTXT_PUBKEY_VERIFIED, entity, name);
1036 printformat_module("fe-common/silc", NULL, NULL,
1037 MSGLEVEL_CRAP, SILCTXT_PUBKEY_NOTVERIFIED,
1041 silc_free(getkey->fingerprint);
1045 /* Command reply handler. This function is called always in the command reply
1046 function. If error occurs it will be called as well. Normal scenario
1047 is that it will be called after the received command data has been parsed
1048 and processed. The function is used to pass the received command data to
1051 `conn' is the associated client connection. `cmd_payload' is the command
1052 payload data received from server and it can be ignored. It is provided
1053 if the application would like to re-parse the received command data,
1054 however, it must be noted that the data is parsed already by the library
1055 thus the payload can be ignored. `success' is FALSE if error occured.
1056 In this case arguments are not sent to the application. `command' is the
1057 command reply being processed. The function has variable argument list
1058 and each command defines the number and type of arguments it passes to the
1059 application (on error they are not sent). */
1062 silc_command_reply(SilcClient client, SilcClientConnection conn,
1063 SilcCommandPayload cmd_payload, bool success,
1064 SilcCommand command, SilcStatus status, ...)
1067 SILC_SERVER_REC *server = conn->context;
1068 SILC_CHANNEL_REC *chanrec;
1071 va_start(vp, status);
1073 SILC_LOG_DEBUG(("Start"));
1076 case SILC_COMMAND_WHOIS:
1078 char buf[1024], *nickname, *username, *realname, *nick;
1079 unsigned char *fingerprint;
1080 SilcUInt32 idle, mode;
1081 SilcBuffer channels, user_modes;
1082 SilcClientEntry client_entry;
1085 if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
1086 /* Print the unknown nick for user */
1087 unsigned char *tmp =
1088 silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
1091 silc_say_error("%s: %s", tmp,
1092 silc_get_status_message(status));
1094 } else if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
1095 /* Try to find the entry for the unknown client ID, since we
1096 might have, and print the nickname of it for user. */
1098 unsigned char *tmp =
1099 silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
1102 SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len,
1105 client_entry = silc_client_get_client_by_id(client, conn,
1107 if (client_entry && client_entry->nickname)
1108 silc_say_error("%s: %s", client_entry->nickname,
1109 silc_get_status_message(status));
1110 silc_free(client_id);
1114 } else if (!success) {
1115 silc_say_error("WHOIS: %s", silc_get_status_message(status));
1119 client_entry = va_arg(vp, SilcClientEntry);
1120 nickname = va_arg(vp, char *);
1121 username = va_arg(vp, char *);
1122 realname = va_arg(vp, char *);
1123 channels = va_arg(vp, SilcBuffer);
1124 mode = va_arg(vp, SilcUInt32);
1125 idle = va_arg(vp, SilcUInt32);
1126 fingerprint = va_arg(vp, unsigned char *);
1127 user_modes = va_arg(vp, SilcBuffer);
1128 attrs = va_arg(vp, SilcDList);
1130 silc_parse_userfqdn(nickname, &nick, NULL);
1131 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1132 SILCTXT_WHOIS_USERINFO, nickname,
1133 client_entry->username, client_entry->hostname,
1134 nick, client_entry->nickname);
1135 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1136 SILCTXT_WHOIS_REALNAME, realname);
1139 if (channels && user_modes) {
1141 SilcDList list = silc_channel_payload_parse_list(channels->data,
1143 if (list && silc_get_mode_list(user_modes, silc_dlist_count(list),
1145 SilcChannelPayload entry;
1148 memset(buf, 0, sizeof(buf));
1149 silc_dlist_start(list);
1150 while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
1151 SilcUInt32 name_len;
1152 char *m = silc_client_chumode_char(umodes[i++]);
1153 char *name = silc_channel_get_name(entry, &name_len);
1156 strncat(buf, m, strlen(m));
1157 strncat(buf, name, name_len);
1158 strncat(buf, " ", 1);
1162 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1163 SILCTXT_WHOIS_CHANNELS, buf);
1164 silc_channel_payload_list_free(list);
1170 memset(buf, 0, sizeof(buf));
1171 silc_get_umode_string(mode, buf, sizeof(buf - 1));
1172 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1173 SILCTXT_WHOIS_MODES, buf);
1176 if (idle && nickname) {
1177 memset(buf, 0, sizeof(buf));
1178 snprintf(buf, sizeof(buf) - 1, "%lu %s",
1179 idle > 60 ? (idle / 60) : idle,
1180 idle > 60 ? "minutes" : "seconds");
1182 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1183 SILCTXT_WHOIS_IDLE, buf);
1187 fingerprint = silc_fingerprint(fingerprint, 20);
1188 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1189 SILCTXT_WHOIS_FINGERPRINT, fingerprint);
1190 silc_free(fingerprint);
1194 silc_query_attributes_print(server, silc_client, conn, attrs,
1199 case SILC_COMMAND_IDENTIFY:
1201 SilcClientEntry client_entry;
1203 if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
1204 /* Print the unknown nick for user */
1205 unsigned char *tmp =
1206 silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
1209 silc_say_error("%s: %s", tmp,
1210 silc_get_status_message(status));
1212 } else if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
1213 /* Try to find the entry for the unknown client ID, since we
1214 might have, and print the nickname of it for user. */
1216 unsigned char *tmp =
1217 silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
1220 SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len,
1223 client_entry = silc_client_get_client_by_id(client, conn,
1225 if (client_entry && client_entry->nickname)
1226 silc_say_error("%s: %s", client_entry->nickname,
1227 silc_get_status_message(status));
1228 silc_free(client_id);
1237 case SILC_COMMAND_WHOWAS:
1239 char *nickname, *username, *realname;
1241 if (status == SILC_STATUS_ERR_NO_SUCH_NICK ||
1242 status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
1244 tmp = silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
1247 silc_say_error("%s: %s", tmp,
1248 silc_get_status_message(status));
1250 } else if (!success) {
1251 silc_say_error("WHOWAS: %s", silc_get_status_message(status));
1255 (void)va_arg(vp, SilcClientEntry);
1256 nickname = va_arg(vp, char *);
1257 username = va_arg(vp, char *);
1258 realname = va_arg(vp, char *);
1260 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1261 SILCTXT_WHOWAS_USERINFO, nickname, username,
1262 realname ? realname : "");
1266 case SILC_COMMAND_INVITE:
1268 SilcChannelEntry channel;
1270 SilcArgumentPayload args;
1276 channel = va_arg(vp, SilcChannelEntry);
1277 invite_list = va_arg(vp, char *);
1279 args = silc_command_get_args(cmd_payload);
1281 argc = silc_argument_get_arg_num(args);
1284 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1285 SILCTXT_CHANNEL_INVITE_LIST, channel->channel_name,
1288 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1289 SILCTXT_CHANNEL_NO_INVITE_LIST,
1290 channel->channel_name);
1294 case SILC_COMMAND_JOIN:
1296 char *channel, *mode, *topic;
1298 SilcChannelEntry channel_entry;
1299 SilcBuffer client_id_list;
1300 SilcUInt32 list_count;
1305 channel = va_arg(vp, char *);
1306 channel_entry = va_arg(vp, SilcChannelEntry);
1307 modei = va_arg(vp, SilcUInt32);
1308 (void)va_arg(vp, SilcUInt32);
1309 (void)va_arg(vp, unsigned char *);
1310 (void)va_arg(vp, unsigned char *);
1311 (void)va_arg(vp, unsigned char *);
1312 topic = va_arg(vp, char *);
1313 (void)va_arg(vp, unsigned char *);
1314 list_count = va_arg(vp, SilcUInt32);
1315 client_id_list = va_arg(vp, SilcBuffer);
1317 chanrec = silc_channel_find(server, channel);
1319 chanrec = silc_channel_create(server, channel, channel, TRUE);
1322 g_free_not_null(chanrec->topic);
1323 chanrec->topic = *topic == '\0' ? NULL : g_strdup(topic);
1324 signal_emit("channel topic changed", 1, chanrec);
1327 mode = silc_client_chmode(modei,
1328 channel_entry->channel_key ?
1329 silc_cipher_get_name(channel_entry->
1331 channel_entry->hmac ?
1332 silc_hmac_get_name(channel_entry->hmac) : "");
1333 g_free_not_null(chanrec->mode);
1334 chanrec->mode = g_strdup(mode == NULL ? "" : mode);
1335 signal_emit("channel mode changed", 1, chanrec);
1337 /* Resolve the client information */
1338 silc_client_get_clients_by_list(client, conn, list_count, client_id_list,
1339 silc_client_join_get_users,
1345 case SILC_COMMAND_NICK:
1348 SilcClientEntry client = va_arg(vp, SilcClientEntry);
1353 old = g_strdup(server->nick);
1354 server_change_nick(SERVER(server), client->nickname);
1355 nicklist_rename_unique(SERVER(server),
1356 server->conn->local_entry, server->nick,
1357 client, client->nickname);
1358 signal_emit("message own_nick", 4, server, server->nick, old, "");
1363 case SILC_COMMAND_LIST:
1368 char tmp[256], *cp, *dm = NULL;
1373 (void)va_arg(vp, SilcChannelEntry);
1374 name = va_arg(vp, char *);
1375 topic = va_arg(vp, char *);
1376 usercount = va_arg(vp, int);
1378 if (topic && !silc_term_utf8() &&
1379 silc_utf8_valid(topic, strlen(topic))) {
1380 memset(tmp, 0, sizeof(tmp));
1382 if (strlen(topic) > sizeof(tmp) - 1) {
1383 dm = silc_calloc(strlen(topic) + 1, sizeof(*dm));
1387 silc_utf8_decode(topic, strlen(topic), SILC_STRING_LANGUAGE,
1392 if (status == SILC_STATUS_LIST_START ||
1393 status == SILC_STATUS_OK)
1394 printformat_module("fe-common/silc", server, NULL,
1395 MSGLEVEL_CRAP, SILCTXT_LIST_HEADER);
1398 snprintf(users, sizeof(users) - 1, "N/A");
1400 snprintf(users, sizeof(users) - 1, "%d", usercount);
1401 printformat_module("fe-common/silc", server, NULL,
1402 MSGLEVEL_CRAP, SILCTXT_LIST,
1403 name, users, topic ? topic : "");
1408 case SILC_COMMAND_UMODE:
1416 mode = va_arg(vp, SilcUInt32);
1418 if (mode & SILC_UMODE_SERVER_OPERATOR &&
1419 !(server->umode & SILC_UMODE_SERVER_OPERATOR))
1420 printformat_module("fe-common/silc", server, NULL,
1421 MSGLEVEL_CRAP, SILCTXT_SERVER_OPER);
1423 if (mode & SILC_UMODE_ROUTER_OPERATOR &&
1424 !(server->umode & SILC_UMODE_ROUTER_OPERATOR))
1425 printformat_module("fe-common/silc", server, NULL,
1426 MSGLEVEL_CRAP, SILCTXT_ROUTER_OPER);
1428 if ((mode & SILC_UMODE_GONE) != (server->umode & SILC_UMODE_GONE)) {
1429 if (mode & SILC_UMODE_GONE) {
1430 if ((server->away_reason != NULL) && (server->away_reason[0] != '\0'))
1431 reason = g_strdup(server->away_reason);
1433 reason = g_strdup("away");
1435 reason = g_strdup("");
1437 silc_set_away(reason, server);
1442 server->umode = mode;
1443 signal_emit("user mode changed", 2, server, NULL);
1447 case SILC_COMMAND_OPER:
1451 server->umode |= SILC_UMODE_SERVER_OPERATOR;
1452 signal_emit("user mode changed", 2, server, NULL);
1454 printformat_module("fe-common/silc", server, NULL,
1455 MSGLEVEL_CRAP, SILCTXT_SERVER_OPER);
1458 case SILC_COMMAND_SILCOPER:
1462 server->umode |= SILC_UMODE_ROUTER_OPERATOR;
1463 signal_emit("user mode changed", 2, server, NULL);
1465 printformat_module("fe-common/silc", server, NULL,
1466 MSGLEVEL_CRAP, SILCTXT_ROUTER_OPER);
1469 case SILC_COMMAND_USERS:
1471 SilcHashTableList htl;
1472 SilcChannelEntry channel;
1473 SilcChannelUser chu;
1478 channel = va_arg(vp, SilcChannelEntry);
1480 printformat_module("fe-common/silc", server, channel->channel_name,
1481 MSGLEVEL_CRAP, SILCTXT_USERS_HEADER,
1482 channel->channel_name);
1484 silc_hash_table_list(channel->user_list, &htl);
1485 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
1486 SilcClientEntry e = chu->client;
1487 char stat[5], *mode;
1492 memset(stat, 0, sizeof(stat));
1493 mode = silc_client_chumode_char(chu->mode);
1494 if (e->mode & SILC_UMODE_GONE)
1496 else if (e->mode & SILC_UMODE_INDISPOSED)
1498 else if (e->mode & SILC_UMODE_BUSY)
1500 else if (e->mode & SILC_UMODE_PAGE)
1502 else if (e->mode & SILC_UMODE_HYPER)
1504 else if (e->mode & SILC_UMODE_ROBOT)
1506 else if (e->mode & SILC_UMODE_ANONYMOUS)
1513 printformat_module("fe-common/silc", server, channel->channel_name,
1514 MSGLEVEL_CRAP, SILCTXT_USERS,
1516 e->username ? e->username : "",
1517 e->hostname ? e->hostname : "",
1518 e->realname ? e->realname : "");
1522 silc_hash_table_list_reset(&htl);
1526 case SILC_COMMAND_BAN:
1528 SilcChannelEntry channel;
1534 channel = va_arg(vp, SilcChannelEntry);
1535 ban_list = va_arg(vp, char *);
1538 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1539 SILCTXT_CHANNEL_BAN_LIST, channel->channel_name,
1542 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1543 SILCTXT_CHANNEL_NO_BAN_LIST,
1544 channel->channel_name);
1548 case SILC_COMMAND_GETKEY:
1552 SilcPublicKey public_key;
1555 GetkeyContext getkey;
1561 id_type = va_arg(vp, SilcUInt32);
1562 entry = va_arg(vp, void *);
1563 public_key = va_arg(vp, SilcPublicKey);
1566 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
1568 getkey = silc_calloc(1, sizeof(*getkey));
1569 getkey->entry = entry;
1570 getkey->id_type = id_type;
1571 getkey->client = client;
1572 getkey->conn = conn;
1573 getkey->fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
1575 name = (id_type == SILC_ID_CLIENT ?
1576 ((SilcClientEntry)entry)->nickname :
1577 ((SilcServerEntry)entry)->server_name);
1579 silc_verify_public_key_internal(client, conn, name,
1580 (id_type == SILC_ID_CLIENT ?
1581 SILC_SOCKET_TYPE_CLIENT :
1582 SILC_SOCKET_TYPE_SERVER),
1583 pk, pk_len, SILC_SKE_PK_TYPE_SILC,
1584 silc_getkey_cb, getkey);
1587 printformat_module("fe-common/silc", server, NULL,
1588 MSGLEVEL_CRAP, SILCTXT_PUBKEY_NOKEY);
1593 case SILC_COMMAND_INFO:
1595 SilcServerEntry server_entry;
1602 server_entry = va_arg(vp, SilcServerEntry);
1603 server_name = va_arg(vp, char *);
1604 server_info = va_arg(vp, char *);
1606 if (server_name && server_info )
1608 printtext(server, NULL, MSGLEVEL_CRAP, "Server: %s", server_name);
1609 printtext(server, NULL, MSGLEVEL_CRAP, "%s", server_info);
1614 case SILC_COMMAND_TOPIC:
1616 SilcChannelEntry channel;
1618 char tmp[256], *cp, *dm = NULL;
1623 channel = va_arg(vp, SilcChannelEntry);
1624 topic = va_arg(vp, char *);
1626 if (topic && !silc_term_utf8() &&
1627 silc_utf8_valid(topic, strlen(topic))) {
1628 memset(tmp, 0, sizeof(tmp));
1630 if (strlen(topic) > sizeof(tmp) - 1) {
1631 dm = silc_calloc(strlen(topic) + 1, sizeof(*dm));
1635 silc_utf8_decode(topic, strlen(topic), SILC_STRING_LANGUAGE,
1641 chanrec = silc_channel_find_entry(server, channel);
1643 g_free_not_null(chanrec->topic);
1644 chanrec->topic = *topic == '\0' ? NULL : g_strdup(topic);
1645 signal_emit("channel topic changed", 1, chanrec);
1647 printformat_module("fe-common/silc", server, channel->channel_name,
1648 MSGLEVEL_CRAP, SILCTXT_CHANNEL_TOPIC,
1649 channel->channel_name, topic);
1651 printformat_module("fe-common/silc", server, channel->channel_name,
1652 MSGLEVEL_CRAP, SILCTXT_CHANNEL_TOPIC_NOT_SET,
1653 channel->channel_name);
1659 case SILC_COMMAND_WATCH:
1662 case SILC_COMMAND_STATS:
1664 SilcUInt32 starttime, uptime, my_clients, my_channels, my_server_ops,
1665 my_router_ops, cell_clients, cell_channels, cell_servers,
1666 clients, channels, servers, routers, server_ops, router_ops;
1668 SilcBufferStruct buf;
1669 unsigned char *tmp_buf;
1671 const char *tmptime;
1672 int days, hours, mins, secs;
1677 tmp_buf = va_arg(vp, unsigned char *);
1678 buf_len = va_arg(vp, SilcUInt32);
1680 if (!tmp_buf || !buf_len) {
1681 printtext(server, NULL, MSGLEVEL_CRAP, "No statistics available");
1685 /* Get statistics structure */
1686 silc_buffer_set(&buf, tmp_buf, buf_len);
1687 silc_buffer_unformat(&buf,
1688 SILC_STR_UI_INT(&starttime),
1689 SILC_STR_UI_INT(&uptime),
1690 SILC_STR_UI_INT(&my_clients),
1691 SILC_STR_UI_INT(&my_channels),
1692 SILC_STR_UI_INT(&my_server_ops),
1693 SILC_STR_UI_INT(&my_router_ops),
1694 SILC_STR_UI_INT(&cell_clients),
1695 SILC_STR_UI_INT(&cell_channels),
1696 SILC_STR_UI_INT(&cell_servers),
1697 SILC_STR_UI_INT(&clients),
1698 SILC_STR_UI_INT(&channels),
1699 SILC_STR_UI_INT(&servers),
1700 SILC_STR_UI_INT(&routers),
1701 SILC_STR_UI_INT(&server_ops),
1702 SILC_STR_UI_INT(&router_ops),
1705 tmptime = silc_get_time(starttime);
1706 printformat_module("fe-common/silc", server, NULL,
1707 MSGLEVEL_CRAP, SILCTXT_STATS,
1708 "Local server start time", tmptime);
1710 days = uptime / (24 * 60 * 60);
1711 uptime -= days * (24 * 60 * 60);
1712 hours = uptime / (60 * 60);
1713 uptime -= hours * (60 * 60);
1715 uptime -= mins * 60;
1717 snprintf(tmp, sizeof(tmp) - 1, "%d days %d hours %d mins %d secs",
1718 days, hours, mins, secs);
1719 printformat_module("fe-common/silc", server, NULL,
1720 MSGLEVEL_CRAP, SILCTXT_STATS,
1721 "Local server uptime", tmp);
1723 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)my_clients);
1724 printformat_module("fe-common/silc", server, NULL,
1725 MSGLEVEL_CRAP, SILCTXT_STATS,
1726 "Local server clients", tmp);
1728 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)my_channels);
1729 printformat_module("fe-common/silc", server, NULL,
1730 MSGLEVEL_CRAP, SILCTXT_STATS,
1731 "Local server channels", tmp);
1733 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)my_server_ops);
1734 printformat_module("fe-common/silc", server, NULL,
1735 MSGLEVEL_CRAP, SILCTXT_STATS,
1736 "Local server operators", tmp);
1738 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)my_router_ops);
1739 printformat_module("fe-common/silc", server, NULL,
1740 MSGLEVEL_CRAP, SILCTXT_STATS,
1741 "Local router operators", tmp);
1743 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cell_clients);
1744 printformat_module("fe-common/silc", server, NULL,
1745 MSGLEVEL_CRAP, SILCTXT_STATS,
1746 "Local cell clients", tmp);
1748 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cell_channels);
1749 printformat_module("fe-common/silc", server, NULL,
1750 MSGLEVEL_CRAP, SILCTXT_STATS,
1751 "Local cell channels", tmp);
1753 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cell_servers);
1754 printformat_module("fe-common/silc", server, NULL,
1755 MSGLEVEL_CRAP, SILCTXT_STATS,
1756 "Local cell servers", tmp);
1758 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)clients);
1759 printformat_module("fe-common/silc", server, NULL,
1760 MSGLEVEL_CRAP, SILCTXT_STATS,
1761 "Total clients", tmp);
1763 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)channels);
1764 printformat_module("fe-common/silc", server, NULL,
1765 MSGLEVEL_CRAP, SILCTXT_STATS,
1766 "Total channels", tmp);
1768 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)servers);
1769 printformat_module("fe-common/silc", server, NULL,
1770 MSGLEVEL_CRAP, SILCTXT_STATS,
1771 "Total servers", tmp);
1773 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)routers);
1774 printformat_module("fe-common/silc", server, NULL,
1775 MSGLEVEL_CRAP, SILCTXT_STATS,
1776 "Total routers", tmp);
1778 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)server_ops);
1779 printformat_module("fe-common/silc", server, NULL,
1780 MSGLEVEL_CRAP, SILCTXT_STATS,
1781 "Total server operators", tmp);
1783 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)router_ops);
1784 printformat_module("fe-common/silc", server, NULL,
1785 MSGLEVEL_CRAP, SILCTXT_STATS,
1786 "Total router operators", tmp);
1797 SilcClientConnection conn;
1803 SilcSKEPKType pk_type;
1804 SilcVerifyPublicKey completion;
1808 static void verify_public_key_completion(const char *line, void *context)
1810 PublicKeyVerify verify = (PublicKeyVerify)context;
1812 if (line[0] == 'Y' || line[0] == 'y') {
1813 /* Call the completion */
1814 if (verify->completion)
1815 verify->completion(TRUE, verify->context);
1817 /* Save the key for future checking */
1818 silc_pkcs_save_public_key_data(verify->filename, verify->pk,
1819 verify->pk_len, SILC_PKCS_FILE_PEM);
1821 /* Call the completion */
1822 if (verify->completion)
1823 verify->completion(FALSE, verify->context);
1825 printformat_module("fe-common/silc", NULL, NULL,
1826 MSGLEVEL_CRAP, SILCTXT_PUBKEY_DISCARD,
1827 verify->entity_name ? verify->entity_name :
1831 silc_free(verify->filename);
1832 silc_free(verify->entity);
1833 silc_free(verify->entity_name);
1834 silc_free(verify->pk);
1838 /* Internal routine to verify public key. If the `completion' is provided
1839 it will be called to indicate whether public was verified or not. For
1840 server/router public key this will check for filename that includes the
1841 remote host's IP address and remote host's hostname. */
1844 silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
1845 const char *name, SilcSocketType conn_type,
1846 unsigned char *pk, SilcUInt32 pk_len,
1847 SilcSKEPKType pk_type,
1848 SilcVerifyPublicKey completion, void *context)
1851 char file[256], filename[256], filename2[256], *ipf, *hostf = NULL;
1852 char *fingerprint, *babbleprint, *format;
1855 char *entity = ((conn_type == SILC_SOCKET_TYPE_SERVER ||
1856 conn_type == SILC_SOCKET_TYPE_ROUTER) ?
1857 "server" : "client");
1858 PublicKeyVerify verify;
1860 if (pk_type != SILC_SKE_PK_TYPE_SILC) {
1861 printformat_module("fe-common/silc", NULL, NULL,
1862 MSGLEVEL_CRAP, SILCTXT_PUBKEY_UNSUPPORTED,
1865 completion(FALSE, context);
1869 pw = getpwuid(getuid());
1872 completion(FALSE, context);
1876 memset(filename, 0, sizeof(filename));
1877 memset(filename2, 0, sizeof(filename2));
1878 memset(file, 0, sizeof(file));
1880 if (conn_type == SILC_SOCKET_TYPE_SERVER ||
1881 conn_type == SILC_SOCKET_TYPE_ROUTER) {
1883 snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
1884 conn->sock->ip, conn->sock->port);
1885 snprintf(filename, sizeof(filename) - 1, "%s/%skeys/%s",
1886 get_irssi_dir(), entity, file);
1888 snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
1889 conn->sock->hostname, conn->sock->port);
1890 snprintf(filename2, sizeof(filename2) - 1, "%s/%skeys/%s",
1891 get_irssi_dir(), entity, file);
1896 snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
1897 name, conn->sock->port);
1898 snprintf(filename, sizeof(filename) - 1, "%s/%skeys/%s",
1899 get_irssi_dir(), entity, file);
1904 /* Replace all whitespaces with `_'. */
1905 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
1906 for (i = 0; i < strlen(fingerprint); i++)
1907 if (fingerprint[i] == ' ')
1908 fingerprint[i] = '_';
1910 snprintf(file, sizeof(file) - 1, "%skey_%s.pub", entity, fingerprint);
1911 snprintf(filename, sizeof(filename) - 1, "%s/%skeys/%s",
1912 get_irssi_dir(), entity, file);
1913 silc_free(fingerprint);
1918 /* Take fingerprint of the public key */
1919 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
1920 babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
1922 verify = silc_calloc(1, sizeof(*verify));
1923 verify->client = client;
1924 verify->conn = conn;
1925 verify->filename = strdup(ipf);
1926 verify->entity = strdup(entity);
1927 verify->entity_name = (conn_type != SILC_SOCKET_TYPE_CLIENT ?
1928 (name ? strdup(name) : strdup(conn->sock->hostname))
1930 verify->pk = silc_calloc(pk_len, sizeof(*verify->pk));
1931 memcpy(verify->pk, pk, pk_len);
1932 verify->pk_len = pk_len;
1933 verify->pk_type = pk_type;
1934 verify->completion = completion;
1935 verify->context = context;
1937 /* Check whether this key already exists */
1938 if (stat(ipf, &st) < 0 && (!hostf || stat(hostf, &st) < 0)) {
1939 /* Key does not exist, ask user to verify the key and save it */
1941 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1942 SILCTXT_PUBKEY_RECEIVED,verify->entity_name ?
1943 verify->entity_name : entity);
1944 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1945 SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint);
1946 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1947 SILCTXT_PUBKEY_BABBLEPRINT, babbleprint);
1948 format = format_get_text("fe-common/silc", NULL, NULL, NULL,
1949 SILCTXT_PUBKEY_ACCEPT);
1950 keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion,
1953 silc_free(fingerprint);
1956 /* The key already exists, verify it. */
1957 SilcPublicKey public_key;
1958 unsigned char *encpk;
1959 SilcUInt32 encpk_len;
1961 /* Load the key file, try for both IP filename and hostname filename */
1962 if (!silc_pkcs_load_public_key(ipf, &public_key,
1963 SILC_PKCS_FILE_PEM) &&
1964 !silc_pkcs_load_public_key(ipf, &public_key,
1965 SILC_PKCS_FILE_BIN) &&
1966 (!hostf || (!silc_pkcs_load_public_key(hostf, &public_key,
1967 SILC_PKCS_FILE_PEM) &&
1968 !silc_pkcs_load_public_key(hostf, &public_key,
1969 SILC_PKCS_FILE_BIN)))) {
1970 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1971 SILCTXT_PUBKEY_RECEIVED,verify->entity_name ?
1972 verify->entity_name : entity);
1973 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1974 SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint);
1975 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1976 SILCTXT_PUBKEY_BABBLEPRINT, babbleprint);
1977 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1978 SILCTXT_PUBKEY_COULD_NOT_LOAD, entity);
1979 format = format_get_text("fe-common/silc", NULL, NULL, NULL,
1980 SILCTXT_PUBKEY_ACCEPT_ANYWAY);
1981 keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion,
1984 silc_free(fingerprint);
1988 /* Encode the key data */
1989 encpk = silc_pkcs_public_key_encode(public_key, &encpk_len);
1991 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1992 SILCTXT_PUBKEY_RECEIVED,verify->entity_name ?
1993 verify->entity_name : entity);
1994 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1995 SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint);
1996 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1997 SILCTXT_PUBKEY_BABBLEPRINT, babbleprint);
1998 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1999 SILCTXT_PUBKEY_MALFORMED, entity);
2000 format = format_get_text("fe-common/silc", NULL, NULL, NULL,
2001 SILCTXT_PUBKEY_ACCEPT_ANYWAY);
2002 keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion,
2005 silc_free(fingerprint);
2009 /* Compare the keys */
2010 if (memcmp(encpk, pk, encpk_len)) {
2011 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2012 SILCTXT_PUBKEY_RECEIVED,verify->entity_name ?
2013 verify->entity_name : entity);
2014 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2015 SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint);
2016 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2017 SILCTXT_PUBKEY_BABBLEPRINT, babbleprint);
2018 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2019 SILCTXT_PUBKEY_NO_MATCH, entity);
2020 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2021 SILCTXT_PUBKEY_MAYBE_EXPIRED, entity);
2022 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2023 SILCTXT_PUBKEY_MITM_ATTACK, entity);
2025 /* Ask user to verify the key and save it */
2026 format = format_get_text("fe-common/silc", NULL, NULL, NULL,
2027 SILCTXT_PUBKEY_ACCEPT_ANYWAY);
2028 keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion,
2031 silc_free(fingerprint);
2035 /* Local copy matched */
2037 completion(TRUE, context);
2038 silc_free(fingerprint);
2042 /* Verifies received public key. The `conn_type' indicates which entity
2043 (server, client etc.) has sent the public key. If user decides to trust
2044 the key may be saved as trusted public key for later use. The
2045 `completion' must be called after the public key has been verified. */
2048 silc_verify_public_key(SilcClient client, SilcClientConnection conn,
2049 SilcSocketType conn_type, unsigned char *pk,
2050 SilcUInt32 pk_len, SilcSKEPKType pk_type,
2051 SilcVerifyPublicKey completion, void *context)
2053 silc_verify_public_key_internal(client, conn, NULL, conn_type, pk,
2055 completion, context);
2058 /* Asks passphrase from user on the input line. */
2061 SilcAskPassphrase completion;
2065 void ask_passphrase_completion(const char *passphrase, void *context)
2067 AskPassphrase p = (AskPassphrase)context;
2068 if (passphrase && passphrase[0] == '\0')
2070 p->completion((unsigned char *)passphrase,
2071 passphrase ? strlen(passphrase) : 0, p->context);
2075 void silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
2076 SilcAskPassphrase completion, void *context)
2078 AskPassphrase p = silc_calloc(1, sizeof(*p));
2079 p->completion = completion;
2080 p->context = context;
2082 keyboard_entry_redirect((SIGNAL_FUNC)ask_passphrase_completion,
2083 "Passphrase: ", ENTRY_REDIRECT_FLAG_HIDDEN, p);
2087 SilcGetAuthMeth completion;
2089 } *InternalGetAuthMethod;
2091 /* Callback called when we've received the authentication method information
2092 from the server after we've requested it. This will get the authentication
2093 data from the user if needed. */
2095 static void silc_get_auth_method_callback(SilcClient client,
2096 SilcClientConnection conn,
2097 SilcAuthMethod auth_meth,
2100 InternalGetAuthMethod internal = (InternalGetAuthMethod)context;
2102 SILC_LOG_DEBUG(("Start"));
2104 switch (auth_meth) {
2105 case SILC_AUTH_NONE:
2106 /* No authentication required. */
2107 (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
2109 case SILC_AUTH_PASSWORD:
2111 /* Check whether we find the password for this server in our
2112 configuration. If not, then don't provide so library will ask
2113 it from the user. */
2114 SERVER_SETUP_REC *setup = server_setup_find_port(conn->remote_host,
2116 if (!setup || !setup->password) {
2117 (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
2121 (*internal->completion)(TRUE, auth_meth, setup->password,
2122 strlen(setup->password), internal->context);
2125 case SILC_AUTH_PUBLIC_KEY:
2126 /* Do not get the authentication data now, the library will generate
2127 it using our default key, if we do not provide it here. */
2128 /* XXX In the future when we support multiple local keys and multiple
2129 local certificates we will need to ask from user which one to use. */
2130 (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
2134 silc_free(internal);
2137 /* Find authentication method and authentication data by hostname and
2138 port. The hostname may be IP address as well. The found authentication
2139 method and authentication data is returned to `auth_meth', `auth_data'
2140 and `auth_data_len'. The function returns TRUE if authentication method
2141 is found and FALSE if not. `conn' may be NULL. */
2143 void silc_get_auth_method(SilcClient client, SilcClientConnection conn,
2144 char *hostname, SilcUInt16 port,
2145 SilcGetAuthMeth completion, void *context)
2147 InternalGetAuthMethod internal;
2149 SILC_LOG_DEBUG(("Start"));
2151 /* If we do not have this connection configured by the user in a
2152 configuration file then resolve the authentication method from the
2153 server for this session. */
2154 internal = silc_calloc(1, sizeof(*internal));
2155 internal->completion = completion;
2156 internal->context = context;
2158 silc_client_request_authentication_method(client, conn,
2159 silc_get_auth_method_callback,
2163 /* Notifies application that failure packet was received. This is called
2164 if there is some protocol active in the client. The `protocol' is the
2165 protocol context. The `failure' is opaque pointer to the failure
2166 indication. Note, that the `failure' is protocol dependant and application
2167 must explicitly cast it to correct type. Usually `failure' is 32 bit
2168 failure type (see protocol specs for all protocol failure types). */
2170 void silc_failure(SilcClient client, SilcClientConnection conn,
2171 SilcProtocol protocol, void *failure)
2173 SILC_LOG_DEBUG(("Start"));
2175 if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
2176 SilcSKEStatus status = (SilcSKEStatus)failure;
2178 if (status == SILC_SKE_STATUS_BAD_VERSION)
2179 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2180 SILCTXT_KE_BAD_VERSION);
2181 if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY)
2182 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2183 SILCTXT_KE_UNSUPPORTED_PUBLIC_KEY);
2184 if (status == SILC_SKE_STATUS_UNKNOWN_GROUP)
2185 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2186 SILCTXT_KE_UNKNOWN_GROUP);
2187 if (status == SILC_SKE_STATUS_UNKNOWN_CIPHER)
2188 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2189 SILCTXT_KE_UNKNOWN_CIPHER);
2190 if (status == SILC_SKE_STATUS_UNKNOWN_PKCS)
2191 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2192 SILCTXT_KE_UNKNOWN_PKCS);
2193 if (status == SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION)
2194 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2195 SILCTXT_KE_UNKNOWN_HASH_FUNCTION);
2196 if (status == SILC_SKE_STATUS_UNKNOWN_HMAC)
2197 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2198 SILCTXT_KE_UNKNOWN_HMAC);
2199 if (status == SILC_SKE_STATUS_INCORRECT_SIGNATURE)
2200 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2201 SILCTXT_KE_INCORRECT_SIGNATURE);
2202 if (status == SILC_SKE_STATUS_INVALID_COOKIE)
2203 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2204 SILCTXT_KE_INVALID_COOKIE);
2207 if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
2208 SilcUInt32 err = (SilcUInt32)failure;
2210 if (err == SILC_AUTH_FAILED)
2211 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2212 SILCTXT_AUTH_FAILED);
2216 /* Asks whether the user would like to perform the key agreement protocol.
2217 This is called after we have received an key agreement packet or an
2218 reply to our key agreement packet. This returns TRUE if the user wants
2219 the library to perform the key agreement protocol and FALSE if it is not
2220 desired (application may start it later by calling the function
2221 silc_client_perform_key_agreement). */
2223 bool silc_key_agreement(SilcClient client, SilcClientConnection conn,
2224 SilcClientEntry client_entry, const char *hostname,
2225 SilcUInt16 port, SilcKeyAgreementCallback *completion,
2230 SILC_LOG_DEBUG(("Start"));
2232 /* We will just display the info on the screen and return FALSE and user
2233 will have to start the key agreement with a command. */
2236 snprintf(portstr, sizeof(portstr) - 1, "%d", port);
2239 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2240 SILCTXT_KEY_AGREEMENT_REQUEST, client_entry->nickname);
2242 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2243 SILCTXT_KEY_AGREEMENT_REQUEST_HOST,
2244 client_entry->nickname, hostname, portstr);
2252 /* Notifies application that file transfer protocol session is being
2253 requested by the remote client indicated by the `client_entry' from
2254 the `hostname' and `port'. The `session_id' is the file transfer
2255 session and it can be used to either accept or reject the file
2256 transfer request, by calling the silc_client_file_receive or
2257 silc_client_file_close, respectively. */
2259 void silc_ftp(SilcClient client, SilcClientConnection conn,
2260 SilcClientEntry client_entry, SilcUInt32 session_id,
2261 const char *hostname, SilcUInt16 port)
2263 SILC_SERVER_REC *server;
2265 FtpSession ftp = NULL;
2267 SILC_LOG_DEBUG(("Start"));
2269 server = conn->context;
2271 silc_dlist_start(server->ftp_sessions);
2272 while ((ftp = silc_dlist_get(server->ftp_sessions)) != SILC_LIST_END) {
2273 if (ftp->client_entry == client_entry &&
2274 ftp->session_id == session_id) {
2275 server->current_session = ftp;
2279 if (ftp == SILC_LIST_END) {
2280 ftp = silc_calloc(1, sizeof(*ftp));
2281 ftp->client_entry = client_entry;
2282 ftp->session_id = session_id;
2285 silc_dlist_add(server->ftp_sessions, ftp);
2286 server->current_session = ftp;
2290 snprintf(portstr, sizeof(portstr) - 1, "%d", port);
2293 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2294 SILCTXT_FILE_REQUEST, client_entry->nickname);
2296 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2297 SILCTXT_FILE_REQUEST_HOST,
2298 client_entry->nickname, hostname, portstr);
2301 /* Delivers SILC session detachment data indicated by `detach_data' to the
2302 application. If application has issued SILC_COMMAND_DETACH command
2303 the client session in the SILC network is not quit. The client remains
2304 in the network but is detached. The detachment data may be used later
2305 to resume the session in the SILC Network. The appliation is
2306 responsible of saving the `detach_data', to for example in a file.
2308 The detachment data can be given as argument to the functions
2309 silc_client_connect_to_server, or silc_client_add_connection when
2310 creating connection to remote server, inside SilcClientConnectionParams
2311 structure. If it is provided the client library will attempt to resume
2312 the session in the network. After the connection is created
2313 successfully, the application is responsible of setting the user
2314 interface for user into the same state it was before detaching (showing
2315 same channels, channel modes, etc). It can do this by fetching the
2316 information (like joined channels) from the client library. */
2319 silc_detach(SilcClient client, SilcClientConnection conn,
2320 const unsigned char *detach_data, SilcUInt32 detach_data_len)
2324 /* Save the detachment data to file. */
2326 memset(file, 0, sizeof(file));
2327 snprintf(file, sizeof(file) - 1, "%s/session", get_irssi_dir());
2328 silc_file_writefile(file, detach_data, detach_data_len);
2332 /* SILC client operations */
2333 SilcClientOperations ops = {
2335 silc_channel_message,
2336 silc_private_message,
2342 silc_get_auth_method,
2343 silc_verify_public_key,
2344 silc_ask_passphrase,