updates.
authorPekka Riikonen <priikone@silcnet.org>
Thu, 6 Sep 2001 18:35:07 +0000 (18:35 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Thu, 6 Sep 2001 18:35:07 +0000 (18:35 +0000)
22 files changed:
CHANGES
TODO
apps/irssi/src/fe-common/silc/module-formats.c
apps/irssi/src/fe-common/silc/module-formats.h
apps/irssi/src/silc/core/client_ops.c
apps/irssi/src/silc/core/silc-channels.c
apps/irssi/src/silc/core/silc-core.c
apps/irssi/src/silc/core/silc-servers.c
doc/draft-riikonen-silc-commands-02.nroff
lib/silcclient/client.c
lib/silcclient/client.h
lib/silcclient/client_notify.c
lib/silcclient/command.c
lib/silcclient/command_reply.c
lib/silcclient/idlist.c
lib/silcclient/idlist.h
lib/silcclient/silcapi.h
lib/silccrypt/silcrng.c
lib/silcutil/silcschedule.c
lib/silcutil/silcutil.c
lib/silcutil/silcutil.h
win32/libsilcclient/libsilcclient.def

diff --git a/CHANGES b/CHANGES
index abccd029b66cf4dd6c508db36f13fe2add4ec738..42413044f220cee2ac47aaa6f384305aa1c2db0f 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,61 @@
+Thu Sep  6 12:47:37 EEST 2001  Pekka Riikonen <priikone@silcnet.org>
+
+       * 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 <priikone@silcnet.org>
 
        * Added public key authentication support to OPER and SILCOPER
diff --git a/TODO b/TODO
index 87e796ca62880b7d543175c7cfdd8c24c9d9d551..cc5fc769a559e397fee0dbfc0528d3ca0eb3f862 100644 (file)
--- 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.
index d071c95cab0953dd5993bdb9dd5c849a83de908e..d542ccc63237edaa0802709cb6edb14f30f8ba3e 100644 (file)
@@ -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 } },
index 61bd8462369ea8beb6601728747eeb814ebfeb21..60cd99a781f2504a9dfcbb04ce10f27b9c10063d 100644 (file)
@@ -48,6 +48,7 @@ enum {
   SILCTXT_FILL_2,
 
   SILCTXT_WHOIS_USERINFO,
+  SILCTXT_WHOIS_REALNAME,
   SILCTXT_WHOIS_CHANNELS,
   SILCTXT_WHOIS_MODES,
   SILCTXT_WHOIS_IDLE,
index 9247a3c4f484b5305855ee17e89e36c8b34cc047..79be2e8c7b4eef61cc9c1e9d7bbbcd1e63e4c332 100644 (file)
@@ -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);
index 2ee76c58e99ad308f936805e31052e5f0708e74f..459dedd6a5d1d332b8c95d61f37703b026652749 100644 (file)
@@ -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. */
index 9ea0cfdc844812501c59131118e5f5589195dba7..9a61a48b736fe8af8702078611bd078ec6a14133 100644 (file)
@@ -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(&params, 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, &params, NULL, silc_version_string);
 
   /* Load local config file */
   silc_config = silc_client_config_alloc(SILC_CLIENT_HOME_CONFIG_FILE);
index a810b8eed7bc4475c31e2e76fd73c169ef271045..4afc351790fa9bd65f574b910c5af4782d70bade 100644 (file)
@@ -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 <channel> [+|-[<nickname>[@<server>[!<username>[@hostname>]]]]] */
 /* SYNTAX: CMODE <channel> +|-<modes> [{ <arguments>}] */
-/* SYNTAX: CUMODE <channel> +|-<modes> <nickname>[@<server>] [-pubkey|<passwd>] */
+/* SYNTAX: CUMODE <channel> +|-<modes> <nickname>[@<hostname>] [-pubkey|<passwd>] */
 /* SYNTAX: GETKEY <nickname or server name> */
-/* SYNTAX: INVITE <channel> [<nickname>[@server>] */
+/* SYNTAX: INVITE <channel> [<nickname>[@hostname>] */
 /* SYNTAX: INVITE <channel> [+|-[<nickname>[@<server>[!<username>[@hostname>]]]]] */
 /* SYNTAX: KEY MSG <nickname> set|unset|list|agreement|negotiate [<arguments>] */
 /* SYNTAX: KEY CHANNEL <channel> set|unset|list|agreement|negotiate [<arguments>] */
