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
 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 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.
 
    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
  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
 ================================
 
 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
 
 
 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 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.
  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, 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 } },
        { "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_FILL_2,
 
   SILCTXT_WHOIS_USERINFO,
+  SILCTXT_WHOIS_REALNAME,
   SILCTXT_WHOIS_CHANNELS,
   SILCTXT_WHOIS_MODES,
   SILCTXT_WHOIS_IDLE,
   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:
     {
   switch(command) {
   case SILC_COMMAND_WHOIS:
     {
-      char buf[1024], *nickname, *username, *realname;
+      char buf[1024], *nickname, *username, *realname, *nick;
       uint32 idle, mode;
       SilcBuffer channels;
       uint32 idle, mode;
       SilcBuffer channels;
+      SilcClientEntry client_entry;
       
       if (status == SILC_STATUS_ERR_NO_SUCH_NICK ||
          status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
       
       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;
       
       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 *);
       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);
       
       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,
       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);
 
       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;
   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;
   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. */
       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;
        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, 
       
       /* 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;
       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 (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;
        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) {
 
     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);
     }
   }
       cmd_return_error(CMDERR_NOT_JOINED);
     }
   }
@@ -1170,10 +1163,7 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
   }
 
  out:
   }
 
  out:
-  if (nickname)
-    silc_free(nickname);
-  if (serv)
-    silc_free(serv);
+  silc_free(nickname);
 }
 
 /* Lists locally saved client and server public keys. */
 }
 
 /* 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);
 }
 
   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;
 /* 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 */
 
   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();
 
   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 */
   /* 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);
 
   /* 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;
 typedef struct {
   char *nick;
   char *msg;
+  SILC_SERVER_REC *server;
 } PRIVMSG_REC;
 
 /* Callback function that sends the private message if the client was
 } 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;
                                  void *context)
 {
   PRIVMSG_REC *rec = context;
+  SILC_SERVER_REC *server = rec->server;
   SilcClientEntry target;
   SilcClientEntry target;
-  
-  if (clients_count == 0) {
+  char *nickname = NULL;
+
+  if (!clients_count) {
     printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown nick: %s", rec->nick);
   } else {
     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);
   }
   
     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);
   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;
 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 */
     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 = 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,
 
     /* 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 */
     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)
 }
 
 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: 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: 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: 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: 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>] */
 /* 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
         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
                         (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
         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.
 
         <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
 
 
   client.c
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1997 - 2001 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 (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;
 
   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;
 }
 
   return new_client;
 }
 
@@ -142,6 +148,12 @@ void silc_client_run(SilcClient client)
   silc_schedule(client->schedule);
 }
 
   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
 /* 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 = 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;
   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. */
 
    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;
 {
   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,
                      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;
     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;
     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 */
   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
                   (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
 
 
   client.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1997 - 2001 Pekka Riikonen
 
 
   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,
 
     /* 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;
       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;
   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) {
   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] != '-') {
   /* 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, 
       /* Find client entry */
       client_entry = silc_idlist_get_client(client, conn, nickname, 
-                                           server, num, TRUE);
+                                           cmd->argv[2], TRUE);
       if (!client_entry) {
       if (!client_entry) {
-       if (nickname)
-         silc_free(nickname);
-       if (server)
-         silc_free(server);
+       silc_free(nickname);
        
        if (cmd->pending) {
          COMMAND_ERROR;
        
        if (cmd->pending) {
          COMMAND_ERROR;
@@ -660,10 +655,7 @@ SILC_CLIENT_CMD_FUNC(invite)
   COMMAND;
 
  out:
   COMMAND;
 
  out:
-  if (nickname)
-    silc_free(nickname);
-  if (server)
-    silc_free(server);
+  silc_free(nickname);
   silc_client_command_free(cmd);
 }
 
   silc_client_command_free(cmd);
 }
 
@@ -731,11 +723,11 @@ SILC_CLIENT_CMD_FUNC(quit)
 SILC_CLIENT_CMD_FUNC(kill)
 {
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
 SILC_CLIENT_CMD_FUNC(kill)
 {
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+  SilcClient client = cmd->client;
   SilcClientConnection conn = cmd->conn;
   SilcBuffer buffer, idp;
   SilcClientEntry target;
   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);
 
   if (!cmd->conn) {
     SILC_NOT_CONNECTED(cmd->client, cmd->conn);
@@ -751,20 +743,16 @@ SILC_CLIENT_CMD_FUNC(kill)
   }
 
   /* Parse the typed nickname. */
   }
 
   /* 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, 
 
   /* 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 (!target) {
     silc_free(nickname);
-    if (server)
-      silc_free(server);
 
     if (cmd->pending) {
       COMMAND_ERROR;
 
     if (cmd->pending) {
       COMMAND_ERROR;
@@ -801,10 +789,7 @@ SILC_CLIENT_CMD_FUNC(kill)
   COMMAND;
 
  out:
   COMMAND;
 
  out:
-  if (nickname)
-    silc_free(nickname);
-  if (server)
-    silc_free(server);
+  silc_free(nickname);
   silc_client_command_free(cmd);
 }
 
   silc_client_command_free(cmd);
 }
 
@@ -1330,6 +1315,7 @@ SILC_CLIENT_CMD_FUNC(cmode)
 SILC_CLIENT_CMD_FUNC(cumode)
 {
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
 SILC_CLIENT_CMD_FUNC(cumode)
 {
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+  SilcClient client = cmd->client;
   SilcClientConnection conn = cmd->conn;
   SilcChannelEntry channel;
   SilcChannelUser chu;
   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;
   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) {
   int i;
 
   if (!cmd->conn) {
@@ -1376,16 +1361,17 @@ SILC_CLIENT_CMD_FUNC(cumode)
   }
 
   /* Parse the typed nickname. */
   }
 
   /* 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 */
 
   /* 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) {
   if (!client_entry) {
+    silc_free(nickname);
+
     if (cmd->pending) {
       COMMAND_ERROR;
       goto out;
     if (cmd->pending) {
       COMMAND_ERROR;
       goto out;
@@ -1486,10 +1472,7 @@ SILC_CLIENT_CMD_FUNC(cumode)
   COMMAND;
 
  out:
   COMMAND;
 
  out:
-  if (nickname)
-    silc_free(nickname);
-  if (server)
-    silc_free(server);
+  silc_free(nickname);
   silc_client_command_free(cmd);
 }
 
   silc_client_command_free(cmd);
 }
 
@@ -1498,14 +1481,14 @@ SILC_CLIENT_CMD_FUNC(cumode)
 SILC_CLIENT_CMD_FUNC(kick)
 {
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
 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;
   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);
 
   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. */
   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, 
 
   /* 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",
   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:
   COMMAND;
 
  out:
-  if (nickname)
-    silc_free(nickname);
-  if (server)
-    silc_free(server);
+  silc_free(nickname);
   silc_client_command_free(cmd);
 }
 
   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;
   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) {
   SilcBuffer idp, buffer;
 
   if (!cmd->conn) {
@@ -2077,18 +2054,17 @@ SILC_CLIENT_CMD_FUNC(getkey)
   }
 
   /* Parse the typed nickname. */
   }
 
   /* 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 */
 
   /* 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 */
                                        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
 
     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 */
         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,
       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, 
       /* 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,
       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_client_command_dup(cmd));
 
       cmd->pending = 1;
+      silc_free(nickname);
       return;
     }
 
       return;
     }
 
@@ -2133,5 +2110,6 @@ SILC_CLIENT_CMD_FUNC(getkey)
   COMMAND;
 
  out:
   COMMAND;
 
  out:
+  silc_free(nickname);
   silc_client_command_free(cmd);
 }
   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"));
                                       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;
   } 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);
   }
 
     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"));
                                         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;
     } 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 */
     }
 
     /* 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. */
                                         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;
     } else {
       /* Yes, we have it already */
       client_entry = (SilcClientEntry)id_cache->context;
index 66270cdc3010f5efed85d399551a16cd1b02bbeb..ffbcf29bda3b2b989750853ca57a2b0afc7d0559 100644 (file)
@@ -2,9 +2,9 @@
 
   idlist.c
 
 
   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
 
   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,
 
 void silc_client_get_clients(SilcClient client,
                             SilcClientConnection conn,
-                            char *nickname,
-                            char *server,
+                            const char *nickname,
+                            const char *server,
                             SilcGetClientCallback completion,
                             void *context)
 {
                             SilcGetClientCallback completion,
                             void *context)
 {
@@ -111,13 +111,19 @@ void silc_client_get_clients(SilcClient client,
                              (void *)i);
 }
 
                              (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,
 
 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;
                                               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 */
   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)) {
     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);
 
   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) {
     /* 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;
     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 {
        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,
 
 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 */
 {
   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) {
   identify:
 
     if (query) {
@@ -397,7 +401,7 @@ SilcClientEntry silc_idlist_get_client(SilcClient client,
     return NULL;
   }
 
     return NULL;
   }
 
-  if (!server && !num) {
+  if (!format) {
     /* Take first found cache entry */
     if (!silc_idcache_list_first(list, &id_cache))
       goto identify;
     /* 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);
   } 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 */
     }
 
     /* If match weren't found, request it */
@@ -527,6 +529,78 @@ void silc_client_get_client_by_id_resolve(SilcClient client,
                              (void *)i);
 }
 
                              (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, 
 /* 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;
 }
   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
 
 
   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
 
   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 */
    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;
   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. */
 
 /* 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,
 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);
 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
 
 #endif
index 157d658ad66cf6e5eb41fed9a4dd64e457bca4a8..22266d68248e6eb5d396c337641ef6c8d306880c 100644 (file)
@@ -2,7 +2,7 @@
 
   silcapi.h
   
 
   silcapi.h
   
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
   
   Copyright (C) 2000 - 2001 Pekka Riikonen
   
   
   Copyright (C) 2000 - 2001 Pekka Riikonen
   
@@ -351,6 +351,25 @@ typedef struct {
 } SilcClientOperations;
 /***/
 
 } 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
 /****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;
      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;
 /***/
 
 } 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
  *    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
  *
 
 /****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,
  *
  *    void silc_client_get_clients(SilcClient client,
  *                                 SilcClientConnection conn,
- *                                 char *nickname,
- *                                 char *server,
+ *                                 const char *nickname,
+ *                                 const char *server,
  *                                 SilcGetClientCallback completion,
  *                                 void *context);
  *
  *                                 SilcGetClientCallback completion,
  *                                 void *context);
  *
@@ -740,8 +810,8 @@ typedef void (*SilcGetClientCallback)(SilcClient client,
  ***/
 void silc_client_get_clients(SilcClient client,
                             SilcClientConnection conn,
  ***/
 void silc_client_get_clients(SilcClient client,
                             SilcClientConnection conn,
-                            char *nickname,
-                            char *server,
+                            const char *nickname,
+                            const char *server,
                             SilcGetClientCallback completion,
                             void *context);
 
                             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,
  *
  *    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
  *                                                   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,
  *
  ***/
 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
                                               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
 #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
 #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, 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);
 #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, 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
 #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++);
 #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);
 
   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;
   /* 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;
 }
 
   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;
 
 {
   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 (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 {
     }
   } else {
-    if (nickname)
-      *nickname = strdup(string);
+    if (left)
+      *left = strdup(string);
   }
 
   return TRUE;
   }
 
   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);
 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,
 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_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