X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Firssi%2Fsrc%2Fsilc%2Fcore%2Fclient_ops.c;fp=apps%2Firssi%2Fsrc%2Fsilc%2Fcore%2Fclient_ops.c;h=0000000000000000000000000000000000000000;hb=72c2de619079457f7a68100eb13385275a424a23;hp=5da2cea29017314d1cdee99b6bd993928fe992be;hpb=e7b6c157b80152bf9fb9266e6bdd93f9fb0db776;p=runtime.git diff --git a/apps/irssi/src/silc/core/client_ops.c b/apps/irssi/src/silc/core/client_ops.c deleted file mode 100644 index 5da2cea2..00000000 --- a/apps/irssi/src/silc/core/client_ops.c +++ /dev/null @@ -1,2876 +0,0 @@ -/* - - client_ops.c - - Author: Pekka Riikonen - - Copyright (C) 2001 - 2007 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#include "module.h" -#include "chat-protocols.h" -#include "args.h" - -#include "chatnets.h" -#include "servers-setup.h" -#include "channels-setup.h" -#include "silc-servers.h" -#include "silc-channels.h" -#include "silc-queries.h" -#include "silc-nicklist.h" -#include "silc-cmdqueue.h" - -#include "signals.h" -#include "levels.h" -#include "settings.h" -#include "ignore.h" -#include "special-vars.h" -#include "fe-common/core/printtext.h" -#include "fe-common/core/fe-channels.h" -#include "fe-common/core/keyboard.h" -#include "fe-common/core/window-items.h" -#include "fe-common/silc/module-formats.h" - -#include "core.h" - -static void -silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, - const char *name, SilcConnectionType conn_type, - SilcPublicKey public_key, - SilcVerifyPublicKey completion, void *context); - -char *silc_get_session_filename(SILC_SERVER_REC *server) -{ - char *file, *expanded; - - expanded = parse_special_string(settings_get_str("session_filename"), - SERVER(server), NULL, "", NULL, 0); - - file = silc_calloc(1, strlen(expanded) + 255); - snprintf(file, strlen(expanded) + 255, "%s/%s", get_irssi_dir(), expanded); - free(expanded); - - return file; -} - -static void silc_get_umode_string(SilcUInt32 mode, char *buf, - SilcUInt32 buf_size) -{ - if ((mode & SILC_UMODE_SERVER_OPERATOR) || - (mode & SILC_UMODE_ROUTER_OPERATOR)) { - strcat(buf, (mode & SILC_UMODE_SERVER_OPERATOR) ? - "[server operator]" : - (mode & SILC_UMODE_ROUTER_OPERATOR) ? - "[SILC operator]" : "[unknown mode]"); - } - if (mode & SILC_UMODE_GONE) - strcat(buf, " [away]"); - if (mode & SILC_UMODE_INDISPOSED) - strcat(buf, " [indisposed]"); - if (mode & SILC_UMODE_BUSY) - strcat(buf, " [busy]"); - if (mode & SILC_UMODE_PAGE) - strcat(buf, " [page to reach]"); - if (mode & SILC_UMODE_HYPER) - strcat(buf, " [hyper active]"); - if (mode & SILC_UMODE_ROBOT) - strcat(buf, " [robot]"); - if (mode & SILC_UMODE_ANONYMOUS) - strcat(buf, " [anonymous]"); - if (mode & SILC_UMODE_BLOCK_PRIVMSG) - strcat(buf, " [blocks private messages]"); - if (mode & SILC_UMODE_DETACHED) - strcat(buf, " [detached]"); - if (mode & SILC_UMODE_REJECT_WATCHING) - strcat(buf, " [rejects watching]"); - if (mode & SILC_UMODE_BLOCK_INVITE) - strcat(buf, " [blocks invites]"); -} - -/* converts an utf-8 string to current locale */ -char * silc_convert_utf8_string(const char *str) -{ - int message_len = (str != NULL ? strlen(str) : 0); - char *message = silc_calloc(message_len + 1, sizeof(*message)); - - g_return_val_if_fail(message != NULL, NULL); - - if (str == NULL) { - *message = 0; - return message; - } - - if (!silc_term_utf8() && silc_utf8_valid(str, message_len)) - silc_utf8_decode(str, message_len, SILC_STRING_LOCALE, - message, message_len); - else - strcpy(message, str); - - return message; -} - -/* print "nick appears as" message to every channel of a server */ -static void -silc_print_nick_change_channel(SILC_SERVER_REC *server, const char *channel, - const char *newnick, const char *oldnick, - const char *address) -{ - if (ignore_check(SERVER(server), oldnick, address, - channel, newnick, MSGLEVEL_NICKS)) - return; - - printformat_module("fe-common/silc", server, channel, MSGLEVEL_NICKS, - SILCTXT_CHANNEL_APPEARS, - oldnick, newnick, channel, address); -} - -static void -silc_print_nick_change(SILC_SERVER_REC *server, const char *newnick, - const char *oldnick, const char *address) -{ - GSList *tmp, *windows; - - /* Print to each channel/query where the nick is. - Don't print more than once to the same window. */ - windows = NULL; - - for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { - CHANNEL_REC *channel = tmp->data; - WINDOW_REC *window = window_item_window((WI_ITEM_REC *) channel); - - if (nicklist_find(channel, newnick) == NULL || - g_slist_find(windows, window) != NULL) - continue; - - windows = g_slist_append(windows, window); - silc_print_nick_change_channel(server, channel->visible_name, - newnick, oldnick, address); - } - - g_slist_free(windows); -} - -static void silc_parse_channel_public_keys(SILC_SERVER_REC *server, - SilcChannelEntry channel_entry, - SilcDList channel_pubkeys) -{ - SilcArgumentDecodedList e; - SilcPublicKey pubkey; - SilcSILCPublicKey silc_pubkey; - SilcUInt32 pk_len, type; - unsigned char *pk; - char *fingerprint, *babbleprint; - int c = 1; - - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_PK_LIST, - channel_entry->channel_name); - - silc_dlist_start(channel_pubkeys); - while ((e = silc_dlist_get(channel_pubkeys))) { - pubkey = e->argument; - type = e->arg_type; - - if (silc_pkcs_get_type(pubkey) != SILC_PKCS_SILC) - continue; - - pk = silc_pkcs_public_key_encode(NULL, pubkey, &pk_len); - if (!pk) - continue; - - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - silc_pubkey = silc_pkcs_public_key_get_pkcs(SILC_PKCS_SILC, pubkey); - - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_PK_LIST_ENTRY, - c++, channel_entry->channel_name, - type == 0x00 ? "Added" : "Removed", - silc_pubkey->identifier.realname ? - silc_pubkey->identifier.realname : "", - fingerprint, babbleprint); - - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); - } -} - -void silc_say(SilcClient client, SilcClientConnection conn, - SilcClientMessageType type, char *msg, ...) -{ - SILC_SERVER_REC *server; - va_list va; - char *str; - - server = conn == NULL ? NULL : conn->context; - - va_start(va, msg); - str = g_strdup_vprintf(msg, va); - printtext(server, NULL, MSGLEVEL_CRAP, "%s", str); - g_free(str); - va_end(va); -} - -void silc_say_error(char *msg, ...) -{ - va_list va; - char *str; - - va_start(va, msg); - str = g_strdup_vprintf(msg, va); - printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "%s", str); - - g_free(str); - va_end(va); -} - -void static verify_message_signature_verified(SilcBool success, - void *context) -{ - *(SilcBool *)context = success; -} - -/* Try to verify a message using locally stored public key data */ - -int verify_message_signature(SilcClientEntry sender, - SilcMessagePayload message) -{ - SilcPublicKey pk; - char file[256], filename[256]; - char *fingerprint, *fingerprint2; - const unsigned char *pk_data; - SilcUInt32 pk_datalen; - struct stat st; - int ret = SILC_MSG_SIGNED_VERIFIED, i; - SilcBool verified = FALSE; - - /* get public key from the signature payload and compare it with the - one stored in the client entry */ - pk = silc_message_signed_get_public_key(message, &pk_data, &pk_datalen); - - if (pk != NULL) { - fingerprint = silc_hash_fingerprint(NULL, pk_data, pk_datalen); - - if (sender->fingerprint[0]) { - fingerprint2 = silc_fingerprint(sender->fingerprint, - sizeof(sender->fingerprint)); - if (strcmp(fingerprint, fingerprint2)) { - /* since the public key differs from the senders public key, the - verification _failed_ */ - silc_pkcs_public_key_free(pk); - silc_free(fingerprint); - ret = SILC_MSG_SIGNED_UNKNOWN; - } - silc_free(fingerprint2); - } - } else if (sender->fingerprint[0]) - fingerprint = silc_fingerprint(sender->fingerprint, - sizeof(sender->fingerprint)); - else - /* no idea, who or what signed that message ... */ - return SILC_MSG_SIGNED_UNKNOWN; - - /* search our local client key cache */ - for (i = 0; i < strlen(fingerprint); i++) - if (fingerprint[i] == ' ') - fingerprint[i] = '_'; - - snprintf(file, sizeof(file) - 1, "clientkey_%s.pub", fingerprint); - snprintf(filename, sizeof(filename) - 1, "%s/clientkeys/%s", - get_irssi_dir(), file); - silc_free(fingerprint); - - if (stat(filename, &st) < 0) - /* we don't have the public key cached ... use the one from the sig */ - ret = SILC_MSG_SIGNED_UNKNOWN; - else { - SilcPublicKey cached_pk=NULL; - - /* try to load the file */ - if (!silc_pkcs_load_public_key(filename, SILC_PKCS_ANY, &cached_pk)) { - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_COULD_NOT_LOAD, "client"); - if (pk == NULL) - return SILC_MSG_SIGNED_UNKNOWN; - else - ret = SILC_MSG_SIGNED_UNKNOWN; - } - - if (cached_pk) { - if (pk) - silc_pkcs_public_key_free(pk); - pk = cached_pk; - } - } - - /* the public key is now in pk, our "level of trust" in ret */ - if (pk) { - silc_message_signed_verify(message, pk, sha1hash, - verify_message_signature_verified, &verified); - if (!verified) - ret = SILC_MSG_SIGNED_FAILED; - } - - if (pk) - silc_pkcs_public_key_free(pk); - - return ret; -} - -char *silc_unescape_data(const char *escaped_data, SilcUInt32 *length) -{ - char *data, *ptr; - int i = 0, j = 0, len = strlen(escaped_data); - - data = silc_calloc(len, sizeof(char)); - - while (i < len) { - ptr = memchr(escaped_data + i, 1, len - i); - if (ptr) { - int inc = (ptr - escaped_data) - i; - memcpy(data + j, escaped_data + i, inc); - j += inc; - i += inc + 2; - data[j++] = *(ptr + 1) - 1; - } else { - memcpy(data + j, escaped_data + i, len - i); - j += (len - i); - break; - } - } - - *length = j; - return data; -} - -char *silc_escape_data(const char *data, SilcUInt32 len) -{ - char *escaped_data, *ptr, *ptr0, *ptr1; - int i = 0, j = 0; - - escaped_data = silc_calloc(2 * len, sizeof(char)); - - while (i < len) { - ptr0 = memchr(data + i, 0, len - i); - ptr1 = memchr(data + i, 1, len - i); - - ptr = (ptr0 < ptr1 ? (ptr0 ? ptr0 : ptr1) : (ptr1 ? ptr1 : ptr0)); - - if (ptr) { - int inc = (ptr - data) - i; - if (inc) - memcpy(escaped_data + j, data + i, inc); - j += inc; - i += inc; - escaped_data[j++] = 1; - escaped_data[j++] = *(data + i++) + 1; - } else { - memcpy(escaped_data + j, data + i, len - i); - j += (len - i); - break; - } - } - - return escaped_data; -} - -void silc_emit_mime_sig(SILC_SERVER_REC *server, WI_ITEM_REC *item, - const char *data, SilcUInt32 data_len, - const char *nick, int verified) -{ - char *escaped_data; - - escaped_data = silc_escape_data(data, data_len); - - signal_emit("mime", 5, server, item, escaped_data, nick, verified); - - silc_free(escaped_data); -} - - -/* Message for a channel. The `sender' is the nickname of the sender - received in the packet. The `channel_name' is the name of the channel. */ - -void silc_channel_message(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcChannelEntry channel, - SilcMessagePayload payload, - SilcChannelPrivateKey key, - SilcMessageFlags flags, const unsigned char *message, - SilcUInt32 message_len) -{ - SILC_SERVER_REC *server; - SILC_NICK_REC *nick; - SILC_CHANNEL_REC *chanrec; - int verified = 0; - - SILC_LOG_DEBUG(("Start")); - - if (!message) - return; - - server = conn == NULL ? NULL : conn->context; - chanrec = silc_channel_find_entry(server, channel); - if (!chanrec) - return; - - nick = silc_nicklist_find(chanrec, sender); - if (!nick) { - /* We didn't find client but it clearly exists, add it. */ - SilcChannelUser chu = silc_client_on_channel(channel, sender); - if (chu) - nick = silc_nicklist_insert(chanrec, chu, FALSE); - if (!nick) - return; - } - - /* If the messages is digitally signed, verify it, if possible. */ - if (flags & SILC_MESSAGE_FLAG_SIGNED) { - if (!settings_get_bool("ignore_message_signatures")) { - verified = verify_message_signature(sender, payload); - } else { - flags &= ~SILC_MESSAGE_FLAG_SIGNED; - } - } - - if (flags & SILC_MESSAGE_FLAG_DATA) { - silc_emit_mime_sig(server, (WI_ITEM_REC *)chanrec, message, message_len, - nick == NULL ? NULL : nick->nick, - flags & SILC_MESSAGE_FLAG_SIGNED ? verified : -1); - message = NULL; - } - - if (!message) - return; - - if (flags & SILC_MESSAGE_FLAG_ACTION) - if(flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) { - char tmp[256], *cp, *dm = NULL; - memset(tmp, 0, sizeof(tmp)); - cp = tmp; - if(message_len > sizeof(tmp) - 1) { - dm = silc_calloc(message_len + 1, sizeof(*dm)); - cp = dm; - } - silc_utf8_decode(message, message_len, SILC_STRING_LOCALE, - cp, message_len); - if (flags & SILC_MESSAGE_FLAG_SIGNED) - signal_emit("message silc signed_action", 6, server, cp, nick->nick, - nick->host, channel->channel_name, verified); - else - signal_emit("message silc action", 5, server, cp, nick->nick, - nick->host, channel->channel_name); - silc_free(dm); - } else { - if (flags & SILC_MESSAGE_FLAG_SIGNED) - signal_emit("message silc signed_action", 6, server, message, - nick->nick, nick->host, channel->channel_name, verified); - else - signal_emit("message silc action", 5, server, message, - nick->nick, nick->host, channel->channel_name); - } - else if (flags & SILC_MESSAGE_FLAG_NOTICE) - if(flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) { - char tmp[256], *cp, *dm = NULL; - memset(tmp, 0, sizeof(tmp)); - cp = tmp; - if(message_len > sizeof(tmp) - 1) { - dm = silc_calloc(message_len + 1, sizeof(*dm)); - cp = dm; - } - silc_utf8_decode(message, message_len, SILC_STRING_LOCALE, - cp, message_len); - if (flags & SILC_MESSAGE_FLAG_SIGNED) - signal_emit("message silc signed_notice", 6, server, cp, nick->nick, - nick->host, channel->channel_name, verified); - else - signal_emit("message silc notice", 5, server, cp, nick->nick, - nick->host, channel->channel_name); - silc_free(dm); - } else { - if (flags & SILC_MESSAGE_FLAG_SIGNED) - signal_emit("message silc signed_notice", 6, server, message, - nick->nick, nick->host, channel->channel_name, verified); - else - signal_emit("message silc notice", 5, server, message, - nick->nick, nick->host, channel->channel_name); - } - else { - if (flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) { - char tmp[256], *cp, *dm = NULL; - - memset(tmp, 0, sizeof(tmp)); - cp = tmp; - if (message_len > sizeof(tmp) - 1) { - dm = silc_calloc(message_len + 1, sizeof(*dm)); - cp = dm; - } - - silc_utf8_decode(message, message_len, SILC_STRING_LOCALE, - cp, message_len); - if (flags & SILC_MESSAGE_FLAG_SIGNED) - signal_emit("message signed_public", 6, server, cp, - nick == NULL ? "[]" : nick->nick, - nick == NULL ? "" : nick->host == NULL ? "" : nick->host, - chanrec->name, verified); - else - signal_emit("message public", 6, server, cp, - nick == NULL ? "[]" : nick->nick, - nick == NULL ? "" : nick->host == NULL ? "" : nick->host, - chanrec->name, nick); - silc_free(dm); - return; - } - - if (flags & SILC_MESSAGE_FLAG_SIGNED) - signal_emit("message signed_public", 6, server, message, - nick == NULL ? "[]" : nick->nick, - nick == NULL ? "" : nick->host == NULL ? "" : nick->host, - chanrec->name, verified); - else - signal_emit("message public", 6, server, message, - nick == NULL ? "[]" : nick->nick, - nick == NULL ? "" : nick->host == NULL ? "" : nick->host, - chanrec->name, nick); - } -} - -/* Private message to the client. The `sender' is the nickname of the - sender received in the packet. */ - -void silc_private_message(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcMessagePayload payload, - SilcMessageFlags flags, - const unsigned char *message, - SilcUInt32 message_len) -{ - SILC_SERVER_REC *server; - char userhost[256]; - int verified = 0; - - SILC_LOG_DEBUG(("Start")); - - server = conn == NULL ? NULL : conn->context; - memset(userhost, 0, sizeof(userhost)); - if (sender->username[0]) - snprintf(userhost, sizeof(userhost) - 1, "%s@%s", - sender->username, sender->hostname); - - /* If the messages is digitally signed, verify it, if possible. */ - if (flags & SILC_MESSAGE_FLAG_SIGNED) { - if (!settings_get_bool("ignore_message_signatures")) { - verified = verify_message_signature(sender, payload); - } else { - flags &= ~SILC_MESSAGE_FLAG_SIGNED; - } - } - - if (flags & SILC_MESSAGE_FLAG_DATA) { - silc_emit_mime_sig(server, - sender->nickname[0] ? - (WI_ITEM_REC *)query_find(SERVER(server), sender->nickname) : - NULL, - message, message_len, - sender->nickname[0] ? sender->nickname : "[]", - flags & SILC_MESSAGE_FLAG_SIGNED ? verified : -1); - message = NULL; - } - - if (!message) - return; - - if (flags & SILC_MESSAGE_FLAG_ACTION) - if(flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) { - char tmp[256], *cp, *dm = NULL; - memset(tmp, 0, sizeof(tmp)); - cp = tmp; - if(message_len > sizeof(tmp) - 1) { - dm = silc_calloc(message_len + 1, sizeof(*dm)); - cp = dm; - } - silc_utf8_decode(message, message_len, SILC_STRING_LOCALE, - cp, message_len); - if (flags & SILC_MESSAGE_FLAG_SIGNED) - signal_emit("message silc signed_private_action", 6, server, cp, - sender->nickname[0] ? sender->nickname : "[]", - sender->username[0] ? userhost : NULL, - NULL, verified); - else - signal_emit("message silc private_action", 5, server, cp, - sender->nickname[0] ? sender->nickname : "[]", - sender->username[0] ? userhost : NULL, NULL); - silc_free(dm); - } else { - if (flags & SILC_MESSAGE_FLAG_SIGNED) - signal_emit("message silc signed_private_action", 6, server, message, - sender->nickname[0] ? sender->nickname : "[]", - sender->username[0] ? userhost : NULL, - NULL, verified); - else - signal_emit("message silc private_action", 5, server, message, - sender->nickname[0] ? sender->nickname : "[]", - sender->username[0] ? userhost : NULL, NULL); - } - else if (flags & SILC_MESSAGE_FLAG_NOTICE) - if(flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) { - char tmp[256], *cp, *dm = NULL; - memset(tmp, 0, sizeof(tmp)); - cp = tmp; - if(message_len > sizeof(tmp) - 1) { - dm = silc_calloc(message_len + 1, sizeof(*dm)); - cp = dm; - } - silc_utf8_decode(message, message_len, SILC_STRING_LOCALE, - cp, message_len); - if (flags & SILC_MESSAGE_FLAG_SIGNED) - signal_emit("message silc signed_private_notice", 6, server, cp, - sender->nickname[0] ? sender->nickname : "[]", - sender->username[0] ? userhost : NULL, - NULL, verified); - else - signal_emit("message silc private_notice", 5, server, cp, - sender->nickname[0] ? sender->nickname : "[]", - sender->username[0] ? userhost : NULL, NULL); - silc_free(dm); - } else { - if (flags & SILC_MESSAGE_FLAG_SIGNED) - signal_emit("message silc signed_private_notice", 6, server, message, - sender->nickname[0] ? sender->nickname : "[]", - sender->username[0] ? userhost : NULL, - NULL, verified); - else - signal_emit("message silc private_notice", 5, server, message, - sender->nickname[0] ? sender->nickname : "[]", - sender->username[0] ? userhost : NULL, NULL); - } - else { - if (flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) { - char tmp[256], *cp, *dm = NULL; - - memset(tmp, 0, sizeof(tmp)); - cp = tmp; - if (message_len > sizeof(tmp) - 1) { - dm = silc_calloc(message_len + 1, sizeof(*dm)); - cp = dm; - } - - silc_utf8_decode(message, message_len, SILC_STRING_LOCALE, - cp, message_len); - if (flags & SILC_MESSAGE_FLAG_SIGNED) - signal_emit("message signed_private", 5, server, cp, - sender->nickname[0] ? sender->nickname : "[]", - sender->username[0] ? userhost : NULL, verified); - else - signal_emit("message private", 4, server, cp, - sender->nickname[0] ? sender->nickname : "[]", - sender->username[0] ? userhost : NULL); - silc_free(dm); - return; - } - - if (flags & SILC_MESSAGE_FLAG_SIGNED) - signal_emit("message signed_private", 5, server, message, - sender->nickname[0] ? sender->nickname : "[]", - sender->username[0] ? userhost : NULL, verified); - else - signal_emit("message private", 4, server, message, - sender->nickname[0] ? sender->nickname : "[]", - sender->username[0] ? userhost : NULL); - } -} - -/* Notify message to the client. The notify arguments are sent in the - same order as servers sends them. The arguments are same as received - from the server except for ID's. If ID is received application receives - the corresponding entry to the ID. For example, if Client ID is received - application receives SilcClientEntry. Also, if the notify type is - for channel the channel entry is sent to application (even if server - does not send it). */ - -void silc_notify(SilcClient client, SilcClientConnection conn, - SilcNotifyType type, ...) -{ - va_list va; - SILC_SERVER_REC *server; - SILC_CHANNEL_REC *chanrec; - SILC_NICK_REC *nickrec; - SilcClientEntry client_entry, client_entry2; - SilcChannelEntry channel, channel2; - SilcServerEntry server_entry; - SilcIdType idtype; - void *entry; - SilcUInt32 mode; - char buf[512]; - char *name, *tmp, *cipher, *hmac; - GSList *list1, *list_tmp; - SilcDList chpks, clients; - - SILC_LOG_DEBUG(("Start")); - - va_start(va, type); - - server = conn == NULL ? NULL : conn->context; - - switch(type) { - case SILC_NOTIFY_TYPE_NONE: - /* Some generic notice from server */ - printtext(server, NULL, MSGLEVEL_CRAP, "%s", (char *)va_arg(va, char *)); - break; - - case SILC_NOTIFY_TYPE_INVITE: - /* - * Invited or modified invite list. - */ - - SILC_LOG_DEBUG(("Notify: INVITE")); - - channel = va_arg(va, SilcChannelEntry); - name = va_arg(va, char *); - client_entry = va_arg(va, SilcClientEntry); - - silc_snprintf(buf, sizeof(buf) - 1, "%s@%s", - client_entry->username, client_entry->hostname); - signal_emit("message invite", 4, server, name, - client_entry->nickname, buf); - break; - - case SILC_NOTIFY_TYPE_JOIN: - /* - * Joined channel. - */ - - SILC_LOG_DEBUG(("Notify: JOIN")); - - client_entry = va_arg(va, SilcClientEntry); - channel = va_arg(va, SilcChannelEntry); - - if (client_entry == server->conn->local_entry) { - /* You joined to channel */ - chanrec = silc_channel_find(server, channel->channel_name); - if (chanrec == NULL) - chanrec = silc_channel_create(server, channel->channel_name, - channel->channel_name, TRUE); - if (!chanrec->joined) - chanrec->entry = channel; - } else { - chanrec = silc_channel_find_entry(server, channel); - if (chanrec != NULL) { - SilcChannelUser chu = silc_client_on_channel(channel, client_entry); - if (chu) - nickrec = silc_nicklist_insert(chanrec, chu, TRUE); - } - } - - memset(buf, 0, sizeof(buf)); - if (client_entry->username[0]) - snprintf(buf, sizeof(buf) - 1, "%s@%s", - client_entry->username, client_entry->hostname); - signal_emit("message join", 4, server, channel->channel_name, - client_entry->nickname, - !client_entry->username[0] ? "" : buf); - - /* If there are multiple same nicknames on channel now, tell it to user. */ - if (client_entry != server->conn->local_entry) { - char *nick, tmp[32]; - int count = 0; - - silc_client_nickname_parse(client, conn, client_entry->nickname, &nick); - clients = silc_client_get_clients_local(client, conn, nick, TRUE); - if (!clients || silc_dlist_count(clients) < 2) { - silc_free(nick); - silc_client_list_free(client, conn, clients); - break; - } - silc_dlist_start(clients); - while ((client_entry2 = silc_dlist_get(clients))) - if (silc_client_on_channel(channel, client_entry2)) - count++; - if (count > 1) { - silc_snprintf(tmp, sizeof(tmp), "%d", silc_dlist_count(clients)); - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_MANY_NICKS, - tmp, nick); - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_USER_APPEARS, - buf, client_entry->nickname); - } - silc_client_list_free(client, conn, clients); - silc_free(nick); - } - break; - - case SILC_NOTIFY_TYPE_LEAVE: - /* - * Left a channel. - */ - - SILC_LOG_DEBUG(("Notify: LEAVE")); - - client_entry = va_arg(va, SilcClientEntry); - channel = va_arg(va, SilcChannelEntry); - - memset(buf, 0, sizeof(buf)); - if (client_entry->username) - snprintf(buf, sizeof(buf) - 1, "%s@%s", - client_entry->username, client_entry->hostname); - signal_emit("message part", 5, server, channel->channel_name, - client_entry->nickname, client_entry->username[0] ? - buf : "", client_entry->nickname); - - chanrec = silc_channel_find_entry(server, channel); - if (chanrec != NULL) { - nickrec = silc_nicklist_find(chanrec, client_entry); - if (nickrec != NULL) - nicklist_remove(CHANNEL(chanrec), NICK(nickrec)); - } - - /* If there is only one client with this same nickname on channel now - change it to the base format if it is formatted nickname. */ - if (channel) { - silc_client_nickname_parse(client, conn, client_entry->nickname, &name); - clients = silc_client_get_clients_local(client, conn, name, TRUE); - if (!clients || silc_dlist_count(clients) != 2) { - silc_free(name); - silc_client_list_free(client, conn, clients); - break; - } - silc_dlist_start(clients); - client_entry2 = silc_dlist_get(clients); - if (client_entry2 == client_entry) - client_entry2 = silc_dlist_get(clients); - if (silc_client_on_channel(channel, client_entry2)) { - silc_snprintf(buf, sizeof(buf), "%s", client_entry2->nickname); - silc_client_nickname_format(client, conn, client_entry2, TRUE); - if (!silc_utf8_strcasecmp(buf, client_entry2->nickname)) { - nicklist_rename_unique(SERVER(server), client_entry2, buf, - client_entry2, client_entry2->nickname); - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_USER_APPEARS, - buf, client_entry2->nickname); - } - } - silc_client_list_free(client, conn, clients); - silc_free(name); - } - break; - - case SILC_NOTIFY_TYPE_SIGNOFF: - /* - * Left the network. - */ - - SILC_LOG_DEBUG(("Notify: SIGNOFF")); - - client_entry = va_arg(va, SilcClientEntry); - tmp = va_arg(va, char *); - channel = va_arg(va, SilcChannelEntry); - - silc_server_free_ftp(server, client_entry); - - memset(buf, 0, sizeof(buf)); - if (client_entry->username) - snprintf(buf, sizeof(buf) - 1, "%s@%s", - client_entry->username, client_entry->hostname); - signal_emit("message quit", 4, server, client_entry->nickname, - client_entry->username[0] ? buf : "", tmp ? tmp : ""); - - list1 = nicklist_get_same_unique(SERVER(server), client_entry); - for (list_tmp = list1; list_tmp != NULL; list_tmp = - list_tmp->next->next) { - CHANNEL_REC *channel = list_tmp->data; - NICK_REC *nickrec = list_tmp->next->data; - - nicklist_remove(channel, nickrec); - } - - /* If there is only one client with this same nickname on channel now - change it to the base format if it is formatted nickname. */ - if (channel) { - silc_client_nickname_parse(client, conn, client_entry->nickname, &name); - clients = silc_client_get_clients_local(client, conn, name, TRUE); - if (!clients || silc_dlist_count(clients) != 2) { - silc_free(name); - silc_client_list_free(client, conn, clients); - break; - } - silc_dlist_start(clients); - client_entry2 = silc_dlist_get(clients); - if (client_entry2 == client_entry) - client_entry2 = silc_dlist_get(clients); - if (silc_client_on_channel(channel, client_entry2)) { - silc_snprintf(buf, sizeof(buf), "%s", client_entry2->nickname); - silc_client_nickname_format(client, conn, client_entry2, TRUE); - if (!silc_utf8_strcasecmp(buf, client_entry2->nickname)) { - nicklist_rename_unique(SERVER(server), client_entry2, buf, - client_entry2, client_entry2->nickname); - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_USER_APPEARS, - buf, client_entry2->nickname); - } - } - silc_client_list_free(client, conn, clients); - silc_free(name); - } - break; - - case SILC_NOTIFY_TYPE_TOPIC_SET: - /* - * Changed topic. - */ - - SILC_LOG_DEBUG(("Notify: TOPIC_SET")); - - idtype = va_arg(va, int); - entry = va_arg(va, void *); - tmp = va_arg(va, char *); - channel = va_arg(va, SilcChannelEntry); - - chanrec = silc_channel_find_entry(server, channel); - if (chanrec != NULL) { - char tmp2[256], *cp, *dm = NULL; - - g_free_not_null(chanrec->topic); - if (tmp && !silc_term_utf8() && silc_utf8_valid(tmp, strlen(tmp))) { - memset(tmp2, 0, sizeof(tmp2)); - cp = tmp2; - if (strlen(tmp) > sizeof(tmp2) - 1) { - dm = silc_calloc(strlen(tmp) + 1, sizeof(*dm)); - cp = dm; - } - - silc_utf8_decode(tmp, strlen(tmp), SILC_STRING_LANGUAGE, - cp, strlen(tmp)); - tmp = cp; - } - - chanrec->topic = *tmp == '\0' ? NULL : g_strdup(tmp); - signal_emit("channel topic changed", 1, chanrec); - - silc_free(dm); - } - - if (idtype == SILC_ID_CLIENT) { - client_entry = (SilcClientEntry)entry; - memset(buf, 0, sizeof(buf)); - snprintf(buf, sizeof(buf) - 1, "%s@%s", - client_entry->username, client_entry->hostname); - signal_emit("message topic", 5, server, channel->channel_name, - tmp, client_entry->nickname, buf); - } else if (idtype == SILC_ID_SERVER) { - server_entry = (SilcServerEntry)entry; - signal_emit("message topic", 5, server, channel->channel_name, - tmp, server_entry->server_name, - server_entry->server_name); - } else if (idtype == SILC_ID_CHANNEL) { - channel = (SilcChannelEntry)entry; - signal_emit("message topic", 5, server, channel->channel_name, - tmp, channel->channel_name, channel->channel_name); - } - break; - - case SILC_NOTIFY_TYPE_NICK_CHANGE: - /* - * Changed nickname. - */ - - SILC_LOG_DEBUG(("Notify: NICK_CHANGE")); - - client_entry = va_arg(va, SilcClientEntry); - name = va_arg(va, char *); /* old nickname */ - - if (!strcmp(client_entry->nickname, name)) - break; - - memset(buf, 0, sizeof(buf)); - snprintf(buf, sizeof(buf) - 1, "%s@%s", - client_entry->username, client_entry->hostname); - nicklist_rename_unique(SERVER(server), - client_entry, name, - client_entry, client_entry->nickname); - signal_emit("message nick", 4, server, client_entry->nickname, name, buf); - break; - - case SILC_NOTIFY_TYPE_CMODE_CHANGE: - /* - * Changed channel mode. - */ - - SILC_LOG_DEBUG(("Notify: CMODE_CHANGE")); - - idtype = va_arg(va, int); - entry = va_arg(va, void *); - mode = va_arg(va, SilcUInt32); - cipher = va_arg(va, char *); /* cipher */ - hmac = va_arg(va, char *); /* hmac */ - (void)va_arg(va, char *); /* passphrase */ - (void)va_arg(va, SilcPublicKey); /* founder key */ - chpks = va_arg(va, SilcDList); /* channel public keys */ - channel = va_arg(va, SilcChannelEntry); - - tmp = silc_client_chmode(mode, cipher ? cipher : "", - hmac ? hmac : ""); - - chanrec = silc_channel_find_entry(server, channel); - if (chanrec != NULL) { - g_free_not_null(chanrec->mode); - chanrec->mode = g_strdup(tmp == NULL ? "" : tmp); - signal_emit("channel mode changed", 1, chanrec); - } - - if (idtype == SILC_ID_CLIENT) { - client_entry = (SilcClientEntry)entry; - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE, - channel->channel_name, tmp ? tmp : "removed all", - client_entry->nickname); - } else if (idtype == SILC_ID_SERVER) { - server_entry = (SilcServerEntry)entry; - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE, - channel->channel_name, tmp ? tmp : "removed all", - server_entry->server_name); - } else if (idtype == SILC_ID_CHANNEL) { - channel2 = (SilcChannelEntry)entry; - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE, - channel->channel_name, tmp ? tmp : "removed all", - channel2->channel_name); - } - - /* Print the channel public key list */ - if (chpks) - silc_parse_channel_public_keys(server, channel, chpks); - - silc_free(tmp); - break; - - case SILC_NOTIFY_TYPE_CUMODE_CHANGE: - /* - * Changed user's mode on channel. - */ - - SILC_LOG_DEBUG(("Notify: CUMODE_CHANGE")); - - idtype = va_arg(va, int); - entry = va_arg(va, void *); - mode = va_arg(va, SilcUInt32); - client_entry2 = va_arg(va, SilcClientEntry); - channel = va_arg(va, SilcChannelEntry); - - tmp = silc_client_chumode(mode); - chanrec = silc_channel_find_entry(server, channel); - if (chanrec != NULL) { - SILC_NICK_REC *nick; - - if (client_entry2 == server->conn->local_entry) - chanrec->chanop = (mode & SILC_CHANNEL_UMODE_CHANOP) != 0; - - nick = silc_nicklist_find(chanrec, client_entry2); - if (nick != NULL) { - nick->op = (mode & SILC_CHANNEL_UMODE_CHANOP) != 0; - nick->founder = (mode & SILC_CHANNEL_UMODE_CHANFO) != 0; - signal_emit("nick mode changed", 2, chanrec, nick); - } - } - - if (idtype == SILC_ID_CLIENT) { - client_entry = (SilcClientEntry)entry; - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE, - channel->channel_name, client_entry2->nickname, - tmp ? tmp : "removed all", - client_entry->nickname); - } else if (idtype == SILC_ID_SERVER) { - server_entry = (SilcServerEntry)entry; - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE, - channel->channel_name, client_entry2->nickname, - tmp ? tmp : "removed all", - server_entry->server_name); - } else if (idtype == SILC_ID_CHANNEL) { - channel2 = (SilcChannelEntry)entry; - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE, - channel->channel_name, client_entry2->nickname, - tmp ? tmp : "removed all", - channel2->channel_name); - } - - if (mode & SILC_CHANNEL_UMODE_CHANFO) - printformat_module("fe-common/silc", - server, channel->channel_name, MSGLEVEL_CRAP, - SILCTXT_CHANNEL_FOUNDER, - channel->channel_name, client_entry2->nickname); - - if (mode & SILC_CHANNEL_UMODE_QUIET && conn->local_entry == client_entry2) - printformat_module("fe-common/silc", - server, channel->channel_name, MSGLEVEL_CRAP, - SILCTXT_CHANNEL_QUIETED, channel->channel_name); - - silc_free(tmp); - break; - - case SILC_NOTIFY_TYPE_MOTD: - /* - * Received MOTD. - */ - - SILC_LOG_DEBUG(("Notify: MOTD")); - - tmp = va_arg(va, char *); - - if (!settings_get_bool("skip_motd")) - printtext_multiline(server, NULL, MSGLEVEL_CRAP, "%s", tmp); - break; - - case SILC_NOTIFY_TYPE_KICKED: - /* - * Someone was kicked from channel. - */ - - SILC_LOG_DEBUG(("Notify: KICKED")); - - client_entry = va_arg(va, SilcClientEntry); - tmp = va_arg(va, char *); - client_entry2 = va_arg(va, SilcClientEntry); - channel = va_arg(va, SilcChannelEntry); - - chanrec = silc_channel_find_entry(server, channel); - - if (client_entry == conn->local_entry) { - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_KICKED_YOU, - channel->channel_name, - client_entry ? client_entry2->nickname : "", - tmp ? tmp : ""); - if (chanrec) { - chanrec->kicked = TRUE; - channel_destroy((CHANNEL_REC *)chanrec); - } - } else { - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_KICKED, - client_entry->nickname, channel->channel_name, - client_entry2 ? client_entry2->nickname : "", - tmp ? tmp : ""); - - if (chanrec) { - SILC_NICK_REC *nickrec = silc_nicklist_find(chanrec, client_entry); - if (nickrec != NULL) - nicklist_remove(CHANNEL(chanrec), NICK(nickrec)); - } - } - break; - - case SILC_NOTIFY_TYPE_KILLED: - /* - * Someone was killed from the network. - */ - - SILC_LOG_DEBUG(("Notify: KILLED")); - - client_entry = va_arg(va, SilcClientEntry); - tmp = va_arg(va, char *); - idtype = va_arg(va, int); - entry = va_arg(va, SilcClientEntry); - - if (client_entry == conn->local_entry) { - if (idtype == SILC_ID_CLIENT) { - client_entry2 = (SilcClientEntry)entry; - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU, - client_entry2 ? client_entry2->nickname : "", - tmp ? tmp : ""); - } else if (idtype == SILC_ID_SERVER) { - server_entry = (SilcServerEntry)entry; - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU, - server_entry->server_name, tmp ? tmp : ""); - } else if (idtype == SILC_ID_CHANNEL) { - channel = (SilcChannelEntry)entry; - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU, - channel->channel_name, tmp ? tmp : ""); - } - } else { - list1 = nicklist_get_same_unique(SERVER(server), client_entry); - for (list_tmp = list1; list_tmp != NULL; list_tmp = - list_tmp->next->next) { - CHANNEL_REC *channel = list_tmp->data; - NICK_REC *nickrec = list_tmp->next->data; - nicklist_remove(channel, nickrec); - } - - if (idtype == SILC_ID_CLIENT) { - client_entry2 = (SilcClientEntry)entry; - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED, - client_entry->nickname, - client_entry2 ? client_entry2->nickname : "", - tmp ? tmp : ""); - } else if (idtype == SILC_ID_SERVER) { - server_entry = (SilcServerEntry)entry; - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED, - client_entry->nickname, - server_entry->server_name, tmp ? tmp : ""); - } else if (idtype == SILC_ID_CHANNEL) { - channel = (SilcChannelEntry)entry; - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED, - client_entry->nickname, - channel->channel_name, tmp ? tmp : ""); - } - } - break; - - case SILC_NOTIFY_TYPE_CHANNEL_CHANGE: - break; - - case SILC_NOTIFY_TYPE_SERVER_SIGNOFF: - { - /* - * Server has quit the network. - */ - SilcDList clients; - - SILC_LOG_DEBUG(("Notify: SERVER_SIGNOFF")); - - (void)va_arg(va, void *); - clients = va_arg(va, SilcDList); - - silc_dlist_start(clients); - while ((client_entry = silc_dlist_get(clients))) { - memset(buf, 0, sizeof(buf)); - - /* Print only if we have the nickname. If this client has just quit - when we were only resolving it, it is possible we don't have the - nickname. */ - if (client_entry->nickname[0]) { - if (client_entry->username[0]) - snprintf(buf, sizeof(buf) - 1, "%s@%s", - client_entry->username, client_entry->hostname); - signal_emit("message quit", 4, server, client_entry->nickname, - client_entry->username[0] ? buf : "", - "server signoff"); - } - - silc_server_free_ftp(server, client_entry); - - list1 = nicklist_get_same_unique(SERVER(server), client_entry); - for (list_tmp = list1; list_tmp != NULL; list_tmp = - list_tmp->next->next) { - CHANNEL_REC *channel = list_tmp->data; - NICK_REC *nickrec = list_tmp->next->data; - nicklist_remove(channel, nickrec); - } - } - } - break; - - case SILC_NOTIFY_TYPE_ERROR: - { - SilcStatus error = va_arg(va, int); - - silc_say(client, conn, SILC_CLIENT_MESSAGE_ERROR, - "%s", silc_get_status_message(error)); - } - break; - - case SILC_NOTIFY_TYPE_WATCH: - { - SilcNotifyType notify; - - client_entry = va_arg(va, SilcClientEntry); - name = va_arg(va, char *); /* Maybe NULL */ - mode = va_arg(va, SilcUInt32); - notify = va_arg(va, int); - - if (notify == SILC_NOTIFY_TYPE_NICK_CHANGE) { - if (name) - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_WATCH_NICK_CHANGE, - client_entry->nickname, name); - else - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_WATCH_PRESENT, - client_entry->nickname); - } else if (notify == SILC_NOTIFY_TYPE_UMODE_CHANGE) { - /* See if client was away and is now present */ - if (!(mode & (SILC_UMODE_GONE | SILC_UMODE_INDISPOSED | - SILC_UMODE_BUSY | SILC_UMODE_PAGE | - SILC_UMODE_DETACHED)) && - (client_entry->mode & SILC_UMODE_GONE || - client_entry->mode & SILC_UMODE_INDISPOSED || - client_entry->mode & SILC_UMODE_BUSY || - client_entry->mode & SILC_UMODE_PAGE || - client_entry->mode & SILC_UMODE_DETACHED)) { - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_WATCH_PRESENT, - client_entry->nickname); - } - - if (mode) { - memset(buf, 0, sizeof(buf)); - silc_get_umode_string(mode, buf, sizeof(buf) - 1); - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_WATCH_UMODE_CHANGE, - client_entry->nickname, buf); - } - } else if (notify == SILC_NOTIFY_TYPE_KILLED) { - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_WATCH_KILLED, - client_entry->nickname); - } else if (notify == SILC_NOTIFY_TYPE_SIGNOFF || - notify == SILC_NOTIFY_TYPE_SERVER_SIGNOFF) { - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_WATCH_SIGNOFF, - client_entry->nickname); - } else if (notify == SILC_NOTIFY_TYPE_NONE) { - /* Client logged in to the network */ - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_WATCH_PRESENT, - client_entry->nickname); - } - } - break; - - default: - /* Unknown notify */ - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_UNKNOWN_NOTIFY, type); - break; - } - - va_end(va); -} - -/* Command handler. This function is called always in the command function. - If error occurs it will be called as well. `conn' is the associated - client connection. `cmd_context' is the command context that was - originally sent to the command. `success' is FALSE if error occured - during command. `command' is the command being processed. It must be - noted that this is not reply from server. This is merely called just - after application has called the command. Just to tell application - that the command really was processed. */ - -static SilcBool cmode_list_chpks = FALSE; - -void silc_command(SilcClient client, SilcClientConnection conn, - SilcBool success, SilcCommand command, SilcStatus status, - SilcUInt32 argc, unsigned char **argv) -{ - SILC_SERVER_REC *server = conn->context; - - SILC_LOG_DEBUG(("Start")); - - if (!success) { - silc_say_error("%s", silc_get_status_message(status)); - return; - } - - switch (command) { - - case SILC_COMMAND_INVITE: - if (argc > 2) - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_INVITING, - argv[2], - (argv[1][0] == '*' ? - (char *)conn->current_channel->channel_name : - (char *)argv[1])); - break; - - case SILC_COMMAND_DETACH: - server->no_reconnect = TRUE; - break; - - case SILC_COMMAND_CMODE: - if (argc == 3 && !strcmp(argv[2], "+C")) - cmode_list_chpks = TRUE; - else - cmode_list_chpks = FALSE; - break; - - default: - break; - } -} - -typedef struct { - SilcClient client; - SilcClientConnection conn; - void *entry; - SilcIdType id_type; -} *GetkeyContext; - -void silc_getkey_cb(bool success, void *context) -{ - GetkeyContext getkey = (GetkeyContext)context; - char *entity = (getkey->id_type == SILC_ID_CLIENT ? "user" : "server"); - char *name = (getkey->id_type == SILC_ID_CLIENT ? - ((SilcClientEntry)getkey->entry)->nickname : - ((SilcServerEntry)getkey->entry)->server_name); - SilcPublicKey public_key = (getkey->id_type == SILC_ID_CLIENT ? - ((SilcClientEntry)getkey->entry)->public_key : - ((SilcServerEntry)getkey->entry)->public_key); - SilcSILCPublicKey silc_pubkey; - - silc_pubkey = silc_pkcs_public_key_get_pkcs(SILC_PKCS_SILC, public_key); - - if (success) { - if (getkey->id_type == SILC_ID_CLIENT) - printformat_module("fe-common/silc", NULL, NULL, - MSGLEVEL_CRAP, SILCTXT_PUBKEY_VERIFIED_CLIENT, - name, - silc_pubkey->identifier.realname ? - silc_pubkey->identifier.realname : "", - silc_pubkey->identifier.email ? - silc_pubkey->identifier.email : ""); - else - printformat_module("fe-common/silc", NULL, NULL, - MSGLEVEL_CRAP, SILCTXT_PUBKEY_VERIFIED, - entity, name); - } else { - printformat_module("fe-common/silc", NULL, NULL, - MSGLEVEL_CRAP, SILCTXT_PUBKEY_NOTVERIFIED, - entity, name); - } - - silc_free(getkey); -} - -/* Parse an invite or ban list */ -void silc_parse_inviteban_list(SilcClient client, - SilcClientConnection conn, - SILC_SERVER_REC *server, - SilcChannelEntry channel, - const char *list_type, - SilcArgumentPayload list) -{ - unsigned char *tmp; - SilcUInt32 type, len; - SILC_CHANNEL_REC *chanrec = silc_channel_find_entry(server, channel); - int counter=0, resolving = FALSE; - - if (!silc_argument_get_arg_num(list)) { - printformat_module("fe-common/silc", server, - (chanrec ? chanrec->visible_name : NULL), - MSGLEVEL_CRAP, SILCTXT_CHANNEL_NO_INVITEBAN_LIST, - channel->channel_name, list_type); - return; - } - - printformat_module("fe-common/silc", server, - (chanrec ? chanrec->visible_name : NULL), - MSGLEVEL_CRAP, SILCTXT_CHANNEL_INVITEBAN_LIST, - channel->channel_name, list_type); - - /* Parse the list */ - tmp = silc_argument_get_first_arg(list, &type, &len); - while (tmp) { - switch (type) { - case 1: - { - /* An invite string */ - char **list; - int i=0; - - if (tmp[len-1] == ',') - tmp[len-1] = '\0'; - - list = g_strsplit(tmp, ",", -1); - while (list[i]) - printformat_module("fe-common/silc", server, - (chanrec ? chanrec->visible_name : NULL), - MSGLEVEL_CRAP, SILCTXT_CHANNEL_INVITEBAN_STRING, - ++counter, channel->channel_name, list_type, - list[i++]); - g_strfreev(list); - } - break; - - case 2: - { - /* A public key */ - char *fingerprint, *babbleprint; - - /* tmp is Public Key Payload, take public key from it. */ - fingerprint = silc_hash_fingerprint(NULL, tmp + 4, len - 4); - babbleprint = silc_hash_babbleprint(NULL, tmp + 4, len - 4); - - printformat_module("fe-common/silc", server, - (chanrec ? chanrec->visible_name : NULL), - MSGLEVEL_CRAP, SILCTXT_CHANNEL_INVITEBAN_PUBKEY, - ++counter, channel->channel_name, list_type, - fingerprint, babbleprint); - } - break; - - case 3: - { - /* A Client ID */ - SilcClientEntry client_entry; - SilcID id; - - if (!silc_id_payload_parse_id(tmp, len, &id)) { - silc_say_error("Invalid data in %s list encountered", list_type); - break; - } - - client_entry = silc_client_get_client_by_id(client, conn, - &id.u.client_id); - if (client_entry) { - printformat_module("fe-common/silc", server, - (chanrec ? chanrec->visible_name : NULL), - MSGLEVEL_CRAP, SILCTXT_CHANNEL_INVITEBAN_STRING, - ++counter, channel->channel_name, list_type, - client_entry->nickname); - silc_client_unref_client(client, conn, client_entry); - } else { - resolving = TRUE; - silc_client_get_client_by_id_resolve(client, conn, &id.u.client_id, - NULL, NULL, NULL); - } - } - break; - - default: - /* "trash" */ - silc_say_error("Unkown type in %s list: %u (len %u)", - list_type, type, len); - break; - } - tmp = silc_argument_get_next_arg(list, &type, &len); - } - - if (resolving) - printformat_module("fe-common/silc", server, - (chanrec ? chanrec->visible_name : NULL), - MSGLEVEL_CRAP, SILCTXT_CHANNEL_INVITEBAN_REGET, - list_type, channel->channel_name); -} - -/* Command reply handler. This function is called always in the command reply - function. If error occurs it will be called as well. Normal scenario - is that it will be called after the received command data has been parsed - and processed. The function is used to pass the received command data to - the application. - - `conn' is the associated client connection. `cmd_payload' is the command - payload data received from server and it can be ignored. It is provided - if the application would like to re-parse the received command data, - however, it must be noted that the data is parsed already by the library - thus the payload can be ignored. `success' is FALSE if error occured. - In this case arguments are not sent to the application. `command' is the - command reply being processed. The function has variable argument list - and each command defines the number and type of arguments it passes to the - application (on error they are not sent). */ - -void silc_command_reply(SilcClient client, SilcClientConnection conn, - SilcCommand command, SilcStatus status, - SilcStatus error, va_list vp) -{ - SILC_SERVER_REC *server = conn->context; - SILC_CHANNEL_REC *chanrec; - - SILC_LOG_DEBUG(("Start")); - - switch(command) { - case SILC_COMMAND_WHOIS: - { - char buf[1024], *nickname, *username, *realname, *nick; - unsigned char *fingerprint; - SilcUInt32 idle, mode, *user_modes; - SilcDList channels; - SilcClientEntry client_entry; - SilcDList attrs; - - if (status == SILC_STATUS_ERR_NO_SUCH_NICK) { - /* Print the unknown nick for user */ - char *tmp = va_arg(vp, char *); - if (tmp) - silc_say_error("%s: %s", tmp, silc_get_status_message(status)); - break; - } else if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) { - /* Try to find the entry for the unknown client ID, since we - might have, and print the nickname of it for user. */ - SilcClientID *id = va_arg(vp, SilcClientID *); - if (id) { - client_entry = silc_client_get_client_by_id(client, conn, id); - if (client_entry && client_entry->nickname[0]) - silc_say_error("%s: %s", client_entry->nickname, - silc_get_status_message(status)); - silc_client_unref_client(client, conn, client_entry); - } - break; - } else if (SILC_STATUS_IS_ERROR(status)) { - silc_say_error("WHOIS: %s", silc_get_status_message(status)); - return; - } - - client_entry = va_arg(vp, SilcClientEntry); - nickname = va_arg(vp, char *); - username = va_arg(vp, char *); - realname = va_arg(vp, char *); - channels = va_arg(vp, SilcDList); - mode = va_arg(vp, SilcUInt32); - idle = va_arg(vp, SilcUInt32); - fingerprint = va_arg(vp, unsigned char *); - user_modes = va_arg(vp, SilcUInt32 *); - attrs = va_arg(vp, SilcDList); - - silc_client_nickname_parse(client, conn, client_entry->nickname, &nick); - printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, - SILCTXT_WHOIS_USERINFO, nickname, - client_entry->username, client_entry->hostname, - nick, client_entry->nickname); - printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, - SILCTXT_WHOIS_REALNAME, realname); - silc_free(nick); - - if (channels && user_modes) { - SilcChannelPayload entry; - int i = 0; - - memset(buf, 0, sizeof(buf)); - silc_dlist_start(channels); - while ((entry = silc_dlist_get(channels))) { - SilcUInt32 name_len; - char *m = silc_client_chumode_char(user_modes[i++]); - char *name = silc_channel_get_name(entry, &name_len); - - if (m) - silc_strncat(buf, sizeof(buf) - 1, m, strlen(m)); - silc_strncat(buf, sizeof(buf) - 1, name, name_len); - silc_strncat(buf, sizeof(buf) - 1, " ", 1); - silc_free(m); - } - - printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, - SILCTXT_WHOIS_CHANNELS, buf); - } - - if (mode) { - memset(buf, 0, sizeof(buf)); - silc_get_umode_string(mode, buf, sizeof(buf - 1)); - printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, - SILCTXT_WHOIS_MODES, buf); - } - - if (idle && nickname) { - memset(buf, 0, sizeof(buf)); - snprintf(buf, sizeof(buf) - 1, "%lu %s", - idle > 60 ? (idle / 60) : idle, - idle > 60 ? "minutes" : "seconds"); - - printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, - SILCTXT_WHOIS_IDLE, buf); - } - - if (fingerprint) { - fingerprint = silc_fingerprint(fingerprint, 20); - printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, - SILCTXT_WHOIS_FINGERPRINT, fingerprint); - silc_free(fingerprint); - } - - if (attrs) - silc_query_attributes_print(server, silc_client, conn, attrs, - client_entry); - } - break; - - case SILC_COMMAND_WHOWAS: - { - char *nickname, *username, *realname; - - if (status == SILC_STATUS_ERR_NO_SUCH_NICK) { - char *tmp = va_arg(vp, char *); - if (tmp) - silc_say_error("%s: %s", tmp, - silc_get_status_message(status)); - break; - } else if (SILC_STATUS_IS_ERROR(status)) { - silc_say_error("WHOWAS: %s", silc_get_status_message(status)); - return; - } - - (void)va_arg(vp, SilcClientEntry); - nickname = va_arg(vp, char *); - username = va_arg(vp, char *); - realname = va_arg(vp, char *); - - printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, - SILCTXT_WHOWAS_USERINFO, nickname, username, - realname ? realname : ""); - } - break; - - case SILC_COMMAND_INVITE: - { - SilcChannelEntry channel; - SilcArgumentPayload invite_list; - - if (SILC_STATUS_IS_ERROR(status)) - return; - - channel = va_arg(vp, SilcChannelEntry); - invite_list = va_arg(vp, SilcArgumentPayload); - - if (invite_list) - silc_parse_inviteban_list(client, conn, server, channel, - "invite", invite_list); - } - break; - - case SILC_COMMAND_JOIN: - { - char *channel, *mode, *topic, *cipher, *hmac; - SilcUInt32 modei; - SilcHashTableList *user_list; - SilcChannelEntry channel_entry; - SilcChannelUser chu; - SilcClientEntry founder = NULL; - NICK_REC *ownnick; - - if (SILC_STATUS_IS_ERROR(status)) { - if (status == SILC_STATUS_ERR_NO_SUCH_SERVER) { - char *tmp = va_arg(vp, char *); - if (tmp) - silc_say_error("JOIN: %s: %s", tmp, - silc_get_status_message(status)); - return; - } - if (status == SILC_STATUS_ERR_NO_SUCH_CHANNEL) { - char *tmp = va_arg(vp, char *); - if (tmp) - silc_say_error("JOIN: %s: %s", tmp, - silc_get_status_message(status)); - return; - } - silc_say_error("JOIN: %s", silc_get_status_message(status)); - return; - } - - channel = va_arg(vp, char *); - channel_entry = va_arg(vp, SilcChannelEntry); - modei = va_arg(vp, SilcUInt32); - user_list = va_arg(vp, SilcHashTableList *); - topic = va_arg(vp, char *); - cipher = va_arg(vp, char *); - hmac = va_arg(vp, char *); - - chanrec = silc_channel_find(server, channel); - if (!chanrec) - chanrec = silc_channel_create(server, channel, channel, TRUE); - - if (topic) { - char tmp[256], *cp, *dm = NULL; - g_free_not_null(chanrec->topic); - - if (!silc_term_utf8() && silc_utf8_valid(topic, strlen(topic))) { - memset(tmp, 0, sizeof(tmp)); - cp = tmp; - if (strlen(topic) > sizeof(tmp) - 1) { - dm = silc_calloc(strlen(topic) + 1, sizeof(*dm)); - cp = dm; - } - - silc_utf8_decode(topic, strlen(topic), SILC_STRING_LOCALE, - cp, strlen(topic)); - topic = cp; - } - - chanrec->topic = *topic == '\0' ? NULL : g_strdup(topic); - signal_emit("channel topic changed", 1, chanrec); - - silc_free(dm); - } - - mode = silc_client_chmode(modei, cipher ? cipher : "", hmac ? hmac : ""); - g_free_not_null(chanrec->mode); - chanrec->mode = g_strdup(mode == NULL ? "" : mode); - signal_emit("channel mode changed", 1, chanrec); - - /* Get user list */ - while (silc_hash_table_get(user_list, NULL, (void *)&chu)) { - if (!chu->client->nickname[0]) - continue; - if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) - founder = chu->client; - silc_nicklist_insert(chanrec, chu, FALSE); - } - - ownnick = NICK(silc_nicklist_find(chanrec, conn->local_entry)); - if (!ownnick) - break; - nicklist_set_own(CHANNEL(chanrec), ownnick); - signal_emit("channel joined", 1, chanrec); - chanrec->entry = channel_entry; - - if (chanrec->topic) - printformat_module("fe-common/silc", server, - channel_entry->channel_name, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_TOPIC, - channel_entry->channel_name, chanrec->topic); - - if (founder) { - if (founder == conn->local_entry) { - printformat_module("fe-common/silc", - server, channel_entry->channel_name, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_FOUNDER_YOU, - channel_entry->channel_name); - signal_emit("nick mode changed", 2, chanrec, ownnick); - } else - printformat_module("fe-common/silc", - server, channel_entry->channel_name, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_FOUNDER, - channel_entry->channel_name, founder->nickname); - } - - break; - } - - case SILC_COMMAND_NICK: - { - char *old; - SilcClientEntry client_entry = va_arg(vp, SilcClientEntry); - GSList *nicks; - - if (SILC_STATUS_IS_ERROR(status)) { - silc_say_error("NICK: %s", silc_get_status_message(status)); - return; - } - - nicks = nicklist_get_same(SERVER(server), client_entry->nickname); - if ((nicks != NULL) && - (strcmp(SERVER(server)->nick, client_entry->nickname))) { - char buf[512]; - SilcClientEntry collider, old; - - old = ((SILC_NICK_REC *)(nicks->next->data))->silc_user->client; - collider = silc_client_get_client_by_id(client, conn, &old->id); - if (collider != client_entry) { - memset(buf, 0, sizeof(buf)); - snprintf(buf, sizeof(buf) - 1, "%s@%s", - collider->username, collider->hostname); - nicklist_rename_unique(SERVER(server), - old, old->nickname, - collider, collider->nickname); - silc_print_nick_change(server, collider->nickname, - client_entry->nickname, buf); - } - silc_client_unref_client(client, conn, collider); - } - - if (nicks != NULL) - g_slist_free(nicks); - - old = g_strdup(server->nick); - server_change_nick(SERVER(server), client_entry->nickname); - nicklist_rename_unique(SERVER(server), - server->conn->local_entry, server->nick, - client_entry, client_entry->nickname); - signal_emit("message own_nick", 4, server, server->nick, old, ""); - g_free(old); - - /* when connecting to a server, the last thing we receive - is a SILC_COMMAND_LIST reply. Since we enable queueing - during the connection, we can now safely disable it again */ - silc_queue_disable(conn); - break; - } - - case SILC_COMMAND_LIST: - { - char *topic, *name; - int usercount; - char users[20]; - char tmp[256], *cp, *dm = NULL; - - if (SILC_STATUS_IS_ERROR(status)) - return; - - (void)va_arg(vp, SilcChannelEntry); - name = va_arg(vp, char *); - topic = va_arg(vp, char *); - usercount = va_arg(vp, int); - - if (topic && !silc_term_utf8() && - silc_utf8_valid(topic, strlen(topic))) { - memset(tmp, 0, sizeof(tmp)); - cp = tmp; - if (strlen(topic) > sizeof(tmp) - 1) { - dm = silc_calloc(strlen(topic) + 1, sizeof(*dm)); - cp = dm; - } - - silc_utf8_decode(topic, strlen(topic), SILC_STRING_LOCALE, - cp, strlen(topic)); - topic = cp; - } - - if (status == SILC_STATUS_LIST_START || - status == SILC_STATUS_OK) - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_LIST_HEADER); - - if (!usercount) - snprintf(users, sizeof(users) - 1, "N/A"); - else - snprintf(users, sizeof(users) - 1, "%d", usercount); - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_LIST, - name, users, topic ? topic : ""); - silc_free(dm); - } - break; - - case SILC_COMMAND_UMODE: - { - SilcUInt32 mode; - char *reason; - - if (SILC_STATUS_IS_ERROR(status)) - return; - - mode = va_arg(vp, SilcUInt32); - - if (mode & SILC_UMODE_SERVER_OPERATOR && - !(server->umode & SILC_UMODE_SERVER_OPERATOR)) - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_SERVER_OPER); - - if (mode & SILC_UMODE_ROUTER_OPERATOR && - !(server->umode & SILC_UMODE_ROUTER_OPERATOR)) - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_ROUTER_OPER); - - if ((mode & SILC_UMODE_GONE) != (server->umode & SILC_UMODE_GONE)) { - if (mode & SILC_UMODE_GONE) { - if ((server->away_reason != NULL) && (server->away_reason[0] != '\0')) - reason = g_strdup(server->away_reason); - else - reason = g_strdup("away"); - } else - reason = g_strdup(""); - - silc_set_away(reason, server); - - g_free(reason); - } - - server->umode = mode; - signal_emit("user mode changed", 2, server, NULL); - } - break; - - case SILC_COMMAND_OPER: - if (SILC_STATUS_IS_ERROR(status)) { - silc_say_error("OPER: %s", silc_get_status_message(status)); - return; - } - - server->umode |= SILC_UMODE_SERVER_OPERATOR; - signal_emit("user mode changed", 2, server, NULL); - - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_SERVER_OPER); - break; - - case SILC_COMMAND_SILCOPER: - if (SILC_STATUS_IS_ERROR(status)) { - silc_say_error("SILCOPER: %s", silc_get_status_message(status)); - return; - } - - server->umode |= SILC_UMODE_ROUTER_OPERATOR; - signal_emit("user mode changed", 2, server, NULL); - - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_ROUTER_OPER); - break; - - case SILC_COMMAND_USERS: - { - SilcHashTableList htl; - SilcChannelEntry channel; - SilcChannelUser chu; - - if (SILC_STATUS_IS_ERROR(status)) { - silc_say_error("USERS: %s", silc_get_status_message(status)); - return; - } - - channel = va_arg(vp, SilcChannelEntry); - - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_CRAP, SILCTXT_USERS_HEADER, - channel->channel_name); - - silc_hash_table_list(channel->user_list, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - SilcClientEntry e = chu->client; - char stat[5], *mode; - - if (!e->nickname[0]) - continue; - - memset(stat, 0, sizeof(stat)); - mode = silc_client_chumode_char(chu->mode); - if (e->mode & SILC_UMODE_GONE) - strcat(stat, "G"); - else if (e->mode & SILC_UMODE_INDISPOSED) - strcat(stat, "I"); - else if (e->mode & SILC_UMODE_BUSY) - strcat(stat, "B"); - else if (e->mode & SILC_UMODE_PAGE) - strcat(stat, "P"); - else if (e->mode & SILC_UMODE_HYPER) - strcat(stat, "H"); - else if (e->mode & SILC_UMODE_ROBOT) - strcat(stat, "R"); - else if (e->mode & SILC_UMODE_ANONYMOUS) - strcat(stat, "?"); - else - strcat(stat, "A"); - if (mode) - strcat(stat, mode); - - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_CRAP, SILCTXT_USERS, - e->nickname, stat, - e->username[0] ? e->username : "", - e->hostname[0] ? e->hostname : "", - e->realname ? e->realname : ""); - if (mode) - silc_free(mode); - } - silc_hash_table_list_reset(&htl); - } - break; - - case SILC_COMMAND_BAN: - { - SilcChannelEntry channel; - SilcArgumentPayload invite_list; - - if (SILC_STATUS_IS_ERROR(status)) - return; - - channel = va_arg(vp, SilcChannelEntry); - invite_list = va_arg(vp, SilcArgumentPayload); - - if (invite_list) - silc_parse_inviteban_list(client, conn, server, channel, - "ban", invite_list); - } - break; - - case SILC_COMMAND_GETKEY: - { - SilcIdType id_type; - void *entry; - SilcPublicKey public_key; - GetkeyContext getkey; - char *name; - - if (SILC_STATUS_IS_ERROR(status)) { - silc_say_error("GETKEY: %s", silc_get_status_message(status)); - return; - } - - id_type = va_arg(vp, SilcUInt32); - entry = va_arg(vp, void *); - public_key = va_arg(vp, SilcPublicKey); - - if (public_key) { - getkey = silc_calloc(1, sizeof(*getkey)); - getkey->entry = entry; - getkey->id_type = id_type; - getkey->client = client; - getkey->conn = conn; - - name = (id_type == SILC_ID_CLIENT ? - ((SilcClientEntry)entry)->nickname : - ((SilcServerEntry)entry)->server_name); - - silc_verify_public_key_internal(client, conn, name, - (id_type == SILC_ID_CLIENT ? - SILC_CONN_CLIENT : - SILC_CONN_SERVER), - public_key, silc_getkey_cb, getkey); - } else { - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_PUBKEY_NOKEY); - } - } - break; - - case SILC_COMMAND_INFO: - { - SilcServerEntry server_entry; - char *server_name; - char *server_info; - - if (SILC_STATUS_IS_ERROR(status)) - return; - - server_entry = va_arg(vp, SilcServerEntry); - server_name = va_arg(vp, char *); - server_info = va_arg(vp, char *); - - if (server_name && server_info ) - { - printtext(server, NULL, MSGLEVEL_CRAP, "Server: %s", server_name); - printtext(server, NULL, MSGLEVEL_CRAP, "%s", server_info); - } - } - break; - - case SILC_COMMAND_TOPIC: - { - SilcChannelEntry channel; - char *topic; - char tmp[256], *cp, *dm = NULL; - - if (SILC_STATUS_IS_ERROR(status)) - return; - - channel = va_arg(vp, SilcChannelEntry); - topic = va_arg(vp, char *); - - if (topic && !silc_term_utf8() && - silc_utf8_valid(topic, strlen(topic))) { - memset(tmp, 0, sizeof(tmp)); - cp = tmp; - if (strlen(topic) > sizeof(tmp) - 1) { - dm = silc_calloc(strlen(topic) + 1, sizeof(*dm)); - cp = dm; - } - - silc_utf8_decode(topic, strlen(topic), SILC_STRING_LOCALE, - cp, strlen(topic)); - topic = cp; - } - - if (topic) { - chanrec = silc_channel_find_entry(server, channel); - if (chanrec) { - g_free_not_null(chanrec->topic); - chanrec->topic = *topic == '\0' ? NULL : g_strdup(topic); - signal_emit("channel topic changed", 1, chanrec); - } - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_TOPIC, - channel->channel_name, topic); - } else { - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_TOPIC_NOT_SET, - channel->channel_name); - } - silc_free(dm); - } - break; - - case SILC_COMMAND_WATCH: - break; - - case SILC_COMMAND_STATS: - { - SilcClientStats *cstats; - char tmp[40]; - const char *tmptime; - int days, hours, mins, secs; - - if (SILC_STATUS_IS_ERROR(status)) - return; - - cstats = va_arg(vp, SilcClientStats *); - if (!cstats) { - printtext(server, NULL, MSGLEVEL_CRAP, "No statistics available"); - return; - } - - tmptime = silc_time_string(cstats->starttime); - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_STATS, - "Local server start time", tmptime); - - days = cstats->uptime / (24 * 60 * 60); - cstats->uptime -= days * (24 * 60 * 60); - hours = cstats->uptime / (60 * 60); - cstats->uptime -= hours * (60 * 60); - mins = cstats->uptime / 60; - cstats->uptime -= mins * 60; - secs = cstats->uptime; - snprintf(tmp, sizeof(tmp) - 1, "%d days %d hours %d mins %d secs", - days, hours, mins, secs); - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_STATS, - "Local server uptime", tmp); - - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->my_clients); - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_STATS, - "Local server clients", tmp); - - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->my_channels); - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_STATS, - "Local server channels", tmp); - - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->my_server_ops); - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_STATS, - "Local server operators", tmp); - - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->my_router_ops); - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_STATS, - "Local router operators", tmp); - - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->cell_clients); - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_STATS, - "Local cell clients", tmp); - - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->cell_channels); - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_STATS, - "Local cell channels", tmp); - - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->cell_servers); - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_STATS, - "Local cell servers", tmp); - - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->clients); - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_STATS, - "Total clients", tmp); - - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->channels); - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_STATS, - "Total channels", tmp); - - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->servers); - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_STATS, - "Total servers", tmp); - - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->routers); - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_STATS, - "Total routers", tmp); - - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->server_ops); - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_STATS, - "Total server operators", tmp); - - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->router_ops); - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_STATS, - "Total router operators", tmp); - } - break; - - case SILC_COMMAND_CMODE: - { - SilcChannelEntry channel_entry; - SilcDList chpks; - SilcPublicKey founder_key; - - channel_entry = va_arg(vp, SilcChannelEntry); - (void)va_arg(vp, SilcUInt32); - founder_key = va_arg(vp, SilcPublicKey); - chpks = va_arg(vp, SilcDList); - - if (SILC_STATUS_IS_ERROR(status) || !channel_entry || - !channel_entry->channel_name) - return; - - /* If founder was changed successfully, tell it to user */ - if (founder_key && channel_entry->founder_key && - !silc_pkcs_public_key_compare(founder_key, - channel_entry->founder_key)) { - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_FOUNDER_CHANGED, - channel_entry->channel_name); - } - - /* Print the channel public key list */ - if (cmode_list_chpks) { - if (chpks) - silc_parse_channel_public_keys(server, channel_entry, chpks); - else - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_PK_NO_LIST, - channel_entry->channel_name); - } - } - break; - - case SILC_COMMAND_LEAVE: - { - if (SILC_STATUS_IS_ERROR(status)) - return; - - /* We might be cycling, so disable queueing again */ - silc_queue_disable(conn); - } - break; - - case SILC_COMMAND_DETACH: - { - /* Save the detachment data to file. */ - char *file; - SilcBuffer detach; - - if (SILC_STATUS_IS_ERROR(status)) - return; - - detach = va_arg(vp, SilcBuffer); - file = silc_get_session_filename(server); - silc_file_writefile(file, silc_buffer_data(detach), - silc_buffer_len(detach)); - silc_free(file); - } - break; - - case SILC_COMMAND_KILL: - { - SilcClientEntry client_entry; - - if (SILC_STATUS_IS_ERROR(status)) { - silc_say_error("KILL: %s", silc_get_status_message(status)); - return; - } - - client_entry = va_arg(vp, SilcClientEntry); - if (!client_entry || !client_entry->nickname[0]) - break; - - /* Print this only if the killed client isn't joined on channels. - If it is, we receive KILLED notify and we'll print this there. */ - if (!silc_hash_table_count(client_entry->channels)) - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED, - client_entry->nickname, - conn->local_entry->nickname, ""); - } - } -} - -typedef struct { - SilcClient client; - SilcClientConnection conn; - char *filename; - char *entity; - char *entity_name; - SilcPublicKey public_key; - SilcVerifyPublicKey completion; - void *context; -} *PublicKeyVerify; - -static void verify_public_key_completion(const char *line, void *context) -{ - PublicKeyVerify verify = (PublicKeyVerify)context; - - if (line[0] == 'Y' || line[0] == 'y') { - /* Call the completion */ - if (verify->completion) - verify->completion(TRUE, verify->context); - - /* Save the key for future checking */ - silc_pkcs_save_public_key(verify->filename, verify->public_key, - SILC_PKCS_FILE_BASE64); - } else { - /* Call the completion */ - if (verify->completion) - verify->completion(FALSE, verify->context); - - printformat_module("fe-common/silc", NULL, NULL, - MSGLEVEL_CRAP, SILCTXT_PUBKEY_DISCARD, - verify->entity_name ? verify->entity_name : - verify->entity); - } - - silc_free(verify->filename); - silc_free(verify->entity); - silc_free(verify->entity_name); - silc_free(verify); -} - -/* Internal routine to verify public key. If the `completion' is provided - it will be called to indicate whether public was verified or not. For - server/router public key this will check for filename that includes the - remote host's IP address and remote host's hostname. */ - -static void -silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, - const char *name, - SilcConnectionType conn_type, - SilcPublicKey public_key, - SilcVerifyPublicKey completion, void *context) -{ - PublicKeyVerify verify; - char file[256], filename[256], filename2[256], *ipf, *hostf = NULL; - char *fingerprint, *babbleprint, *format; - SilcPublicKey local_pubkey; - SilcSILCPublicKey silc_pubkey; - SilcUInt16 port; - const char *hostname, *ip; - unsigned char *pk; - SilcUInt32 pk_len; - struct passwd *pw; - struct stat st; - char *entity = ((conn_type == SILC_CONN_SERVER || - conn_type == SILC_CONN_ROUTER) ? - "server" : "client"); - int i; - - if (silc_pkcs_get_type(public_key) != SILC_PKCS_SILC) { - printformat_module("fe-common/silc", NULL, NULL, - MSGLEVEL_CRAP, SILCTXT_PUBKEY_UNSUPPORTED, - entity, silc_pkcs_get_type(public_key)); - if (completion) - completion(FALSE, context); - return; - } - - /* Encode public key */ - pk = silc_pkcs_public_key_encode(NULL, public_key, &pk_len); - if (!pk) { - if (completion) - completion(FALSE, context); - return; - } - - silc_pubkey = silc_pkcs_public_key_get_pkcs(SILC_PKCS_SILC, public_key); - - pw = getpwuid(getuid()); - if (!pw) { - if (completion) - completion(FALSE, context); - silc_free(pk); - return; - } - - memset(filename, 0, sizeof(filename)); - memset(filename2, 0, sizeof(filename2)); - memset(file, 0, sizeof(file)); - - /* Get remote host information */ - silc_socket_stream_get_info(silc_packet_stream_get_stream(conn->stream), - NULL, &hostname, &ip, &port); - - if (conn_type == SILC_CONN_SERVER || - conn_type == SILC_CONN_ROUTER) { - if (!name) { - snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, ip, port); - snprintf(filename, sizeof(filename) - 1, "%s/%skeys/%s", - get_irssi_dir(), entity, file); - - snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, - hostname, port); - snprintf(filename2, sizeof(filename2) - 1, "%s/%skeys/%s", - get_irssi_dir(), entity, file); - - ipf = filename; - hostf = filename2; - } else { - snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, - name, port); - snprintf(filename, sizeof(filename) - 1, "%s/%skeys/%s", - get_irssi_dir(), entity, file); - - ipf = filename; - } - } else { - /* Replace all whitespaces with `_'. */ - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - for (i = 0; i < strlen(fingerprint); i++) - if (fingerprint[i] == ' ') - fingerprint[i] = '_'; - - snprintf(file, sizeof(file) - 1, "%skey_%s.pub", entity, fingerprint); - snprintf(filename, sizeof(filename) - 1, "%s/%skeys/%s", - get_irssi_dir(), entity, file); - silc_free(fingerprint); - - ipf = filename; - } - - /* Take fingerprint of the public key */ - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - - verify = silc_calloc(1, sizeof(*verify)); - verify->client = client; - verify->conn = conn; - verify->filename = strdup(ipf); - verify->entity = strdup(entity); - verify->entity_name = (conn_type != SILC_CONN_CLIENT ? - (name ? strdup(name) : strdup(hostname)) - : NULL); - verify->public_key = public_key; - verify->completion = completion; - verify->context = context; - - /* Check whether this key already exists */ - if (stat(ipf, &st) < 0 && (!hostf || stat(hostf, &st) < 0)) { - /* Key does not exist, ask user to verify the key and save it */ - - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_RECEIVED,verify->entity_name ? - verify->entity_name : entity); - if (conn_type == SILC_CONN_CLIENT && name && - silc_pubkey->identifier.realname) - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_RECEIVED_CLIENT, name, - silc_pubkey->identifier.realname, - silc_pubkey->identifier.email ? - silc_pubkey->identifier.email : ""); - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint); - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_BABBLEPRINT, babbleprint); - format = format_get_text("fe-common/silc", NULL, NULL, NULL, - SILCTXT_PUBKEY_ACCEPT); - keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion, - format, 0, verify); - g_free(format); - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); - return; - } else { - /* The key already exists, verify it. */ - unsigned char *encpk; - SilcUInt32 encpk_len; - - /* Load the key file, try for both IP filename and hostname filename */ - if (!silc_pkcs_load_public_key(ipf, SILC_PKCS_ANY, &local_pubkey) && - (!hostf || (!silc_pkcs_load_public_key(hostf, SILC_PKCS_ANY, - &local_pubkey)))) { - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_RECEIVED,verify->entity_name ? - verify->entity_name : entity); - if (conn_type == SILC_CONN_CLIENT && name && - silc_pubkey->identifier.realname) - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_RECEIVED_CLIENT, name, - silc_pubkey->identifier.realname, - silc_pubkey->identifier.email ? - silc_pubkey->identifier.email : ""); - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint); - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_BABBLEPRINT, babbleprint); - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_COULD_NOT_LOAD, entity); - format = format_get_text("fe-common/silc", NULL, NULL, NULL, - SILCTXT_PUBKEY_ACCEPT_ANYWAY); - keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion, - format, 0, verify); - g_free(format); - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); - return; - } - - /* Encode the key data */ - encpk = silc_pkcs_public_key_encode(NULL, local_pubkey, &encpk_len); - if (!encpk) { - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_RECEIVED,verify->entity_name ? - verify->entity_name : entity); - if (conn_type == SILC_CONN_CLIENT && name && - silc_pubkey->identifier.realname) - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_RECEIVED_CLIENT, name, - silc_pubkey->identifier.realname, - silc_pubkey->identifier.email ? - silc_pubkey->identifier.email : ""); - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint); - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_BABBLEPRINT, babbleprint); - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_MALFORMED, entity); - format = format_get_text("fe-common/silc", NULL, NULL, NULL, - SILCTXT_PUBKEY_ACCEPT_ANYWAY); - keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion, - format, 0, verify); - g_free(format); - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); - return; - } - silc_pkcs_public_key_free(local_pubkey); - - /* Compare the keys */ - if (memcmp(encpk, pk, encpk_len)) { - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_RECEIVED,verify->entity_name ? - verify->entity_name : entity); - if (conn_type == SILC_CONN_CLIENT && name && - silc_pubkey->identifier.realname) - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_RECEIVED_CLIENT, name, - silc_pubkey->identifier.realname, - silc_pubkey->identifier.email ? - silc_pubkey->identifier.email : ""); - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint); - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_BABBLEPRINT, babbleprint); - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_NO_MATCH, entity); - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_MAYBE_EXPIRED, entity); - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_PUBKEY_MITM_ATTACK, entity); - - /* Ask user to verify the key and save it */ - format = format_get_text("fe-common/silc", NULL, NULL, NULL, - SILCTXT_PUBKEY_ACCEPT_ANYWAY); - keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion, - format, 0, verify); - g_free(format); - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(encpk); - silc_free(pk); - return; - } - - /* Local copy matched */ - if (completion) - completion(TRUE, context); - silc_free(encpk); - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(verify->filename); - silc_free(verify->entity); - silc_free(verify->entity_name); - silc_free(verify); - silc_free(pk); - } -} - -/* Verifies received public key. The `conn_type' indicates which entity - (server, client etc.) has sent the public key. If user decides to trust - the key may be saved as trusted public key for later use. The - `completion' must be called after the public key has been verified. */ - -void -silc_verify_public_key(SilcClient client, SilcClientConnection conn, - SilcConnectionType conn_type, - SilcPublicKey public_key, - SilcVerifyPublicKey completion, void *context) -{ - silc_verify_public_key_internal(client, conn, NULL, conn_type, public_key, - completion, context); -} - -/* Asks passphrase from user on the input line. */ - -typedef struct { - SilcAskPassphrase completion; - void *context; -} *AskPassphrase; - -void ask_passphrase_completion(const char *passphrase, void *context) -{ - AskPassphrase p = (AskPassphrase)context; - if (passphrase && passphrase[0] == '\0') - passphrase = NULL; - p->completion((unsigned char *)passphrase, - passphrase ? strlen(passphrase) : 0, p->context); - silc_free(p); -} - -void silc_ask_passphrase(SilcClient client, SilcClientConnection conn, - SilcAskPassphrase completion, void *context) -{ - AskPassphrase p = silc_calloc(1, sizeof(*p)); - p->completion = completion; - p->context = context; - - keyboard_entry_redirect((SIGNAL_FUNC)ask_passphrase_completion, - "Passphrase: ", ENTRY_REDIRECT_FLAG_HIDDEN, p); -} - -typedef struct { - SilcGetAuthMeth completion; - void *context; -} *GetAuthMethod; - -static void silc_get_auth_ask_passphrase(const unsigned char *passphrase, - SilcUInt32 passphrase_len, - void *context) -{ - GetAuthMethod a = context; - a->completion(passphrase ? SILC_AUTH_PASSWORD : SILC_AUTH_NONE, - passphrase, passphrase_len, a->context); - silc_free(a); -} - -/* Find authentication data by hostname and port. The hostname may be IP - address as well.*/ - -void silc_get_auth_method(SilcClient client, SilcClientConnection conn, - char *hostname, SilcUInt16 port, - SilcAuthMethod auth_meth, - SilcGetAuthMeth completion, void *context) -{ - SERVER_SETUP_REC *setup; - - SILC_LOG_DEBUG(("Start")); - - if (auth_meth == SILC_AUTH_PUBLIC_KEY) { - /* Returning NULL will cause library to use our private key configured - for this connection */ - completion(SILC_AUTH_PUBLIC_KEY, NULL, 0, context); - return; - } - - /* Check whether we find the password for this server in our - configuration. If it's set, always send it server. */ - setup = server_setup_find_port(hostname, port); - if (setup && setup->password) { - completion(SILC_AUTH_PASSWORD, setup->password, strlen(setup->password), - context); - return; - } - - /* Didn't find password. If server wants it, ask it from user. */ - if (auth_meth == SILC_AUTH_PASSWORD) { - GetAuthMethod a; - a = silc_calloc(1, sizeof(*a)); - if (a) { - a->completion = completion; - a->context = context; - silc_ask_passphrase(client, conn, silc_get_auth_ask_passphrase, a); - return; - } - } - - /* No authentication */ - completion(SILC_AUTH_NONE, NULL, 0, context); -} - -/* Asks whether the user would like to perform the key agreement protocol. - This is called after we have received an key agreement packet or an - reply to our key agreement packet. This returns TRUE if the user wants - the library to perform the key agreement protocol and FALSE if it is not - desired (application may start it later by calling the function - silc_client_perform_key_agreement). */ - -void silc_key_agreement(SilcClient client, SilcClientConnection conn, - SilcClientEntry client_entry, const char *hostname, - SilcUInt16 protocol, SilcUInt16 port) -{ - char portstr[12], protostr[5]; - - SILC_LOG_DEBUG(("Start")); - - /* We will just display the info on the screen and return FALSE and user - will have to start the key agreement with a command. */ - - if (hostname) { - snprintf(portstr, sizeof(portstr) - 1, "%d", port); - snprintf(protostr, sizeof(protostr) - 1, "%s", protocol == 1 ? "UDP" : - "TCP"); - } - - if (!hostname) - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_KEY_AGREEMENT_REQUEST, client_entry->nickname); - else - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_KEY_AGREEMENT_REQUEST_HOST, - client_entry->nickname, hostname, portstr, protostr); -} - -/* Notifies application that file transfer protocol session is being - requested by the remote client indicated by the `client_entry' from - the `hostname' and `port'. The `session_id' is the file transfer - session and it can be used to either accept or reject the file - transfer request, by calling the silc_client_file_receive or - silc_client_file_close, respectively. */ - -void silc_ftp(SilcClient client, SilcClientConnection conn, - SilcClientEntry client_entry, SilcUInt32 session_id, - const char *hostname, SilcUInt16 port) -{ - SILC_SERVER_REC *server; - char portstr[12]; - FtpSession ftp = NULL; - - SILC_LOG_DEBUG(("Start")); - - server = conn->context; - - silc_dlist_start(server->ftp_sessions); - while ((ftp = silc_dlist_get(server->ftp_sessions)) != SILC_LIST_END) { - if (ftp->client_entry == client_entry && - ftp->session_id == session_id) { - server->current_session = ftp; - break; - } - } - if (ftp == SILC_LIST_END) { - ftp = silc_calloc(1, sizeof(*ftp)); - ftp->client_entry = client_entry; - ftp->session_id = session_id; - ftp->send = FALSE; - ftp->conn = conn; - silc_dlist_add(server->ftp_sessions, ftp); - server->current_session = ftp; - } - - if (hostname) - snprintf(portstr, sizeof(portstr) - 1, "%d", port); - - if (!hostname) - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_FILE_REQUEST, client_entry->nickname); - else - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_FILE_REQUEST_HOST, - client_entry->nickname, hostname, portstr); -} - -/* SILC client operations */ -SilcClientOperations ops = { - silc_say, - silc_channel_message, - silc_private_message, - silc_notify, - silc_command, - silc_command_reply, - silc_get_auth_method, - silc_verify_public_key, - silc_ask_passphrase, - silc_key_agreement, - silc_ftp, -};