From: Pekka Riikonen Date: Thu, 6 Sep 2001 18:35:07 +0000 (+0000) Subject: updates. X-Git-Tag: silcertest~128 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=017dec75a98209fbef49eb496c2269b0c49e736d updates. --- diff --git a/CHANGES b/CHANGES index abccd029..42413044 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,61 @@ +Thu Sep 6 12:47:37 EEST 2001 Pekka Riikonen + + * Renamed function silc_parse_nickname to silc_parse_userfqdn + to generally parse user@fqdn format strings. Affected file + lib/silcutil/silcutil.c. + + * Added nickname_format and nickname_force_format fields to the + SilcClientParams structure. The first one defines the format + for the nicknames that the library will enforce if the receives + multiple same nicknames. The second one is boolean value and + can be used to force the library to always enforce the format + to the nicknames regardles whether there are multiple nicknames + or not. This configurable formatting was employed to flexibly + support accessing multiple nicknames from the user interface. + The userinterface can now set the nicknames to what ever format + they prefer. Affected file lib/silcclient/silcapi.h. + + Added function silc_client_nickname_format to the file + lib/silcclient/idlist.c. It performs the nickname formatting. + + Added new field `hostname´ to the SilcClientEntry context. + It holds the hostname of the client. Affected file is + lib/silcclient/idlist.h. + + * Irssi SILC Client sets the nicknames in nick@hostn format. + Fe. priikone@otaku, priikone@otaku2 etc. Affected file + irssi/src/silc/core/silc-core.c. + + The WHOIS printing now also shows both the real nickname and + the formatted nickname so that user knows how to access the + user if there are multiple same nicknames cached. Affected + file irssi/src/silc/core/client_ops.c. Changed the WHOIS + printing formatting too to take the hostname now as a separate + argument. The Affected file is + irssi/src/fe-common/silc/modules-formats.[ch]. + + * Changed the silc_client_get_clients_local to accept the formatted + nickname as argument. It accepts the real nickname too but the + formatted nickname can be used to find the true entry from + multiple entries. Affected file lib/silcclient/silcapi.h and + lib/silcclient/idlist.c. + + * Added nickname_format_parse field to the SilcClientParams. + It is a callback function provided by the application to parse + the nickname out of the formatted nickname string. The library + calls it to get the nickname from the formatted string. Since + the application generally knows better the format of the nickname + string it parses it instead of the library, even though library + encodes the formatted string. If the callback function is not + provided then the library will use the string as is. The + affected file is lib/silcclient/silcapi.h. + + * All the nickname strings passed to the client library in + commands are now expected to be formatted nickname strings. + If the command does not support the formatted nickname string + it will assume that the sent string is the actual nickname. + Affected file lib/silcclient/command.c. + Tue Sep 4 22:31:28 EEST 2001 Pekka Riikonen * Added public key authentication support to OPER and SILCOPER diff --git a/TODO b/TODO index 87e796ca..cc5fc769 100644 --- a/TODO +++ b/TODO @@ -17,9 +17,12 @@ TODO/bugs in Irssi SILC client o The QUIT command should wait for servers disconnection (at least for a while) before exiting the application. - o The JOIN commands HELP is generated from Irssi IRCs JOIN help and + o The JOIN command's HELP is generated from Irssi IRCs JOIN help and the syntax is not same in SILC. This must be fixed. + o With USERS command to a channel user is not joined the name of the + channel is printed as garbled. + o Add PERL scripting support from Irssi CVS. o Extend the /HELP command to support sub commands or something. So @@ -33,13 +36,7 @@ TODO/bugs in Irssi SILC client TODO/bugs In SILC Client Library ================================ - o The client library must manage somehow when receiving client that has - same nickname, same server, same username but different Client ID than - what we have in the cache. It is now assumed that they are different - client but it might not be. It should at least number the clients - using the client->num so that they can be accessed from the user - interface separately or it could just remove the old client unless - it is on some channels. + o JOIN command's argument handling is buggy. See the XXX in the code. TODO/bugs In SILC Server @@ -47,6 +44,13 @@ TODO/bugs In SILC Server o Add perhaps /var/run/silcd.pid for PID information for the server. + o Add a timeout to handling incmoing JOIN commands. It should be + enforced that JOIN command is executed only once in a second or two + seconds. Now it is possible to accept n incoming JOIN commands + and process them without any timeouts. THis must be employed because + each JOIN command will create and distribute the new channel key + to everybody on the channel. + o Incomplete IPv6 support: o silcd/serverid.c and its routines supports only IPv4. diff --git a/apps/irssi/src/fe-common/silc/module-formats.c b/apps/irssi/src/fe-common/silc/module-formats.c index d071c95c..d542ccc6 100644 --- a/apps/irssi/src/fe-common/silc/module-formats.c +++ b/apps/irssi/src/fe-common/silc/module-formats.c @@ -51,7 +51,8 @@ FORMAT_REC fecommon_silc_formats[] = { /* WHOIS, WHOWAS and USERS (alias WHO) messages */ { NULL, "Who Queries", 0 }, - { "whois", "{nick $0} {nickhost $1}%: realname : $2", 3, { 0, 0, 0 } }, + { "whois", "{nick $0} {nickhost $1@$2}%: nickname : $3 ($4)", 5, { 0, 0, 0, 0, 0 } }, + { "whois_realname", " realname : $0", 1, { 0 } }, { "whois_channels", " channels : $0", 1, { 0 } }, { "whois_modes", " modes : $0", 1, { 0 } }, { "whois_idle", " idle : $0", 1, { 0 } }, diff --git a/apps/irssi/src/fe-common/silc/module-formats.h b/apps/irssi/src/fe-common/silc/module-formats.h index 61bd8462..60cd99a7 100644 --- a/apps/irssi/src/fe-common/silc/module-formats.h +++ b/apps/irssi/src/fe-common/silc/module-formats.h @@ -48,6 +48,7 @@ enum { SILCTXT_FILL_2, SILCTXT_WHOIS_USERINFO, + SILCTXT_WHOIS_REALNAME, SILCTXT_WHOIS_CHANNELS, SILCTXT_WHOIS_MODES, SILCTXT_WHOIS_IDLE, diff --git a/apps/irssi/src/silc/core/client_ops.c b/apps/irssi/src/silc/core/client_ops.c index 9247a3c4..79be2e8c 100644 --- a/apps/irssi/src/silc/core/client_ops.c +++ b/apps/irssi/src/silc/core/client_ops.c @@ -333,9 +333,10 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, switch(command) { case SILC_COMMAND_WHOIS: { - char buf[1024], *nickname, *username, *realname; + char buf[1024], *nickname, *username, *realname, *nick; uint32 idle, mode; SilcBuffer channels; + SilcClientEntry client_entry; if (status == SILC_STATUS_ERR_NO_SUCH_NICK || status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) { @@ -353,7 +354,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, if (!success) return; - (void)va_arg(vp, SilcClientEntry); + client_entry = va_arg(vp, SilcClientEntry); nickname = va_arg(vp, char *); username = va_arg(vp, char *); realname = va_arg(vp, char *); @@ -361,9 +362,14 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, mode = va_arg(vp, uint32); idle = va_arg(vp, uint32); + silc_parse_userfqdn(nickname, &nick, NULL); + 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_USERINFO, nickname, username, - realname); + SILCTXT_WHOIS_REALNAME, realname); + silc_free(nick); if (channels) { SilcDList list = silc_channel_payload_parse_list(channels); diff --git a/apps/irssi/src/silc/core/silc-channels.c b/apps/irssi/src/silc/core/silc-channels.c index 2ee76c58..459dedd6 100644 --- a/apps/irssi/src/silc/core/silc-channels.c +++ b/apps/irssi/src/silc/core/silc-channels.c @@ -794,8 +794,7 @@ static void command_key(const char *data, SILC_SERVER_REC *server, SilcClientConnection conn = server->conn; SilcClientEntry client_entry = NULL; SilcChannelEntry channel_entry = NULL; - uint32 num = 0; - char *nickname = NULL, *serv = NULL, *tmp; + char *nickname = NULL, *tmp; int command = 0, port = 0, type = 0; char *hostname = NULL; KeyInternal internal = NULL; @@ -836,7 +835,7 @@ static void command_key(const char *data, SILC_SERVER_REC *server, nickname = "*"; } else { /* Parse the typed nickname. */ - if (!silc_parse_nickname(argv[2], &nickname, &serv, &num)) { + if (!silc_parse_userfqdn(argv[2], &nickname, NULL)) { printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]); return; @@ -844,7 +843,7 @@ static void command_key(const char *data, SILC_SERVER_REC *server, /* Find client entry */ client_entry = silc_idlist_get_client(silc_client, conn, nickname, - serv, num, TRUE); + argv[2], TRUE); if (!client_entry) { KeyGetClients inter = silc_calloc(1, sizeof(*inter)); inter->server = server; @@ -868,10 +867,7 @@ static void command_key(const char *data, SILC_SERVER_REC *server, if (argv[2][0] == '*') { if (!conn->current_channel) { - if (nickname) - silc_free(nickname); - if (serv) - silc_free(serv); + silc_free(nickname); cmd_return_error(CMDERR_NOT_JOINED); } name = conn->current_channel->channel_name; @@ -881,10 +877,7 @@ static void command_key(const char *data, SILC_SERVER_REC *server, channel_entry = silc_client_get_channel(silc_client, conn, name); if (!channel_entry) { - if (nickname) - silc_free(nickname); - if (serv) - silc_free(serv); + silc_free(nickname); cmd_return_error(CMDERR_NOT_JOINED); } } @@ -1170,10 +1163,7 @@ static void command_key(const char *data, SILC_SERVER_REC *server, } out: - if (nickname) - silc_free(nickname); - if (serv) - silc_free(serv); + silc_free(nickname); } /* Lists locally saved client and server public keys. */ diff --git a/apps/irssi/src/silc/core/silc-core.c b/apps/irssi/src/silc/core/silc-core.c index 9ea0cfdc..9a61a48b 100644 --- a/apps/irssi/src/silc/core/silc-core.c +++ b/apps/irssi/src/silc/core/silc-core.c @@ -203,11 +203,18 @@ void silc_core_init(void) args_register(options); } +static void silc_nickname_format_parse(const char *nickname, + char **ret_nickname) +{ + silc_parse_userfqdn(nickname, ret_nickname, NULL); +} + /* Finalize init. Called from src/fe-text/silc.c */ void silc_core_init_finish(void) { CHAT_PROTOCOL_REC *rec; + SilcClientParams params; if (opt_create_keypair == TRUE) { /* Create new key pair and exit */ @@ -270,8 +277,13 @@ void silc_core_init_finish(void) settings_add_str("server", "alternate_nick", NULL); silc_init_userinfo(); + /* Initialize client parameters */ + memset(¶ms, 0, sizeof(params)); + strcat(params.nickname_format, "%n@%h%a"); + params.nickname_parse = silc_nickname_format_parse; + /* Allocate SILC client */ - silc_client = silc_client_alloc(&ops, NULL, NULL, silc_version_string); + silc_client = silc_client_alloc(&ops, ¶ms, NULL, silc_version_string); /* Load local config file */ silc_config = silc_client_config_alloc(SILC_CLIENT_HOME_CONFIG_FILE); diff --git a/apps/irssi/src/silc/core/silc-servers.c b/apps/irssi/src/silc/core/silc-servers.c index a810b8ee..4afc3517 100644 --- a/apps/irssi/src/silc/core/silc-servers.c +++ b/apps/irssi/src/silc/core/silc-servers.c @@ -61,6 +61,7 @@ static void silc_send_channel(SILC_SERVER_REC *server, typedef struct { char *nick; char *msg; + SILC_SERVER_REC *server; } PRIVMSG_REC; /* Callback function that sends the private message if the client was @@ -73,18 +74,39 @@ static void silc_send_msg_clients(SilcClient client, void *context) { PRIVMSG_REC *rec = context; + SILC_SERVER_REC *server = rec->server; SilcClientEntry target; - - if (clients_count == 0) { + char *nickname = NULL; + + if (!clients_count) { printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown nick: %s", rec->nick); } else { - target = clients[0]; /* FIXME: not a good idea :) */ - + if (clients_count > 1) { + silc_parse_userfqdn(rec->nick, &nickname, NULL); + + /* Find the correct one. The rec->nick might be a formatted nick + so this will find the correct one. */ + clients = silc_client_get_clients_local(silc_client, server->conn, + nickname, rec->nick, + &clients_count); + if (!clients) { + printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown nick: %s", + rec->nick); + silc_free(nickname); + goto out; + } + silc_free(nickname); + } + + target = clients[0]; + + /* Send the private message */ silc_client_send_private_message(client, conn, target, 0, rec->msg, strlen(rec->msg), TRUE); } + out: g_free(rec->nick); g_free(rec->msg); g_free(rec); @@ -93,33 +115,36 @@ static void silc_send_msg_clients(SilcClient client, static void silc_send_msg(SILC_SERVER_REC *server, char *nick, char *msg) { PRIVMSG_REC *rec; - SilcClientEntry client_entry; - uint32 num = 0; - char *nickname = NULL, *serv = NULL; - - if (!silc_parse_nickname(nick, &nickname, &serv, &num)) { + SilcClientEntry *clients; + uint32 clients_count; + char *nickname = NULL; + + if (!silc_parse_userfqdn(nick, &nickname, NULL)) { printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_BAD_NICK, nick); return; } /* Find client entry */ - client_entry = silc_idlist_get_client(silc_client, server->conn, - nickname, serv, num, FALSE); - if (!client_entry) { + clients = silc_client_get_clients_local(silc_client, server->conn, + nickname, nick, &clients_count); + silc_free(nickname); + + if (!clients) { rec = g_new0(PRIVMSG_REC, 1); rec->nick = g_strdup(nick); rec->msg = g_strdup(msg); + rec->server = server; /* Could not find client with that nick, resolve it from server. */ silc_client_get_clients(silc_client, server->conn, - nickname, serv, silc_send_msg_clients, rec); + nickname, NULL, silc_send_msg_clients, rec); return; } /* Send the private message directly */ - silc_client_send_private_message(silc_client, server->conn, client_entry, 0, - msg, strlen(msg), TRUE); + silc_client_send_private_message(silc_client, server->conn, + clients[0], 0, msg, strlen(msg), TRUE); } static int isnickflag_func(char flag) @@ -252,20 +277,20 @@ char *silc_server_get_channels(SILC_SERVER_REC *server) /* SYNTAX: BAN [+|-[[@[![@hostname>]]]]] */ /* SYNTAX: CMODE +|- [{ }] */ -/* SYNTAX: CUMODE +|- [@] [-pubkey|] */ +/* SYNTAX: CUMODE +|- [@] [-pubkey|] */ /* SYNTAX: GETKEY */ -/* SYNTAX: INVITE [[@server>] */ +/* SYNTAX: INVITE [[@hostname>] */ /* SYNTAX: INVITE [+|-[[@[![@hostname>]]]]] */ /* SYNTAX: KEY MSG set|unset|list|agreement|negotiate [] */ /* SYNTAX: KEY CHANNEL set|unset|list|agreement|negotiate [] */ -/* SYNTAX: KICK [@] [] */ -/* SYNTAX: KILL [@] [] */ +/* SYNTAX: KICK [@] [] */ +/* SYNTAX: KILL [@] [] */ /* SYNTAX: OPER [-pubkey] */ /* SYNTAX: SILCOPER [-pubkey] */ /* SYNTAX: TOPIC [] */ /* SYNTAX: UMODE +|- */ -/* SYNTAX: WHOIS [@] [] */ -/* SYNTAX: WHOWAS [@] [] */ +/* SYNTAX: WHOIS [@] [] */ +/* SYNTAX: WHOWAS [@] [] */ /* SYNTAX: CLOSE [] */ /* SYNTAX: SHUTDOWN */ /* SYNTAX: MOTD [] */ diff --git a/doc/draft-riikonen-silc-commands-02.nroff b/doc/draft-riikonen-silc-commands-02.nroff index 0094ece8..ac17d89c 100644 --- a/doc/draft-riikonen-silc-commands-02.nroff +++ b/doc/draft-riikonen-silc-commands-02.nroff @@ -389,7 +389,7 @@ List of all defined commands in SILC follows. Reply messages to the command: Max Arguments: 4 - Arguments: (1) (2) + Arguments: (1) (2) (3) [] (4) [] This command may reply with several command reply messages to form @@ -399,7 +399,7 @@ List of all defined commands in SILC follows. one reply the status is set to normal STATUS_OK. When querying clients the must include the client's - nickname in the following format: nickname>[@server]. The + nickname in the following format: nickname[@server]. The must include the client's username and host in the following format: username@host. diff --git a/lib/silcclient/client.c b/lib/silcclient/client.c index aebaebe6..681d9e0e 100644 --- a/lib/silcclient/client.c +++ b/lib/silcclient/client.c @@ -2,7 +2,7 @@ client.c - Author: Pekka Riikonen + Author: Pekka Riikonen Copyright (C) 1997 - 2001 Pekka Riikonen @@ -60,12 +60,18 @@ SilcClient silc_client_alloc(SilcClientOperations *ops, if (params) memcpy(new_client->params, params, sizeof(*params)); + if (!new_client->params->task_max) + new_client->params->task_max = 200; + if (!new_client->params->rekey_secs) new_client->params->rekey_secs = 3600; if (!new_client->params->connauth_request_secs) new_client->params->connauth_request_secs = 2; + new_client->params-> + nickname_format[sizeof(new_client->params->nickname_format) - 1] = 0; + return new_client; } @@ -142,6 +148,12 @@ void silc_client_run(SilcClient client) silc_schedule(client->schedule); } +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 @@ -161,7 +173,8 @@ SilcClientConnection silc_client_add_connection(SilcClient client, conn = silc_calloc(1, sizeof(*conn)); /* Initialize ID caches */ - conn->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT, NULL); + conn->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT, + silc_client_entry_destructor); conn->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL); conn->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL); conn->client = client; @@ -318,9 +331,9 @@ int silc_client_connect_to_server(SilcClient client, int port, used only if the application performed the connecting outside the library. The library however may use this internally. */ -int silc_client_start_key_exchange(SilcClient client, - SilcClientConnection conn, - int fd) +bool silc_client_start_key_exchange(SilcClient client, + SilcClientConnection conn, + int fd) { SilcProtocol protocol; SilcClientKEInternalContext *proto_ctx; @@ -357,7 +370,7 @@ int silc_client_start_key_exchange(SilcClient client, silc_client_connect_to_server_second); if (!protocol) { client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR, - "Error: Could not start authentication protocol"); + "Error: Could not start key exchange protocol"); return FALSE; } conn->sock->protocol = protocol; @@ -1369,18 +1382,15 @@ void silc_client_receive_new_id(SilcClient client, conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry)); conn->local_entry->nickname = conn->nickname; - if (!conn->local_entry->username) { - conn->local_entry->username = - silc_calloc(strlen(client->username) + strlen(client->hostname) + 1, - sizeof(conn->local_entry->username)); - sprintf(conn->local_entry->username, "%s@%s", client->username, - client->hostname); - } + if (!conn->local_entry->username) + conn->local_entry->username = strdup(client->username); + if (!conn->local_entry->hostname) + conn->local_entry->hostname = strdup(client->hostname); conn->local_entry->server = strdup(conn->remote_host); conn->local_entry->id = conn->local_id; /* Put it to the ID cache */ - silc_idcache_add(conn->client_cache, conn->nickname, conn->local_id, + silc_idcache_add(conn->client_cache, strdup(conn->nickname), conn->local_id, (void *)conn->local_entry, FALSE); /* Issue INFO command to fetch the real server name and server information diff --git a/lib/silcclient/client.h b/lib/silcclient/client.h index c0e33228..7259267f 100644 --- a/lib/silcclient/client.h +++ b/lib/silcclient/client.h @@ -2,7 +2,7 @@ client.h - Author: Pekka Riikonen + Author: Pekka Riikonen Copyright (C) 1997 - 2001 Pekka Riikonen diff --git a/lib/silcclient/client_notify.c b/lib/silcclient/client_notify.c index dd787cac..a0799173 100644 --- a/lib/silcclient/client_notify.c +++ b/lib/silcclient/client_notify.c @@ -190,7 +190,7 @@ void silc_client_notify_by_server(SilcClient client, /* Get channel entry */ if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id, - &id_cache)) + &id_cache)) break; channel = (SilcChannelEntry)id_cache->context; diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index 5379000a..b449b115 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -549,8 +549,8 @@ SILC_CLIENT_CMD_FUNC(invite) SilcClientEntry client_entry = NULL; SilcChannelEntry channel; SilcBuffer buffer, clidp, chidp; - uint32 num = 0, type = 0; - char *nickname = NULL, *server = NULL, *name; + uint32 type = 0; + char *nickname = NULL, *name; char *invite = NULL; if (!cmd->conn) { @@ -591,21 +591,16 @@ SILC_CLIENT_CMD_FUNC(invite) /* Parse the typed nickname. */ if (cmd->argc == 3) { if (cmd->argv[2][0] != '+' && cmd->argv[2][0] != '-') { - if (!silc_parse_nickname(cmd->argv[2], &nickname, &server, &num)) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, - "Bad nickname"); - COMMAND_ERROR; - goto out; - } - + if (client->params->nickname_parse) + client->params->nickname_parse(cmd->argv[2], &nickname); + else + nickname = strdup(cmd->argv[2]); + /* Find client entry */ client_entry = silc_idlist_get_client(client, conn, nickname, - server, num, TRUE); + cmd->argv[2], TRUE); if (!client_entry) { - if (nickname) - silc_free(nickname); - if (server) - silc_free(server); + silc_free(nickname); if (cmd->pending) { COMMAND_ERROR; @@ -660,10 +655,7 @@ SILC_CLIENT_CMD_FUNC(invite) COMMAND; out: - if (nickname) - silc_free(nickname); - if (server) - silc_free(server); + silc_free(nickname); silc_client_command_free(cmd); } @@ -731,11 +723,11 @@ SILC_CLIENT_CMD_FUNC(quit) SILC_CLIENT_CMD_FUNC(kill) { SilcClientCommandContext cmd = (SilcClientCommandContext)context; + SilcClient client = cmd->client; SilcClientConnection conn = cmd->conn; SilcBuffer buffer, idp; SilcClientEntry target; - uint32 num = 0; - char *nickname = NULL, *server = NULL; + char *nickname = NULL; if (!cmd->conn) { SILC_NOT_CONNECTED(cmd->client, cmd->conn); @@ -751,20 +743,16 @@ SILC_CLIENT_CMD_FUNC(kill) } /* Parse the typed nickname. */ - if (!silc_parse_nickname(cmd->argv[1], &nickname, &server, &num)) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, - "Bad nickname"); - COMMAND_ERROR; - goto out; - } + if (client->params->nickname_parse) + client->params->nickname_parse(cmd->argv[1], &nickname); + else + nickname = strdup(cmd->argv[1]); /* Get the target client */ target = silc_idlist_get_client(cmd->client, conn, nickname, - server, num, TRUE); + cmd->argv[1], TRUE); if (!target) { silc_free(nickname); - if (server) - silc_free(server); if (cmd->pending) { COMMAND_ERROR; @@ -801,10 +789,7 @@ SILC_CLIENT_CMD_FUNC(kill) COMMAND; out: - if (nickname) - silc_free(nickname); - if (server) - silc_free(server); + silc_free(nickname); silc_client_command_free(cmd); } @@ -1330,6 +1315,7 @@ SILC_CLIENT_CMD_FUNC(cmode) SILC_CLIENT_CMD_FUNC(cumode) { SilcClientCommandContext cmd = (SilcClientCommandContext)context; + SilcClient client = cmd->client; SilcClientConnection conn = cmd->conn; SilcChannelEntry channel; SilcChannelUser chu; @@ -1337,8 +1323,7 @@ SILC_CLIENT_CMD_FUNC(cumode) SilcBuffer buffer, clidp, chidp, auth = NULL; unsigned char *name, *cp, modebuf[4]; uint32 mode = 0, add, len; - char *nickname = NULL, *server = NULL; - uint32 num = 0; + char *nickname = NULL; int i; if (!cmd->conn) { @@ -1376,16 +1361,17 @@ SILC_CLIENT_CMD_FUNC(cumode) } /* Parse the typed nickname. */ - if (!silc_parse_nickname(cmd->argv[3], &nickname, &server, &num)) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, "Bad nickname"); - COMMAND_ERROR; - goto out; - } + if (client->params->nickname_parse) + client->params->nickname_parse(cmd->argv[3], &nickname); + else + nickname = strdup(cmd->argv[3]); /* Find client entry */ - client_entry = silc_idlist_get_client(cmd->client, conn, - nickname, server, num, TRUE); + client_entry = silc_idlist_get_client(cmd->client, conn, nickname, + cmd->argv[3], TRUE); if (!client_entry) { + silc_free(nickname); + if (cmd->pending) { COMMAND_ERROR; goto out; @@ -1486,10 +1472,7 @@ SILC_CLIENT_CMD_FUNC(cumode) COMMAND; out: - if (nickname) - silc_free(nickname); - if (server) - silc_free(server); + silc_free(nickname); silc_client_command_free(cmd); } @@ -1498,14 +1481,14 @@ SILC_CLIENT_CMD_FUNC(cumode) 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; char *name; - uint32 num = 0; - char *nickname = NULL, *server = NULL; + char *nickname = NULL; if (!cmd->conn) { SILC_NOT_CONNECTED(cmd->client, cmd->conn); @@ -1550,16 +1533,14 @@ SILC_CLIENT_CMD_FUNC(kick) channel = (SilcChannelEntry)id_cache->context; /* Parse the typed nickname. */ - if (!silc_parse_nickname(cmd->argv[2], &nickname, &server, &num)) { - cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, - "Bad nickname"); - COMMAND_ERROR; - goto out; - } + if (client->params->nickname_parse) + client->params->nickname_parse(cmd->argv[2], &nickname); + else + nickname = strdup(cmd->argv[2]); /* Get the target client */ target = silc_idlist_get_client(cmd->client, conn, nickname, - server, num, FALSE); + cmd->argv[2], FALSE); if (!target) { cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, "No such client: %s", @@ -1591,10 +1572,7 @@ SILC_CLIENT_CMD_FUNC(kick) COMMAND; out: - if (nickname) - silc_free(nickname); - if (server) - silc_free(server); + silc_free(nickname); silc_client_command_free(cmd); } @@ -2059,8 +2037,7 @@ SILC_CLIENT_CMD_FUNC(getkey) SilcClient client = cmd->client; SilcClientEntry client_entry = NULL; SilcServerEntry server_entry = NULL; - uint32 num = 0; - char *nickname = NULL, *server = NULL; + char *nickname = NULL; SilcBuffer idp, buffer; if (!cmd->conn) { @@ -2077,18 +2054,17 @@ SILC_CLIENT_CMD_FUNC(getkey) } /* Parse the typed nickname. */ - if (!silc_parse_nickname(cmd->argv[1], &nickname, &server, &num)) { - client->ops->say(client, conn, SILC_CLIENT_MESSAGE_INFO, "Bad nickname"); - COMMAND_ERROR; - goto out; - } + if (client->params->nickname_parse) + client->params->nickname_parse(cmd->argv[1], &nickname); + else + nickname = strdup(cmd->argv[1]); /* Find client entry */ - client_entry = silc_idlist_get_client(client, conn, nickname, server, num, + client_entry = silc_idlist_get_client(client, conn, nickname, cmd->argv[1], FALSE); if (!client_entry) { /* Check whether user requested server actually */ - server_entry = silc_client_get_server(client, conn, nickname); + server_entry = silc_client_get_server(client, conn, cmd->argv[1]); if (!server_entry) { /* No. what ever user wants we don't have it, so resolve it. We @@ -2096,7 +2072,7 @@ SILC_CLIENT_CMD_FUNC(getkey) bound to be wrong. */ /* This will send the IDENTIFY command */ - silc_idlist_get_client(client, conn, nickname, server, num, TRUE); + silc_idlist_get_client(client, conn, nickname, cmd->argv[1], TRUE); silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, conn->cmd_ident, silc_client_command_destructor, @@ -2106,7 +2082,7 @@ SILC_CLIENT_CMD_FUNC(getkey) /* This sends the INFO command to resolve the server. */ silc_client_send_command(client, conn, SILC_COMMAND_INFO, ++conn->cmd_ident, 1, - 1, nickname, strlen(nickname)); + 1, cmd->argv[1], cmd->argv_lens[1]); silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, conn->cmd_ident, silc_client_command_destructor, @@ -2114,6 +2090,7 @@ SILC_CLIENT_CMD_FUNC(getkey) silc_client_command_dup(cmd)); cmd->pending = 1; + silc_free(nickname); return; } @@ -2133,5 +2110,6 @@ SILC_CLIENT_CMD_FUNC(getkey) COMMAND; out: + silc_free(nickname); silc_client_command_free(cmd); } diff --git a/lib/silcclient/command_reply.c b/lib/silcclient/command_reply.c index 61bade4b..79acee69 100644 --- a/lib/silcclient/command_reply.c +++ b/lib/silcclient/command_reply.c @@ -257,43 +257,13 @@ silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd, silc_hash_client_id_compare, NULL, &id_cache)) { SILC_LOG_DEBUG(("Adding new client entry")); - - client_entry = silc_calloc(1, sizeof(*client_entry)); - client_entry->id = client_id; - silc_parse_nickname(nickname, &client_entry->nickname, - &client_entry->server, &client_entry->num); - client_entry->username = strdup(username); - if (realname) - client_entry->realname = strdup(realname); - client_entry->mode = mode; - - /* Add client to cache */ - silc_idcache_add(conn->client_cache, client_entry->nickname, - client_id, (void *)client_entry, FALSE); + client_entry = + silc_client_add_client(cmd->client, conn, nickname, username, realname, + client_id, mode); } else { client_entry = (SilcClientEntry)id_cache->context; - if (client_entry->nickname) - silc_free(client_entry->nickname); - if (client_entry->server) - silc_free(client_entry->server); - if (client_entry->username) - silc_free(client_entry->username); - if (client_entry->realname) - silc_free(client_entry->realname); - client_entry->mode = mode; - - SILC_LOG_DEBUG(("Updating client entry")); - - silc_parse_nickname(nickname, &client_entry->nickname, - &client_entry->server, &client_entry->num); - client_entry->username = strdup(username); - if (realname) - client_entry->realname = strdup(realname); - - /* Remove the old cache entry and create a new one */ - silc_idcache_del_by_context(conn->client_cache, client_entry); - silc_idcache_add(conn->client_cache, client_entry->nickname, - client_entry->id, client_entry, FALSE); + silc_client_update_client(cmd->client, conn, client_entry, + nickname, username, realname, mode); silc_free(client_id); } @@ -477,38 +447,13 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd, silc_hash_client_id_compare, NULL, &id_cache)) { SILC_LOG_DEBUG(("Adding new client entry")); - - client_entry = silc_calloc(1, sizeof(*client_entry)); - client_entry->id = silc_id_dup(client_id, id_type); - silc_parse_nickname(name, &client_entry->nickname, - &client_entry->server, &client_entry->num); - if (info) - client_entry->username = strdup(info); - - /* Add client to cache */ - silc_idcache_add(conn->client_cache, client_entry->nickname, - client_entry->id, (void *)client_entry, FALSE); + client_entry = + silc_client_add_client(cmd->client, conn, name, info, NULL, + silc_id_dup(client_id, id_type), 0); } else { client_entry = (SilcClientEntry)id_cache->context; - if (client_entry->nickname) - silc_free(client_entry->nickname); - if (client_entry->server) - silc_free(client_entry->server); - if (info && client_entry->username) - silc_free(client_entry->username); - - SILC_LOG_DEBUG(("Updating client entry")); - - silc_parse_nickname(name, &client_entry->nickname, - &client_entry->server, &client_entry->num); - - if (info) - client_entry->username = strdup(info); - - /* Remove the old cache entry and create a new one */ - silc_idcache_del_by_context(conn->client_cache, client_entry); - silc_idcache_add(conn->client_cache, client_entry->nickname, - client_entry->id, client_entry, FALSE); + silc_client_update_client(cmd->client, conn, client_entry, + name, info, NULL, 0); } /* Notify application */ @@ -1142,10 +1087,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(join) silc_hash_client_id_compare, NULL, &id_cache)) { /* No, we don't have it, add entry for it. */ - client_entry = silc_calloc(1, sizeof(*client_entry)); - client_entry->id = silc_id_dup(client_id, SILC_ID_CLIENT); - silc_idcache_add(conn->client_cache, NULL, client_entry->id, - (void *)client_entry, FALSE); + client_entry = + silc_client_add_client(cmd->client, conn, NULL, NULL, NULL, + silc_id_dup(client_id, SILC_ID_CLIENT), 0); } else { /* Yes, we have it already */ client_entry = (SilcClientEntry)id_cache->context; diff --git a/lib/silcclient/idlist.c b/lib/silcclient/idlist.c index 66270cdc..ffbcf29b 100644 --- a/lib/silcclient/idlist.c +++ b/lib/silcclient/idlist.c @@ -2,9 +2,9 @@ idlist.c - Author: Pekka Riikonen + Author: Pekka Riikonen - Copyright (C) 2000 Pekka Riikonen + Copyright (C) 2001 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 @@ -74,8 +74,8 @@ static void silc_client_get_client_destructor(void *context) void silc_client_get_clients(SilcClient client, SilcClientConnection conn, - char *nickname, - char *server, + const char *nickname, + const char *server, SilcGetClientCallback completion, void *context) { @@ -111,13 +111,19 @@ void silc_client_get_clients(SilcClient client, (void *)i); } -/* Same as above function but does not resolve anything from the server. - This checks local cache and returns all clients from the cache. */ +/* Same as silc_client_get_clients function but does not resolve anything + from the server. This checks local cache and returns all matching + clients from the local cache. If none was found this returns NULL. + The `nickname' is the real nickname of the client, and the `format' + is the formatted nickname to find exact match from multiple found + entries. The format must be same as given in the SilcClientParams + structure to the client library. If the `format' is NULL all found + clients by `nickname' are returned. */ SilcClientEntry *silc_client_get_clients_local(SilcClient client, SilcClientConnection conn, - char *nickname, - char *server, + const char *nickname, + const char *format, uint32 *clients_count) { SilcIDCacheEntry id_cache; @@ -127,7 +133,7 @@ SilcClientEntry *silc_client_get_clients_local(SilcClient client, bool found = FALSE; /* Find ID from cache */ - if (!silc_idcache_find_by_name(conn->client_cache, nickname, &list)) + if (!silc_idcache_find_by_name(conn->client_cache, (char *)nickname, &list)) return NULL; if (!silc_idcache_list_count(list)) { @@ -138,7 +144,7 @@ SilcClientEntry *silc_client_get_clients_local(SilcClient client, clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients)); *clients_count = silc_idcache_list_count(list); - if (!server) { + if (!format) { /* Take all without any further checking */ silc_idcache_list_first(list, &id_cache); while (id_cache) { @@ -152,9 +158,7 @@ SilcClientEntry *silc_client_get_clients_local(SilcClient client, silc_idcache_list_first(list, &id_cache); while (id_cache) { entry = (SilcClientEntry)id_cache->context; - - if (entry->server && - strncasecmp(server, entry->server, strlen(server))) { + if (strcasecmp(entry->nickname, format)) { if (!silc_idcache_list_next(list, &id_cache)) { break; } else { @@ -358,17 +362,17 @@ void silc_client_get_clients_by_list(SilcClient client, SilcClientEntry silc_idlist_get_client(SilcClient client, SilcClientConnection conn, - char *nickname, - char *server, - uint32 num, - int query) + const char *nickname, + const char *format, + bool query) { SilcIDCacheEntry id_cache; SilcIDCacheList list = NULL; SilcClientEntry entry = NULL; /* Find ID from cache */ - if (!silc_idcache_find_by_name(conn->client_cache, nickname, &list)) { + if (!silc_idcache_find_by_name(conn->client_cache, (char *)nickname, + &list)) { identify: if (query) { @@ -397,7 +401,7 @@ SilcClientEntry silc_idlist_get_client(SilcClient client, return NULL; } - if (!server && !num) { + if (!format) { /* Take first found cache entry */ if (!silc_idcache_list_first(list, &id_cache)) goto identify; @@ -406,22 +410,20 @@ SilcClientEntry silc_idlist_get_client(SilcClient client, } else { /* Check multiple cache entries for match */ silc_idcache_list_first(list, &id_cache); - entry = (SilcClientEntry)id_cache->context; - - while (entry) { - if (server && entry->server && - !strncasecmp(server, entry->server, strlen(server))) - break; - - if (num && entry->num == num) - break; + while (id_cache) { + entry = (SilcClientEntry)id_cache->context; - if (!silc_idcache_list_next(list, &id_cache)) { - entry = NULL; - break; + if (strcasecmp(entry->nickname, format)) { + if (!silc_idcache_list_next(list, &id_cache)) { + entry = NULL; + break; + } else { + entry = NULL; + continue; + } } - entry = (SilcClientEntry)id_cache->context; + break; } /* If match weren't found, request it */ @@ -527,6 +529,78 @@ void silc_client_get_client_by_id_resolve(SilcClient client, (void *)i); } +/* Creates new client entry and adds it to the ID cache. Returns pointer + to the new entry. */ + +SilcClientEntry +silc_client_add_client(SilcClient client, SilcClientConnection conn, + char *nickname, char *username, + char *userinfo, SilcClientID *id, uint32 mode) +{ + SilcClientEntry client_entry; + char *nick = NULL; + + /* Save the client infos */ + client_entry = silc_calloc(1, sizeof(*client_entry)); + client_entry->id = id; + silc_parse_userfqdn(nickname, &nick, &client_entry->server); + silc_parse_userfqdn(username, &client_entry->username, + &client_entry->hostname); + if (userinfo) + client_entry->realname = strdup(userinfo); + client_entry->mode = mode; + if (nick) + client_entry->nickname = strdup(nick); + + /* 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->client_cache, nick, client_entry->id, + (void *)client_entry, FALSE)) { + silc_free(client_entry->nickname); + silc_free(client_entry->username); + silc_free(client_entry->hostname); + silc_free(client_entry->server); + silc_free(client_entry); + return NULL; + } + + return client_entry; +} + +/* Updates the `client_entry' with the new information sent as argument. */ + +void silc_client_update_client(SilcClient client, + SilcClientConnection conn, + SilcClientEntry client_entry, + const char *nickname, + const char *username, + const char *userinfo, + uint32 mode) +{ + char *nick = NULL; + + if (!client_entry->username && username) + silc_parse_userfqdn(username, &client_entry->username, + &client_entry->hostname); + if (!client_entry->realname && userinfo) + client_entry->realname = strdup(userinfo); + if (!client_entry->nickname && nickname) { + silc_parse_userfqdn(nickname, &nick, &client_entry->server); + client_entry->nickname = strdup(nick); + silc_client_nickname_format(client, conn, client_entry); + } + client_entry->mode = mode; + + if (nick) { + /* Remove the old cache entry and create a new one */ + silc_idcache_del_by_context(conn->client_cache, client_entry); + silc_idcache_add(conn->client_cache, nick, client_entry->id, + client_entry, FALSE); + } +} + /* Deletes the client entry and frees all memory. */ void silc_client_del_client_entry(SilcClient client, @@ -751,3 +825,132 @@ bool silc_client_del_server(SilcClient client, SilcClientConnection conn, silc_free(server); return ret; } + +/* Formats the nickname of the client specified by the `client_entry'. + If the format is specified by the application this will format the + nickname and replace the old nickname in the client entry. If the + format string is not specified then this function has no effect. */ + +void silc_client_nickname_format(SilcClient client, + SilcClientConnection conn, + SilcClientEntry client_entry) +{ + char *cp; + char *newnick = NULL; + int i, off = 0, len; + SilcClientEntry *clients; + uint32 clients_count; + + if (!client->params->nickname_format[0]) + return; + + if (!client_entry->nickname) + return; + + /* Get all clients with same nickname. Do not perform the formatting + if there aren't any clients with same nickname unless the application + is forcing us to do so. */ + clients = silc_client_get_clients_local(client, conn, + client_entry->nickname, NULL, + &clients_count); + if (!clients && !client->params->nickname_force_format) + return; + + cp = client->params->nickname_format; + while (*cp) { + if (*cp == '%') { + cp++; + continue; + } + + switch(*cp) { + case 'n': + /* Nickname */ + if (!client_entry->nickname) + break; + len = strlen(client_entry->nickname); + newnick = silc_realloc(newnick, sizeof(*newnick) * (off + len)); + memcpy(&newnick[off], client_entry->nickname, len); + off += len; + break; + case 'h': + /* Stripped hostname */ + if (!client_entry->hostname) + break; + len = strcspn(client_entry->hostname, "."); + newnick = silc_realloc(newnick, sizeof(*newnick) * (off + len)); + memcpy(&newnick[off], client_entry->hostname, len); + off += len; + break; + case 'H': + /* Full hostname */ + if (!client_entry->hostname) + break; + len = strlen(client_entry->hostname); + newnick = silc_realloc(newnick, sizeof(*newnick) * (off + len)); + memcpy(&newnick[off], client_entry->hostname, len); + off += len; + break; + case 's': + /* Stripped server name */ + if (!client_entry->server) + break; + len = strcspn(client_entry->server, "."); + newnick = silc_realloc(newnick, sizeof(*newnick) * (off + len)); + memcpy(&newnick[off], client_entry->server, len); + off += len; + break; + case 'S': + /* Full server name */ + if (!client_entry->server) + break; + len = strlen(client_entry->server); + newnick = silc_realloc(newnick, sizeof(*newnick) * (off + len)); + memcpy(&newnick[off], client_entry->server, len); + off += len; + break; + case 'a': + /* Ascending number */ + { + char tmp[6]; + int num, max = 1; + + if (clients_count == 1) + break; + + for (i = 0; i < clients_count; i++) { + if (strncmp(clients[i]->nickname, newnick, off)) + continue; + if (strlen(clients[i]->nickname) <= off) + continue; + num = atoi(&clients[i]->nickname[off]); + if (num > max) + max = num; + } + + memset(tmp, 0, sizeof(tmp)); + snprintf(tmp, sizeof(tmp) - 1, "%d", ++max); + len = strlen(tmp); + newnick = silc_realloc(newnick, sizeof(*newnick) * (off + len)); + memcpy(&newnick[off], tmp, len); + off += len; + } + break; + default: + /* Some other character in the string */ + newnick = silc_realloc(newnick, sizeof(*newnick) * (off + 1)); + memcpy(&newnick[off], cp, 1); + off++; + break; + } + + cp++; + } + + newnick = silc_realloc(newnick, sizeof(*newnick) * (off + 1)); + newnick[off] = 0; + + silc_free(client_entry->nickname); + client_entry->nickname = newnick; + silc_free(clients); +} diff --git a/lib/silcclient/idlist.h b/lib/silcclient/idlist.h index 815d0392..c120ff29 100644 --- a/lib/silcclient/idlist.h +++ b/lib/silcclient/idlist.h @@ -2,9 +2,9 @@ idlist.h - Author: Pekka Riikonen + Author: Pekka Riikonen - Copyright (C) 1997 - 2000 Pekka Riikonen + Copyright (C) 1997 - 2001 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 @@ -27,7 +27,8 @@ they are used. */ typedef struct { char *nickname; /* nickname */ - char *username; /* username[@host] */ + char *username; /* username */ + char *hostname; /* hostname */ char *server; /* SILC server name */ char *realname; /* Realname (userinfo) */ uint32 num; @@ -91,17 +92,30 @@ typedef struct { /* Prototypes. These are used only by the library. Application should not call these directly. */ +SilcClientEntry +silc_client_add_client(SilcClient client, SilcClientConnection conn, + char *nickname, char *username, + char *userinfo, SilcClientID *id, uint32 mode); +void silc_client_update_client(SilcClient client, + SilcClientConnection conn, + SilcClientEntry client_entry, + const char *nickname, + const char *username, + const char *userinfo, + uint32 mode); void silc_client_del_client_entry(SilcClient client, SilcClientEntry client_entry); SilcClientEntry silc_idlist_get_client(SilcClient client, SilcClientConnection conn, - char *nickname, - char *server, - uint32 num, - int query); + const char *nickname, + const char *format, + bool query); SilcChannelEntry silc_idlist_get_channel_by_id(SilcClient client, SilcClientConnection conn, SilcChannelID *channel_id, int query); +void silc_client_nickname_format(SilcClient client, + SilcClientConnection conn, + SilcClientEntry client_entry); #endif diff --git a/lib/silcclient/silcapi.h b/lib/silcclient/silcapi.h index 157d658a..22266d68 100644 --- a/lib/silcclient/silcapi.h +++ b/lib/silcclient/silcapi.h @@ -2,7 +2,7 @@ silcapi.h - Author: Pekka Riikonen + Author: Pekka Riikonen Copyright (C) 2000 - 2001 Pekka Riikonen @@ -351,6 +351,25 @@ typedef struct { } SilcClientOperations; /***/ +/****f* silcclient/SilcClientAPI/SilcNicknameFormatParse + * + * SYNOPSIS + * + * typedef void (*SilcNicknameFormatParse)(const char *nickname, + * char **ret_nickname); + * + * DESCRIPTION + * + * A callback function provided by the application for the library in + * SilcClientParams structure. This function parses the formatted + * nickname string `nickname' and returns the true nickname to the + * `ret_nickname' pointer. The library can call this function at + * any time. + * + ***/ +typedef void (*SilcNicknameFormatParse)(const char *nickname, + char **ret_nickname); + /****s* silcclient/SilcClientAPI/SilcClientParams * * NAME @@ -381,6 +400,56 @@ typedef struct { in this time interval we'll assume the reply will not come at all. If set to zero, the default value (2 seconds) will be used. */ unsigned int connauth_request_secs; + + /* Nickname format string. This can be used to order the client library + to save the nicknames in the library in a certain format. Since + nicknames are not unique in SILC it is possible to have multiple same + nicknames. Using this format string it is possible to order the library + to separate the multiple same nicknames from each other. The format + types are defined below and they can appear in any order in the format + string. If this is NULL then default format is used which is the + default nickname without anything else. The string MUST be NULL + terminated. + + Following format types are available: + + %n nickname - the real nickname returned by the server (mandatory) + %h hostname - the stripped hostname of the client + %H full hostname - the full hostname of the client + %s server name - the server name the client is connected + %S full server - the full server name the client is connected + %a number - ascending number in case there are several + same nicknames (fe. nick@host and nick@host2) + + Example format strings: "%n@%h%a" (fe. nick@host, nick@host2) + "%a!%n@%s" (fe. nick@server, 2!nick@server) + "%n@%H" (fe. nick@host.domain.com) + + By default this format is employed to the nicknames by the libary + only when there appears multiple same nicknames. If the library has + only one nickname cached the nickname is saved as is and without the + defined format. If you want always to save the nickname in the defined + format set the boolean field `nickname_force_format' to value TRUE. + */ + char nickname_format[32]; + + /* If this is set to TRUE then the `nickname_format' is employed to all + saved nicknames even if there are no multiple same nicknames in the + cache. By default this is FALSE, which means that the `nickname_format' + is employed only if the library will receive a nickname that is + already saved in the cache. It is recommended to leave this to FALSE + value. */ + bool nickname_force_format; + + /* A callback function provided by the application for the library to + parse the nickname from the formatted nickname string. Even though + the libary formats the nicknames the application knows generally the + format better so this function should be provided for the library + if the application sets the `nickname_format' field. The library + will call this to get the true nickname from the provided formatted + nickname string whenever it needs the true nickname. */ + SilcNicknameFormatParse nickname_parse; + } SilcClientParams; /***/ @@ -583,12 +652,13 @@ void silc_client_del_socket(SilcClient client, SilcSocketConnection sock); * directly if application is performing its own connecting and does not * use the connecting provided by this library. This function is normally * used only if the application performed the connecting outside the - * library. The library however may use this internally. + * library. The library however may use this internally. Returns FALSE + * if the key exchange could not be started. * ***/ -int silc_client_start_key_exchange(SilcClient client, - SilcClientConnection conn, - int fd); +bool silc_client_start_key_exchange(SilcClient client, + SilcClientConnection conn, + int fd); /****f* silcclient/SilcClientAPI/silc_client_close_connection * @@ -718,8 +788,8 @@ typedef void (*SilcGetClientCallback)(SilcClient client, * * void silc_client_get_clients(SilcClient client, * SilcClientConnection conn, - * char *nickname, - * char *server, + * const char *nickname, + * const char *server, * SilcGetClientCallback completion, * void *context); * @@ -740,8 +810,8 @@ typedef void (*SilcGetClientCallback)(SilcClient client, ***/ void silc_client_get_clients(SilcClient client, SilcClientConnection conn, - char *nickname, - char *server, + const char *nickname, + const char *server, SilcGetClientCallback completion, void *context); @@ -751,21 +821,26 @@ void silc_client_get_clients(SilcClient client, * * SilcClientEntry *silc_client_get_clients_local(SilcClient client, * SilcClientConnection conn, - * char *nickname, - * char *server, + * const char *nickname, + * const char *format, * uint32 *clients_count); * * DESCRIPTION * * Same as silc_client_get_clients function but does not resolve anything - * from the server. This checks local cache and returns all clients from - * the local cache. + * from the server. This checks local cache and returns all matching + * clients from the local cache. If none was found this returns NULL. + * The `nickname' is the real nickname of the client, and the `format' + * is the formatted nickname to find exact match from multiple found + * entries. The format must be same as given in the SilcClientParams + * structure to the client library. If the `format' is NULL all found + * clients by `nickname' are returned. * ***/ SilcClientEntry *silc_client_get_clients_local(SilcClient client, SilcClientConnection conn, - char *nickname, - char *server, + const char *nickname, + const char *format, uint32 *clients_count); /****f* silcclient/SilcClientAPI/silc_client_get_clients_by_list diff --git a/lib/silccrypt/silcrng.c b/lib/silccrypt/silcrng.c index a9cd3595..e9fe1c81 100644 --- a/lib/silccrypt/silcrng.c +++ b/lib/silccrypt/silcrng.c @@ -203,8 +203,8 @@ static void silc_rng_get_soft_noise(SilcRng rng) #ifdef HAVE_GETPID silc_rng_xor(rng, getpid(), 1); #ifdef HAVE_GETPGID - silc_rng_xor(rng, getpgid(getpid() << 8), 2); - silc_rng_xor(rng, getpgid(getpid() << 8), 3); + silc_rng_xor(rng, getpgid(getpid()) << 8, 2); + silc_rng_xor(rng, getpgid(getpid()) << 8, 3); #endif silc_rng_xor(rng, getgid(), 4); #endif @@ -212,7 +212,7 @@ static void silc_rng_get_soft_noise(SilcRng rng) silc_rng_xor(rng, getpgrp(), 5); #endif #ifdef HAVE_GETSID - silc_rng_xor(rng, getsid(getpid() << 16), 6); + silc_rng_xor(rng, getsid(getpid()) << 16, 6); #endif silc_rng_xor(rng, times(&ptime), 7); silc_rng_xor(rng, ptime.tms_utime, 8); @@ -229,13 +229,13 @@ static void silc_rng_get_soft_noise(SilcRng rng) silc_rng_xor(rng, clock() << 4, pos++); #ifndef SILC_WIN32 #ifdef HAVE_GETPGID - silc_rng_xor(rng, getpgid(getpid() << 8), pos++); + silc_rng_xor(rng, getpgid(getpid()) << 8, pos++); #endif #ifdef HAVE_GETPGRP silc_rng_xor(rng, getpgrp(), pos++); #endif #ifdef HAVE_SETSID - silc_rng_xor(rng, getsid(getpid() << 16), pos++); + silc_rng_xor(rng, getsid(getpid()) << 16, pos++); #endif silc_rng_xor(rng, times(&ptime), pos++); silc_rng_xor(rng, ptime.tms_utime, pos++); diff --git a/lib/silcutil/silcschedule.c b/lib/silcutil/silcschedule.c index d3833af1..bd046a8f 100644 --- a/lib/silcutil/silcschedule.c +++ b/lib/silcutil/silcschedule.c @@ -200,6 +200,9 @@ SilcSchedule silc_schedule_init(int max_tasks) silc_task_queue_alloc(&schedule->timeout_queue); silc_task_queue_alloc(&schedule->generic_queue); + if (!max_tasks) + max_tasks = 200; + /* Initialize the scheduler */ schedule->fd_list = silc_calloc(max_tasks, sizeof(*schedule->fd_list)); schedule->max_fd = max_tasks; diff --git a/lib/silcutil/silcutil.c b/lib/silcutil/silcutil.c index fa482dcc..d571b8a6 100644 --- a/lib/silcutil/silcutil.c +++ b/lib/silcutil/silcutil.c @@ -355,51 +355,30 @@ unsigned char *silc_decode_pem(unsigned char *pem, uint32 pem_len, return data; } -/* Parse nickname string. The format may be !@ to - support multiple same nicknames. The is the final unifier if same - nickname is on same server. Note, this is only local format and server - does not know anything about these. */ +/* Parse userfqdn string which is in user@fqdn format */ -int silc_parse_nickname(char *string, char **nickname, char **server, - uint32 *num) +bool silc_parse_userfqdn(const char *string, char **left, char **right) { uint32 tlen; if (!string) return FALSE; - if (strchr(string, '!')) { - char *tmp; - tlen = strcspn(string, "!"); - tmp = silc_calloc(tlen + 1, sizeof(*tmp)); - memcpy(tmp, string, tlen); - - if (num) - *num = atoi(tmp); - - silc_free(tmp); - - if (tlen >= strlen(string)) - return FALSE; - - string += tlen + 1; - } - if (strchr(string, '@')) { tlen = strcspn(string, "@"); - if (nickname) { - *nickname = silc_calloc(tlen + 1, sizeof(char)); - memcpy(*nickname, string, tlen); + if (left) { + *left = silc_calloc(tlen + 1, sizeof(char)); + memcpy(*left, string, tlen); } - if (server) { - *server = silc_calloc((strlen(string) - tlen) + 1, sizeof(char)); - memcpy(*server, string + tlen + 1, strlen(string) - tlen - 1); + if (right) { + *right = silc_calloc((strlen(string) - tlen) + 1, sizeof(char)); + memcpy(*right, string + tlen + 1, strlen(string) - tlen - 1); } } else { - if (nickname) - *nickname = strdup(string); + if (left) + *left = strdup(string); } return TRUE; diff --git a/lib/silcutil/silcutil.h b/lib/silcutil/silcutil.h index 5499f8a8..92742709 100644 --- a/lib/silcutil/silcutil.h +++ b/lib/silcutil/silcutil.h @@ -34,8 +34,7 @@ char *silc_encode_pem(unsigned char *data, uint32 len); char *silc_encode_pem_file(unsigned char *data, uint32 data_len); unsigned char *silc_decode_pem(unsigned char *pem, uint32 pem_len, uint32 *ret_len); -int silc_parse_nickname(char *string, char **nickname, char **server, - uint32 *num); +bool silc_parse_userfqdn(const char *string, char **left, char **right); void silc_parse_command_line(unsigned char *buffer, unsigned char ***parsed, uint32 **parsed_lens, diff --git a/win32/libsilcclient/libsilcclient.def b/win32/libsilcclient/libsilcclient.def index 641f56fd..26dcc046 100644 --- a/win32/libsilcclient/libsilcclient.def +++ b/win32/libsilcclient/libsilcclient.def @@ -153,3 +153,6 @@ EXPORTS silc_idlist_get_channel_by_id @ 136 ; silc_idlist_get_client @ 137 ; silc_client_abort_key_agreement @ 138 ; + silc_client_set_away_message @ 139 ; + silc_client_request_authentication_method @ 140 ; +