From: Pekka Riikonen Date: Thu, 31 Mar 2005 06:07:09 +0000 (+0000) Subject: Added support for UTF-8 encoded nicks, channel names and X-Git-Tag: silc.server.0.9.19~21 X-Git-Url: http://git.silcnet.org/gitweb/?a=commitdiff_plain;h=35b8a75cc33fd84fb5c3b7d05e58c5128d851825;p=silc.git Added support for UTF-8 encoded nicks, channel names and server names in client library. --- diff --git a/CHANGES b/CHANGES index c543fa5b..12b4392e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,9 @@ +Thu Mar 31 08:52:06 EEST 2005 Pekka Riikonen + + * Added support for UTF-8 nicknames, channel names and + server names in client library. Affected files in + lib/silcclient/. + Wed Mar 30 22:16:35 EEST 2005 Pekka Riikonen * Added silc_utf8_str[n]casecmp into lib/silcutil/silcutf8.[ch]. diff --git a/lib/silcclient/client.c b/lib/silcclient/client.c index 33a97549..d4546038 100644 --- a/lib/silcclient/client.c +++ b/lib/silcclient/client.c @@ -227,12 +227,6 @@ void silc_client_run_one(SilcClient client) silc_schedule_one(client->schedule, 0); } -static void silc_client_entry_destructor(SilcIDCache cache, - SilcIDCacheEntry entry) -{ - silc_free(entry->name); -} - /* Allocates and adds new connection to the client. This adds the allocated connection to the connection table and returns a pointer to it. A client can have multiple connections to multiple servers. Every connection must @@ -260,12 +254,11 @@ silc_client_add_connection(SilcClient client, conn->remote_port = port; conn->context = context; conn->internal->client_cache = - silc_idcache_alloc(0, SILC_ID_CLIENT, silc_client_entry_destructor, - FALSE, FALSE); + silc_idcache_alloc(0, SILC_ID_CLIENT, NULL, FALSE, TRUE); conn->internal->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL, - FALSE, FALSE); + FALSE, TRUE); conn->internal->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL, - FALSE, FALSE); + FALSE, TRUE); conn->internal->pending_commands = silc_dlist_init(); conn->internal->ftp_sessions = silc_dlist_init(); @@ -1745,6 +1738,7 @@ void silc_client_receive_new_id(SilcClient client, SilcClientConnection conn = (SilcClientConnection)sock->user_data; int connecting = FALSE; SilcClientID *client_id = silc_id_payload_get_id(idp); + char *nickname; if (!conn->local_entry) connecting = TRUE; @@ -1787,9 +1781,14 @@ void silc_client_receive_new_id(SilcClient client, NULL, NULL, NULL, TRUE); - /* Put it to the ID cache */ - silc_idcache_add(conn->internal->client_cache, - strdup(conn->nickname), conn->local_id, + /* Normalize nickname */ + nickname = silc_identifier_check(conn->nickname, strlen(conn->nickname), + SILC_STRING_UTF8, 128, NULL); + if (!nickname) + return; + + /* Put it to the ID cache */ + silc_idcache_add(conn->internal->client_cache, nickname, conn->local_id, (void *)conn->local_entry, 0, NULL); if (connecting) { diff --git a/lib/silcclient/client_notify.c b/lib/silcclient/client_notify.c index a56d4b8b..eb1f97ed 100644 --- a/lib/silcclient/client_notify.c +++ b/lib/silcclient/client_notify.c @@ -634,11 +634,18 @@ void silc_client_notify_by_server(SilcClient client, if (SILC_ID_COMPARE_HASH(client_entry->id, client_id) && silc_utf8_strcasecmp(tmp, client_entry->nickname)) { /* Nickname didn't change. Update only Client ID. */ + + /* Normalize nickname */ + tmp = silc_identifier_check(tmp, strlen(tmp), + SILC_STRING_UTF8, 128, NULL); + if (!tmp) + goto out; + silc_idcache_del_by_context(conn->internal->client_cache, client_entry); silc_free(client_entry->id); client_entry->id = silc_id_dup(client_id, SILC_ID_CLIENT); - silc_idcache_add(conn->internal->client_cache, strdup(tmp), + silc_idcache_add(conn->internal->client_cache, tmp, client_entry->id, client_entry, 0, NULL); /* Notify application */ diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index a7f59aba..e2537fe6 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -547,10 +547,8 @@ SILC_CLIENT_CMD_FUNC(list) { SilcClientCommandContext cmd = (SilcClientCommandContext)context; SilcClientConnection conn = cmd->conn; - SilcIDCacheEntry id_cache = NULL; SilcChannelEntry channel; SilcBuffer buffer, idp = NULL; - char *name; if (!cmd->conn) { SILC_NOT_CONNECTED(cmd->client, cmd->conn); @@ -559,14 +557,10 @@ SILC_CLIENT_CMD_FUNC(list) } if (cmd->argc == 2) { - name = cmd->argv[1]; - /* Get the Channel ID of the channel */ - if (silc_idcache_find_by_name_one(conn->internal->channel_cache, - name, &id_cache)) { - channel = (SilcChannelEntry)id_cache->context; - idp = silc_id_payload_encode(id_cache->id, SILC_ID_CHANNEL); - } + channel = silc_client_get_channel(cmd->client, cmd->conn, cmd->argv[1]); + if (channel) + idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL); } if (!idp) @@ -597,7 +591,6 @@ SILC_CLIENT_CMD_FUNC(topic) { SilcClientCommandContext cmd = (SilcClientCommandContext)context; SilcClientConnection conn = cmd->conn; - SilcIDCacheEntry id_cache = NULL; SilcChannelEntry channel; SilcBuffer buffer, idp; char *name; @@ -632,16 +625,14 @@ SILC_CLIENT_CMD_FUNC(topic) } /* Get the Channel ID of the channel */ - if (!silc_idcache_find_by_name_one(conn->internal->channel_cache, - name, &id_cache)) { + channel = silc_client_get_channel(cmd->client, conn, name); + if (!channel) { COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL); goto out; } - channel = (SilcChannelEntry)id_cache->context; - /* Send TOPIC command to the server */ - idp = silc_id_payload_encode(id_cache->id, SILC_ID_CHANNEL); + idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL); if (cmd->argc > 2) buffer = silc_command_payload_encode_va(SILC_COMMAND_TOPIC, ++conn->cmd_ident, 2, @@ -1971,7 +1962,6 @@ SILC_CLIENT_CMD_FUNC(kick) SilcClientCommandContext cmd = (SilcClientCommandContext)context; SilcClient client = cmd->client; SilcClientConnection conn = cmd->conn; - SilcIDCacheEntry id_cache = NULL; SilcChannelEntry channel; SilcBuffer buffer, idp, idp2; SilcClientEntry target; @@ -2007,14 +1997,12 @@ SILC_CLIENT_CMD_FUNC(kick) } /* Get the Channel ID of the channel */ - if (!silc_idcache_find_by_name_one(conn->internal->channel_cache, - name, &id_cache)) { + channel = silc_client_get_channel(cmd->client, conn, name); + if (!channel) { COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL); goto out; } - channel = (SilcChannelEntry)id_cache->context; - /* Parse the typed nickname. */ if (client->internal->params->nickname_parse) client->internal->params->nickname_parse(cmd->argv[2], &nickname); @@ -2032,7 +2020,7 @@ SILC_CLIENT_CMD_FUNC(kick) } /* Send KICK command to the server */ - idp = silc_id_payload_encode(id_cache->id, SILC_ID_CHANNEL); + idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL); idp2 = silc_id_payload_encode(target->id, SILC_ID_CLIENT); if (cmd->argc == 3) buffer = silc_command_payload_encode_va(SILC_COMMAND_KICK, diff --git a/lib/silcclient/command_reply.c b/lib/silcclient/command_reply.c index 035f9f15..0c818a96 100644 --- a/lib/silcclient/command_reply.c +++ b/lib/silcclient/command_reply.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2004 Pekka Riikonen + Copyright (C) 1997 - 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 @@ -580,9 +580,19 @@ SILC_CLIENT_CMD_REPLY_FUNC(nick) silc_free(conn->nickname); conn->nickname = strdup(tmp); conn->local_entry->nickname = conn->nickname; + + /* Normalize nickname */ + tmp = silc_identifier_check(conn->nickname, strlen(conn->nickname), + SILC_STRING_UTF8, 128, NULL); + if (!tmp) { + COMMAND_REPLY_ERROR(SILC_STATUS_ERR_BAD_NICKNAME); + goto out; + } + silc_client_nickname_format(cmd->client, conn, conn->local_entry); - silc_idcache_add(conn->internal->client_cache, strdup(tmp), - conn->local_entry->id, conn->local_entry, 0, NULL); + + silc_idcache_add(conn->internal->client_cache, tmp, + conn->local_entry->id, conn->local_entry, 0, NULL); } /* Notify application */ diff --git a/lib/silcclient/idlist.c b/lib/silcclient/idlist.c index 8b69f6d4..51cba4e3 100644 --- a/lib/silcclient/idlist.c +++ b/lib/silcclient/idlist.c @@ -48,18 +48,28 @@ SilcClientEntry *silc_client_get_clients_local(SilcClient client, SilcClientEntry entry, *clients; int i = 0; bool found = FALSE; + char *nicknamec; assert(client && conn); if (!nickname) return NULL; + /* Normalize nickname for search */ + nicknamec = silc_identifier_check(nickname, strlen(nickname), + SILC_STRING_UTF8, 128, NULL); + if (!nicknamec) + return NULL; + /* Find ID from cache */ - if (!silc_idcache_find_by_name(conn->internal->client_cache, - (char *)nickname, &list)) + if (!silc_idcache_find_by_name(conn->internal->client_cache, nicknamec, + &list)) { + silc_free(nicknamec); return NULL; + } if (!silc_idcache_list_count(list)) { silc_idcache_list_free(list); + silc_free(nicknamec); return NULL; } @@ -95,6 +105,8 @@ SilcClientEntry *silc_client_get_clients_local(SilcClient client, } } + silc_free(nicknamec); + if (list) silc_idcache_list_free(list); @@ -381,12 +393,19 @@ SilcClientEntry silc_idlist_get_client(SilcClient client, SilcIDCacheEntry id_cache; SilcIDCacheList list = NULL; SilcClientEntry entry = NULL; + char *nicknamec; SILC_LOG_DEBUG(("Start")); + /* Normalize nickname for search */ + nicknamec = silc_identifier_check(nickname, strlen(nickname), + SILC_STRING_UTF8, 128, NULL); + if (!nicknamec) + return NULL; + /* Find ID from cache */ if (!silc_idcache_find_by_name(conn->internal->client_cache, - (char *)nickname, &list)) { + nicknamec, &list)) { identify: if (query) { @@ -405,8 +424,11 @@ SilcClientEntry silc_idlist_get_client(SilcClient client, if (list) silc_idcache_list_free(list); + silc_free(nicknamec); return NULL; } + + silc_free(nicknamec); return NULL; } @@ -440,6 +462,8 @@ SilcClientEntry silc_idlist_get_client(SilcClient client, goto identify; } + silc_free(nicknamec); + if (list) silc_idcache_list_free(list); @@ -954,12 +978,30 @@ silc_client_add_client(SilcClient client, SilcClientConnection conn, client_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr, NULL, NULL, NULL, NULL, NULL, TRUE); + /* Normalize nickname */ + if (client_entry->nickname) { + silc_free(nick); + nick = silc_identifier_check(client_entry->nickname, + strlen(client_entry->nickname), + SILC_STRING_UTF8, 128, NULL); + if (!nick) { + silc_free(client_entry->nickname); + silc_free(client_entry->username); + silc_free(client_entry->hostname); + silc_free(client_entry->server); + silc_hash_table_free(client_entry->channels); + silc_free(client_entry); + return NULL; + } + } + /* Format the nickname */ silc_client_nickname_format(client, conn, client_entry); /* Add client to cache, the non-formatted nickname is saved to cache */ if (!silc_idcache_add(conn->internal->client_cache, nick, client_entry->id, (void *)client_entry, 0, NULL)) { + silc_free(nick); silc_free(client_entry->nickname); silc_free(client_entry->username); silc_free(client_entry->hostname); @@ -999,6 +1041,16 @@ void silc_client_update_client(SilcClient client, if (!client_entry->nickname && nickname) { silc_parse_userfqdn(nickname, &nick, &client_entry->server); client_entry->nickname = strdup(nick); + + /* Normalize nickname */ + silc_free(nick); + nick = silc_identifier_check(client_entry->nickname, + strlen(client_entry->nickname), + SILC_STRING_UTF8, 128, NULL); + if (!nick) + return; + + /* Format nickname */ silc_client_nickname_format(client, conn, client_entry); } client_entry->mode = mode; @@ -1068,6 +1120,7 @@ SilcChannelEntry silc_client_add_channel(SilcClient client, SilcChannelID *channel_id) { SilcChannelEntry channel; + char *channel_namec; SILC_LOG_DEBUG(("Start")); @@ -1078,9 +1131,20 @@ SilcChannelEntry silc_client_add_channel(SilcClient client, channel->user_list = silc_hash_table_alloc(1, silc_hash_ptr, NULL, NULL, NULL, NULL, NULL, TRUE); + /* Normalize channel name */ + channel_namec = silc_identifier_check(channel_name, strlen(channel_name), + SILC_STRING_UTF8, 256, NULL); + if (!channel_namec) { + silc_free(channel->channel_name); + silc_hash_table_free(channel->user_list); + silc_free(channel); + return NULL; + } + /* Put it to the ID cache */ - if (!silc_idcache_add(conn->internal->channel_cache, channel->channel_name, + if (!silc_idcache_add(conn->internal->channel_cache, channel_namec, (void *)channel->id, (void *)channel, 0, NULL)) { + silc_free(channel_namec); silc_free(channel->channel_name); silc_hash_table_free(channel->user_list); silc_free(channel); @@ -1161,6 +1225,8 @@ bool silc_client_replace_channel_id(SilcClient client, SilcChannelEntry channel, SilcChannelID *new_id) { + char *channel_namec; + if (!new_id) return FALSE; @@ -1172,8 +1238,15 @@ bool silc_client_replace_channel_id(SilcClient client, silc_idcache_del_by_id(conn->internal->channel_cache, channel->id); silc_free(channel->id); channel->id = new_id; - return silc_idcache_add(conn->internal->channel_cache, - channel->channel_name, + + /* Normalize channel name */ + channel_namec = silc_identifier_check(channel->channel_name, + strlen(channel->channel_name), + SILC_STRING_UTF8, 256, NULL); + if (!channel_namec) + return FALSE; + + return silc_idcache_add(conn->internal->channel_cache, channel_namec, (void *)channel->id, (void *)channel, 0, NULL); } @@ -1195,14 +1268,24 @@ SilcChannelEntry silc_client_get_channel(SilcClient client, SILC_LOG_DEBUG(("Start")); + /* Normalize name for search */ + channel = silc_identifier_check(channel, strlen(channel), SILC_STRING_UTF8, + 256, NULL); + if (!channel) + return NULL; + if (!silc_idcache_find_by_name_one(conn->internal->channel_cache, channel, - &id_cache)) + &id_cache)) { + silc_free(channel); return NULL; + } entry = (SilcChannelEntry)id_cache->context; SILC_LOG_DEBUG(("Found")); + silc_free(channel); + return entry; } @@ -1373,12 +1456,22 @@ SilcServerEntry silc_client_get_server(SilcClient client, SILC_LOG_DEBUG(("Start")); + /* Normalize server name for search */ + server_name = silc_identifier_check(server_name, strlen(server_name), + SILC_STRING_UTF8, 256, NULL); + if (!server_name) + return NULL; + if (!silc_idcache_find_by_name_one(conn->internal->server_cache, - server_name, &id_cache)) + server_name, &id_cache)) { + silc_free(server_name); return NULL; + } entry = (SilcServerEntry)id_cache->context; + silc_free(server_name); + return entry; } @@ -1415,6 +1508,7 @@ SilcServerEntry silc_client_add_server(SilcClient client, SilcServerID *server_id) { SilcServerEntry server_entry; + char *server_namec = NULL; SILC_LOG_DEBUG(("Start")); @@ -1428,10 +1522,23 @@ SilcServerEntry silc_client_add_server(SilcClient client, if (server_info) server_entry->server_info = strdup(server_info); + /* Normalize server name */ + if (server_name) { + server_namec = silc_identifier_check(server_name, strlen(server_name), + SILC_STRING_UTF8, 256, NULL); + if (!server_namec) { + silc_free(server_entry->server_id); + silc_free(server_entry->server_name); + silc_free(server_entry->server_info); + silc_free(server_entry); + return NULL; + } + } + /* Add server to cache */ - if (!silc_idcache_add(conn->internal->server_cache, - server_entry->server_name, + if (!silc_idcache_add(conn->internal->server_cache, server_namec, server_entry->server_id, server_entry, 0, NULL)) { + silc_free(server_namec); silc_free(server_entry->server_id); silc_free(server_entry->server_name); silc_free(server_entry->server_info); @@ -1463,6 +1570,8 @@ void silc_client_update_server(SilcClient client, const char *server_name, const char *server_info) { + char *server_namec = NULL; + SILC_LOG_DEBUG(("Start")); if (server_name && @@ -1472,9 +1581,18 @@ void silc_client_update_server(SilcClient client, silc_idcache_del_by_context(conn->internal->server_cache, server_entry); silc_free(server_entry->server_name); server_entry->server_name = strdup(server_name); - silc_idcache_add(conn->internal->server_cache, server_entry->server_name, - server_entry->server_id, - server_entry, 0, NULL); + + /* Normalize server name */ + if (server_name) { + server_namec = silc_identifier_check(server_name, strlen(server_name), + SILC_STRING_UTF8, 256, NULL); + if (!server_namec) + return; + + silc_idcache_add(conn->internal->server_cache, server_namec, + server_entry->server_id, + server_entry, 0, NULL); + } } if (server_info &&