X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=apps%2Firssi%2Fsrc%2Fsilc%2Fcore%2Fclient_ops.c;h=44c7b0a32b2c8e6cff34cbeb2c18ff35263f41cc;hp=476fbeda80d86fcaf14452563f78aa176807ef19;hb=c257b555225193e54d85daf541d29578b3c93882;hpb=f658940d02cf2fd893296b6a7825b42502573668 diff --git a/apps/irssi/src/silc/core/client_ops.c b/apps/irssi/src/silc/core/client_ops.c index 476fbeda..44c7b0a3 100644 --- a/apps/irssi/src/silc/core/client_ops.c +++ b/apps/irssi/src/silc/core/client_ops.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2001 - 2003 Pekka Riikonen + Copyright (C) 2001 - 2005 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 @@ -29,11 +29,13 @@ #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" @@ -49,6 +51,20 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, SilcSKEPKType pk_type, 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) { @@ -83,6 +99,28 @@ static void silc_get_umode_string(SilcUInt32 mode, char *buf, 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, @@ -290,62 +328,71 @@ int verify_message_signature(SilcClientEntry sender, char * silc_unescape_data(const char *escaped_data, SilcUInt32 *length) { - SilcUInt32 ctr, dest=0; - char *data; - - data = silc_calloc(strlen(escaped_data), sizeof(char)); - - for (ctr = 0; ctr < strlen(escaped_data); ctr++) - if (escaped_data[ctr] == 1) - data[dest++] = escaped_data[++ctr] - 1; - else - data[dest++] = escaped_data[ctr]; + 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 = dest; - return data; + *length = j; + return data; } char * silc_escape_data(const char *data, SilcUInt32 len) { - char *escaped_data; - SilcUInt32 ctr, zeros=0; - - for (ctr = 0; ctr < len; ctr++) - if (data[ctr] == 0 || data[ctr] == 1) - zeros++; - - escaped_data = silc_calloc(zeros + len, sizeof(char)); - - zeros=0; - for (ctr = 0; ctr < len; ctr++) - switch (data[ctr]) { - case 0: - escaped_data[zeros++] = 1; - escaped_data[zeros++] = 1; - break; - - case 1: - escaped_data[zeros++] = 1; - escaped_data[zeros++] = 2; - break; - - default: - escaped_data[zeros++] = data[ctr]; - } + 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, SILC_CHANNEL_REC *channel, - const char *data, SilcUInt32 data_len, - const char *encoding, const char *type, const char *nick) +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", 6, server, channel, escaped_data, encoding, type, nick); - + signal_emit("mime", 5, server, item, escaped_data, nick, verified); + silc_free(escaped_data); } @@ -356,6 +403,7 @@ void silc_emit_mime_sig(SILC_SERVER_REC *server, SILC_CHANNEL_REC *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) { @@ -393,34 +441,15 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn, } if (flags & SILC_MESSAGE_FLAG_DATA) { - /* MIME object received, try to display it as well as we can */ - char type[128], enc[128]; - unsigned char *data; - SilcUInt32 data_len; - - memset(type, 0, sizeof(type)); - memset(enc, 0, sizeof(enc)); - if (!silc_mime_parse(message, message_len, NULL, 0, type, sizeof(type) - 1, - enc, sizeof(enc) - 1, &data, &data_len)) - return; - - /* Then figure out what we can display */ - if (strstr(type, "text/") && !strstr(type, "text/t140") && - !strstr(type, "text/vnd")) { - /* It is something textual, display it */ - message = (const unsigned char *)data; - } else { - silc_emit_mime_sig(server, chanrec, data, data_len, - enc, type, nick == NULL ? NULL : nick->nick); - message = NULL; - } + 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; - /* FIXME: replace those printformat calls with signals and add signature - information to them (if present) */ if (flags & SILC_MESSAGE_FLAG_ACTION) if(flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) { char tmp[256], *cp, *dm = NULL; @@ -430,17 +459,22 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn, dm = silc_calloc(message_len + 1, sizeof(*dm)); cp = dm; } - silc_utf8_decode(message, message_len, SILC_STRING_LANGUAGE, + silc_utf8_decode(message, message_len, SILC_STRING_LOCALE, cp, message_len); - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_ACTION, - nick == NULL ? "[]" : nick->nick, cp); + 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 { - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_ACTION, - nick == NULL ? "[]" : nick->nick, - message); + 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()) { @@ -451,17 +485,22 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn, dm = silc_calloc(message_len + 1, sizeof(*dm)); cp = dm; } - silc_utf8_decode(message, message_len, SILC_STRING_LANGUAGE, + silc_utf8_decode(message, message_len, SILC_STRING_LOCALE, cp, message_len); - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_NOTICES, SILCTXT_CHANNEL_NOTICE, - nick == NULL ? "[]" : nick->nick, cp); + 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 { - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_NOTICES, SILCTXT_CHANNEL_NOTICE, - nick == NULL ? "[]" : nick->nick, - message); + 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()) { @@ -474,7 +513,7 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn, cp = dm; } - silc_utf8_decode(message, message_len, SILC_STRING_LANGUAGE, + 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, @@ -535,65 +574,117 @@ void silc_private_message(SilcClient client, SilcClientConnection conn, } if (flags & SILC_MESSAGE_FLAG_DATA) { - /* MIME object received, try to display it as well as we can */ - char type[128], enc[128]; - unsigned char *data; - SilcUInt32 data_len; - - memset(type, 0, sizeof(type)); - memset(enc, 0, sizeof(enc)); - if (!silc_mime_parse(message, message_len, NULL, 0, type, sizeof(type) - 1, - enc, sizeof(enc) - 1, &data, &data_len)) - return; - - /* Then figure out what we can display */ - if (strstr(type, "text/") && !strstr(type, "text/t140") && - !strstr(type, "text/vnd")) { - /* It is something textual, display it */ - message = (const unsigned char *)data; - } else { - silc_emit_mime_sig(server, NULL, data, data_len, - enc, type, sender->nickname ? sender->nickname : - "[]"); - message = NULL; - } + silc_emit_mime_sig(server, + sender->nickname ? + (WI_ITEM_REC *)query_find(SERVER(server), sender->nickname) : + NULL, + message, message_len, + sender->nickname ? sender->nickname : "[]", + flags & SILC_MESSAGE_FLAG_SIGNED ? verified : -1); + message = NULL; } if (!message) return; - if (flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) { - char tmp[256], *cp, *dm = NULL; + 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 ? sender->nickname : "[]", + sender->username ? userhost : NULL, + NULL, verified); + else + signal_emit("message silc private_action", 5, server, cp, + sender->nickname ? sender->nickname : "[]", + sender->username ? 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 ? sender->nickname : "[]", + sender->username ? userhost : NULL, + NULL, verified); + else + signal_emit("message silc private_action", 5, server, message, + sender->nickname ? sender->nickname : "[]", + sender->username ? 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 ? sender->nickname : "[]", + sender->username ? userhost : NULL, + NULL, verified); + else + signal_emit("message silc private_notice", 5, server, cp, + sender->nickname ? sender->nickname : "[]", + sender->username ? 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 ? sender->nickname : "[]", + sender->username ? userhost : NULL, + NULL, verified); + else + signal_emit("message silc private_notice", 5, server, message, + sender->nickname ? sender->nickname : "[]", + sender->username ? 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; + } - 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 ? sender->nickname : "[]", + sender->username ? userhost : NULL, verified); + else + signal_emit("message private", 4, server, cp, + sender->nickname ? sender->nickname : "[]", + sender->username ? userhost : NULL); + silc_free(dm); + return; } - silc_utf8_decode(message, message_len, SILC_STRING_LANGUAGE, - cp, message_len); if (flags & SILC_MESSAGE_FLAG_SIGNED) - signal_emit("message signed_private", 5, server, cp, - sender->nickname ? sender->nickname : "[]", - sender->username ? userhost : NULL, verified); + signal_emit("message signed_private", 5, server, message, + sender->nickname ? sender->nickname : "[]", + sender->username ? userhost : NULL, verified); else - signal_emit("message private", 4, server, cp, - sender->nickname ? sender->nickname : "[]", - sender->username ? userhost : NULL); - silc_free(dm); - return; + signal_emit("message private", 4, server, message, + sender->nickname ? sender->nickname : "[]", + sender->username ? userhost : NULL); } - - if (flags & SILC_MESSAGE_FLAG_SIGNED) - signal_emit("message signed_private", 5, server, message, - sender->nickname ? sender->nickname : "[]", - sender->username ? userhost : NULL, verified); - else - signal_emit("message private", 4, server, message, - sender->nickname ? sender->nickname : "[]", - sender->username ? userhost : NULL); } /* Notify message to the client. The notify arguments are sent in the @@ -1201,6 +1292,9 @@ void silc_connect(SilcClient client, SilcClientConnection conn, switch (status) { case SILC_CLIENT_CONN_SUCCESS: /* We have successfully connected to server */ + if ((client->nickname != NULL) && + (strcmp(client->nickname, client->username))) + silc_queue_enable(conn); /* enable queueing until we have our nick */ server->connected = TRUE; signal_emit("event connected", 1, server); break; @@ -1222,14 +1316,37 @@ void silc_connect(SilcClient client, SilcClientConnection conn, signal_emit("message own_nick", 4, server, server->nick, old, ""); g_free(old); } + + /* remove the detach data now */ + { + char *file; + + file = silc_get_session_filename(server); + + unlink(file); + silc_free(file); + } break; default: - server->connection_lost = TRUE; - if (server->conn) - server->conn->context = NULL; - server_disconnect(SERVER(server)); - break; + { + char * file; + + file = silc_get_session_filename(server); + + if (silc_file_size(file) > 0) + printformat_module("fe-common/silc", server, NULL, + MSGLEVEL_CRAP, SILCTXT_REATTACH_FAILED, file); + + silc_free(file); + + server->connection_lost = TRUE; + if (server->conn) + server->conn->context = NULL; + server_disconnect(SERVER(server)); + + break; + } } } @@ -1578,7 +1695,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, /* Print the unknown nick for user */ unsigned char *tmp = silc_argument_get_arg_type(silc_command_get_args(cmd_payload), - 3, NULL); + 2, NULL); if (tmp) silc_say_error("%s: %s", tmp, silc_get_status_message(status)); @@ -1696,7 +1813,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, /* Print the unknown nick for user */ unsigned char *tmp = silc_argument_get_arg_type(silc_command_get_args(cmd_payload), - 3, NULL); + 2, NULL); if (tmp) silc_say_error("%s: %s", tmp, silc_get_status_message(status)); @@ -1730,11 +1847,10 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, { char *nickname, *username, *realname; - if (status == SILC_STATUS_ERR_NO_SUCH_NICK || - status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) { - char *tmp; - tmp = silc_argument_get_arg_type(silc_command_get_args(cmd_payload), - 3, NULL); + if (status == SILC_STATUS_ERR_NO_SUCH_NICK) { + char *tmp = + silc_argument_get_arg_type(silc_command_get_args(cmd_payload), + 2, NULL); if (tmp) silc_say_error("%s: %s", tmp, silc_get_status_message(status)); @@ -1820,7 +1936,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, cp = dm; } - silc_utf8_decode(topic, strlen(topic), SILC_STRING_LANGUAGE, + silc_utf8_decode(topic, strlen(topic), SILC_STRING_LOCALE, cp, strlen(topic)); topic = cp; } @@ -1872,17 +1988,22 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, collider = silc_client_get_client_by_id(client, conn, old->id); - 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); - g_slist_free(nicks); + 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); + } } + 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), @@ -1890,6 +2011,11 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, 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; } @@ -1905,6 +2031,8 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, (void)va_arg(vp, SilcChannelEntry); name = va_arg(vp, char *); + if (!name) + return; topic = va_arg(vp, char *); usercount = va_arg(vp, int); @@ -1917,7 +2045,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, cp = dm; } - silc_utf8_decode(topic, strlen(topic), SILC_STRING_LANGUAGE, + silc_utf8_decode(topic, strlen(topic), SILC_STRING_LOCALE, cp, strlen(topic)); topic = cp; } @@ -2169,7 +2297,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, cp = dm; } - silc_utf8_decode(topic, strlen(topic), SILC_STRING_LANGUAGE, + silc_utf8_decode(topic, strlen(topic), SILC_STRING_LOCALE, cp, strlen(topic)); topic = cp; } @@ -2340,11 +2468,19 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, /* Print the channel public key list */ if (channel_pubkeys) - silc_parse_channel_public_keys(server, channel_entry, channel_pubkeys); + silc_parse_channel_public_keys(server, channel_entry, channel_pubkeys); else - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_PK_NO_LIST, - channel_entry->channel_name); + printformat_module("fe-common/silc", server, NULL, + MSGLEVEL_CRAP, SILCTXT_CHANNEL_PK_NO_LIST, + channel_entry->channel_name); + + } + break; + + case SILC_COMMAND_LEAVE: + { + /* we might be cycling, so disable queueing again */ + silc_queue_disable(conn); } break; @@ -2884,13 +3020,14 @@ void silc_detach(SilcClient client, SilcClientConnection conn, const unsigned char *detach_data, SilcUInt32 detach_data_len) { - char file[256]; + SILC_SERVER_REC *server = conn->context; + char *file; /* Save the detachment data to file. */ - memset(file, 0, sizeof(file)); - snprintf(file, sizeof(file) - 1, "%s/session", get_irssi_dir()); + file = silc_get_session_filename(server); silc_file_writefile(file, detach_data, detach_data_len); + silc_free(file); }