-/* SYNTAX: KICK <channel> <nickname>[@<server>] [<comment>] */
-/* SYNTAX: KILL <channel> <nickname>[@<server>] [<comment>] */
+/* SYNTAX: KICK <channel> <nickname>[@<hostname>] [<comment>] */
+/* SYNTAX: KILL <channel> <nickname>[@<hostname>] [<comment>] */
 /* SYNTAX: OPER <username> [-pubkey] */
 /* SYNTAX: SILCOPER <username> [-pubkey] */
 /* SYNTAX: TOPIC <channel> [<topic>] */
 /* SYNTAX: UMODE +|-<modes> */
-/* SYNTAX: WHOIS <nickname>[@<server>] [<count>] */
-/* SYNTAX: WHOWAS <nickname>[@<server>] [<count>] */
+/* SYNTAX: WHOIS <nickname>[@<hostname>] [<count>] */
+/* SYNTAX: WHOWAS <nickname>[@<hostname>] [<count>] */
 /* SYNTAX: CLOSE <server> [<port>] */
 /* SYNTAX: SHUTDOWN */
 /* SYNTAX: MOTD [<server>] */
index 0094ece81088c9f949f9269872889f477593f226..ac17d89c3828c0f2673cb071d7c59ea8d56b11bd 100644 (file)
@@ -389,7 +389,7 @@ List of all defined commands in SILC follows.
         Reply messages to the command:
 
         Max Arguments:  4
-            Arguments:  (1) <Status Payload>   (2) <Client ID>
+            Arguments:  (1) <Status Payload>   (2) <ID Payload>
                         (3) [<entity's name>]  (4) [<info>]
 
         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 <entity's name> must include the client's
-        nickname in the following format: nickname>[@server].  The
+        nickname in the following format: nickname[@server].  The
         <info> must include the client's username and host in the following
         format: username@host.
 
index aebaebe65134b8749b1739326a5df644981c9e51..681d9e0eaf300ff1f9d88047a55ef1ce58214905 100644 (file)
@@ -2,7 +2,7 @@
 
   client.c
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   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
index c0e33228f361bfea6594835f8ffac6e18587efe3..7259267f1416d1e2c14161e41d36c43f82b36fb3 100644 (file)
@@ -2,7 +2,7 @@
 
   client.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1997 - 2001 Pekka Riikonen
 
index dd787cac42c12b1f94a1dd1208762d20239b435a..a07991736323e7930e1f33c0657609266cffc75c 100644 (file)
@@ -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;
index 5379000a24473ba256a5e1d37f0f2fb0953fcb66..b449b1150ed9da09d1d1eccd113d1f948bf63754 100644 (file)
@@ -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);
 }
index 61bade4bbce963df43c4e7fef712ae50d76329da..79acee69291f3865e8a859debadc8201eab32c59 100644 (file)
@@ -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;
index 66270cdc3010f5efed85d399551a16cd1b02bbeb..ffbcf29bda3b2b989750853ca57a2b0afc7d0559 100644 (file)
@@ -2,9 +2,9 @@
 
   idlist.c
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-  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);
+}
index 815d039240fb9ade0d72570cc54034ec51acb069..c120ff296c6659f349d442e84fc2ca3352df6466 100644 (file)
@@ -2,9 +2,9 @@
 
   idlist.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-  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
index 157d658ad66cf6e5eb41fed9a4dd64e457bca4a8..22266d68248e6eb5d396c337641ef6c8d306880c 100644 (file)
@@ -2,7 +2,7 @@
 
   silcapi.h
   
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
   
   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
index a9cd3595f8877564131d633d6b5dcaf3f5b8eb9a..e9fe1c81ffe3d596b1572aeafa355104f388a2dc 100644 (file)
@@ -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++);
index d3833af1aaf23f006586418dc436937f4390845b..bd046a8f4e84044c0b2243f9c767c0a44dcf27bb 100644 (file)
@@ -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;
index fa482dcce9c89a4f422762b35ca4a9bb112cd68b..d571b8a62a4dd328b3a1b901a8ac00f59f8e2934 100644 (file)
@@ -355,51 +355,30 @@ unsigned char *silc_decode_pem(unsigned char *pem, uint32 pem_len,
   return data;
 }
 
-/* Parse nickname string. The format may be <num>!<nickname>@<server> to
-   support multiple same nicknames. The <num> 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;
index 5499f8a826445feae3116fbe34574c07489a6d87..927427090b1602a45534e6af76a2f3798f18e7ae 100644 (file)
@@ -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,
index 641f56fd90150258a83adc1a11ed5bd8c6cce4f5..26dcc0468c6d3da791b566791b866d8c86810fc6 100644 (file)
@@ -153,3 +153,6 @@ EXPORTS
        silc_idlist_get_channel_by_id @ 136 ; \r
        silc_idlist_get_client @ 137 ; \r
        silc_client_abort_key_agreement @ 138 ; \r
+       silc_client_set_away_message @ 139 ; \r
+       silc_client_request_authentication_method @ 140 ; \r
+\r