Added support for channel@server channel name strings (SILC
authorPekka Riikonen <priikone@silcnet.org>
Sun, 10 Jun 2007 18:32:58 +0000 (18:32 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 10 Jun 2007 18:32:58 +0000 (18:32 +0000)
protocol 1.3 change).  Added full_nicknames and full_channel_name
SilcClientParams.

CHANGES
lib/silcclient/client_entry.c
lib/silcclient/command.c
lib/silcclient/command_reply.c
lib/silcclient/silcclient.h
lib/silcclient/silcclient_entry.h

diff --git a/CHANGES b/CHANGES
index ac255b55d9190db96faddff5993ee286b0537737..87a83573b26f3cc7322ea03f33a9222abc8b8dd0 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,15 @@
+Sun Jun 10 17:32:15 EEST 2007  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added support for channel@server channel name strings to
+         client library (SILC protocol version 1.3 change).  Affected
+         files are lib/silcclient/silcclient_entry.h, client_entry.c.
+
+       * Added full_nicknames and full_channel_names settings to
+         SilcClientParams that can be used to specify whether client
+         library returns full nickname and channel name strings.
+         Full strings are nick@server and channel@server.  Affected
+         file is lib/silcclient/client_entry.c and command.c.
+
 Sat Jun  9 19:43:25 EEST 2007  Pekka Riikonen <priikone@silcnet.org>
 
        * Fixed unix connecting failure to return error code correctly.
index 6a92210a32c5d9a1c63332d1822a8bfd6338797f..0c812de00adbd6bec3672098d5b4565e334c52f3 100644 (file)
@@ -781,7 +781,7 @@ SilcClientEntry silc_client_add_client(SilcClient client,
                                       SilcUInt32 mode)
 {
   SilcClientEntry client_entry;
-  char *nick = NULL;
+  char *nick = NULL, parsed[128 + 1];
 
   SILC_LOG_DEBUG(("Adding new client entry"));
 
@@ -795,14 +795,21 @@ SilcClientEntry silc_client_add_client(SilcClient client,
   client_entry->id = *id;
   client_entry->mode = mode;
   client_entry->realname = userinfo ? strdup(userinfo) : NULL;
-  silc_parse_userfqdn(nickname, client_entry->nickname,
-                     sizeof(client_entry->nickname),
-                     client_entry->server,
-                     sizeof(client_entry->server));
+
+  silc_parse_userfqdn(nickname, parsed, sizeof(parsed),
+                     client_entry->server, sizeof(client_entry->server));
+  if (nickname && client->internal->params->full_nicknames)
+    silc_snprintf(client_entry->nickname, sizeof(client_entry->nickname),
+                 nickname);
+  else if (nickname)
+    silc_snprintf(client_entry->nickname, sizeof(client_entry->nickname),
+                 parsed);
+
   silc_parse_userfqdn(username, client_entry->username,
                      sizeof(client_entry->username),
                      client_entry->hostname,
                      sizeof(client_entry->hostname));
+
   client_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr, NULL, NULL,
                                                 NULL, NULL, NULL, TRUE);
   if (!client_entry->channels) {
@@ -813,8 +820,7 @@ SilcClientEntry silc_client_add_client(SilcClient client,
 
   /* Normalize nickname */
   if (client_entry->nickname[0]) {
-    nick = silc_identifier_check(client_entry->nickname,
-                                strlen(client_entry->nickname),
+    nick = silc_identifier_check(parsed, strlen(parsed),
                                 SILC_STRING_UTF8, 128, NULL);
     if (!nick) {
       silc_free(client_entry->realname);
@@ -864,7 +870,7 @@ void silc_client_update_client(SilcClient client,
                               const char *userinfo,
                               SilcUInt32 mode)
 {
-  char *nick = NULL;
+  char *nick = NULL, parsed[128 + 1];
 
   SILC_LOG_DEBUG(("Update client entry"));
 
@@ -872,20 +878,25 @@ void silc_client_update_client(SilcClient client,
 
   if (!client_entry->realname && userinfo)
     client_entry->realname = strdup(userinfo);
+
   if ((!client_entry->username[0] || !client_entry->hostname[0]) && username)
     silc_parse_userfqdn(username, client_entry->username,
                        sizeof(client_entry->username),
                        client_entry->hostname,
                        sizeof(client_entry->username));
+
   if (!client_entry->nickname[0] && nickname) {
-    silc_parse_userfqdn(nickname, client_entry->nickname,
-                       sizeof(client_entry->nickname),
-                       client_entry->server,
-                       sizeof(client_entry->server));
+    silc_parse_userfqdn(nickname, parsed, sizeof(parsed),
+                       client_entry->server, sizeof(client_entry->server));
+    if (client->internal->params->full_nicknames)
+      silc_snprintf(client_entry->nickname, sizeof(client_entry->nickname),
+                   nickname);
+    else
+      silc_snprintf(client_entry->nickname, sizeof(client_entry->nickname),
+                   parsed);
 
     /* Normalize nickname */
-    nick = silc_identifier_check(client_entry->nickname,
-                                strlen(client_entry->nickname),
+    nick = silc_identifier_check(parsed, strlen(parsed),
                                 SILC_STRING_UTF8, 128, NULL);
     if (!nick) {
       silc_rwlock_unlock(client_entry->internal.lock);
@@ -1357,32 +1368,66 @@ SilcChannelEntry silc_client_get_channel(SilcClient client,
                                         SilcClientConnection conn,
                                         char *channel)
 {
+  SilcList list;
   SilcIDCacheEntry id_cache;
-  SilcChannelEntry entry;
+  SilcChannelEntry entry = NULL;
+  char chname[256 + 1], server[256 + 1];
 
   if (!client || !conn || !channel)
     return NULL;
 
   SILC_LOG_DEBUG(("Find channel %s", channel));
 
+  /* Parse server name from channel name */
+  silc_parse_userfqdn(channel, chname, sizeof(chname), server, sizeof(server));
+
   /* Normalize name for search */
-  channel = silc_channel_name_check(channel, strlen(channel), SILC_STRING_UTF8,
+  channel = silc_channel_name_check(chname, strlen(chname), SILC_STRING_UTF8,
                                    256, NULL);
   if (!channel)
     return NULL;
 
   silc_mutex_lock(conn->internal->lock);
 
-  if (!silc_idcache_find_by_name_one(conn->internal->channel_cache, channel,
-                                    &id_cache)) {
+  if (!silc_idcache_find_by_name(conn->internal->channel_cache, channel,
+                                &list)) {
     silc_mutex_unlock(conn->internal->lock);
     silc_free(channel);
     return NULL;
   }
 
-  SILC_LOG_DEBUG(("Found"));
+  /* If server name was specified with channel name, find the correct
+     channel entry with the server name.  There can only be one channel
+     with same name on same server. */
+  silc_list_start(list);
+  if (server[0]) {
+    while ((id_cache = silc_list_get(list))) {
+      entry = id_cache->context;
+      if (!entry->server[0])
+       continue;
+      if (silc_utf8_strcasecmp(entry->server, server))
+       break;
+    }
+  } else {
+    /* Get first channel without server name specified or one with our
+       current server connection name */
+    while ((id_cache = silc_list_get(list))) {
+      entry = id_cache->context;
+      if (!entry->server[0])
+       break;
+      if (silc_utf8_strcasecmp(entry->server, conn->remote_host))
+       break;
+    }
+  }
 
-  entry = id_cache->context;
+  if (!id_cache) {
+    silc_mutex_unlock(conn->internal->lock);
+    silc_free(channel);
+    return NULL;
+  }
+
+  SILC_LOG_DEBUG(("Found channel %s%s%s", entry->channel_name,
+                 entry->server[0] ? "@" : "", entry->server));
 
   /* Reference */
   silc_client_ref_channel(client, conn, entry);
@@ -1571,9 +1616,9 @@ SilcChannelEntry silc_client_add_channel(SilcClient client,
                                         SilcChannelID *channel_id)
 {
   SilcChannelEntry channel;
-  char *channel_namec;
+  char *channel_namec, name[256 + 1];
 
-  SILC_LOG_DEBUG(("Start"));
+  SILC_LOG_DEBUG(("Adding channel %s", channel_name));
 
   channel = silc_calloc(1, sizeof(*channel));
   if (!channel)
@@ -1584,8 +1629,16 @@ SilcChannelEntry silc_client_add_channel(SilcClient client,
   channel->id = *channel_id;
   channel->mode = mode;
 
-  channel->channel_name = strdup(channel_name);
+  silc_parse_userfqdn(channel_name, name, sizeof(name),
+                     channel->server, sizeof(channel->server));
+  if (client->internal->params->full_channel_names)
+    channel->channel_name = strdup(channel_name);
+  else
+    channel->channel_name = strdup(name);
+
   if (!channel->channel_name) {
+    silc_rwlock_free(channel->internal.lock);
+    silc_atomic_uninit16(&channel->internal.refcnt);
     silc_free(channel);
     return NULL;
   }
@@ -1593,15 +1646,19 @@ SilcChannelEntry silc_client_add_channel(SilcClient client,
   channel->user_list = silc_hash_table_alloc(1, silc_hash_ptr, NULL, NULL,
                                             NULL, NULL, NULL, TRUE);
   if (!channel->user_list) {
+    silc_rwlock_free(channel->internal.lock);
+    silc_atomic_uninit16(&channel->internal.refcnt);
     silc_free(channel->channel_name);
     silc_free(channel);
     return NULL;
   }
 
   /* Normalize channel name */
-  channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
+  channel_namec = silc_channel_name_check(name, strlen(name),
                                          SILC_STRING_UTF8, 256, NULL);
   if (!channel_namec) {
+    silc_rwlock_free(channel->internal.lock);
+    silc_atomic_uninit16(&channel->internal.refcnt);
     silc_free(channel->channel_name);
     silc_hash_table_free(channel->user_list);
     silc_free(channel);
@@ -1613,6 +1670,8 @@ SilcChannelEntry silc_client_add_channel(SilcClient client,
   /* Add channel to cache, the normalized channel name is saved to cache */
   if (!silc_idcache_add(conn->internal->channel_cache, channel_namec,
                        &channel->id, channel)) {
+    silc_rwlock_free(channel->internal.lock);
+    silc_atomic_uninit16(&channel->internal.refcnt);
     silc_free(channel_namec);
     silc_free(channel->channel_name);
     silc_hash_table_free(channel->user_list);
index 0f66b97ad2ddeef002fd86c0ff7ccedbcbedb1df..85e33fe38217f0fe7b17c6c70a97270b1d3e2aca 100644 (file)
@@ -938,7 +938,7 @@ SILC_FSM_STATE(silc_client_command_topic)
   SilcClient client = conn->client;
   SilcChannelEntry channel;
   SilcBuffer idp;
-  char *name;
+  char *name, tmp[512];
 
   if (cmd->argc < 2 || cmd->argc > 3) {
     SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO,
@@ -953,7 +953,15 @@ SILC_FSM_STATE(silc_client_command_topic)
       COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL);
       goto out;
     }
-    name = conn->current_channel->channel_name;
+
+    if (client->internal->params->full_channel_names)
+      silc_snprintf(tmp, sizeof(tmp), conn->current_channel->channel_name);
+    else
+      silc_snprintf(tmp, sizeof(tmp), "%s%s%s",
+                   conn->current_channel->channel_name,
+                   conn->current_channel->server[0] ? "@" : "",
+                   conn->current_channel->server);
+    name = tmp;
   } else {
     name = cmd->argv[1];
   }
@@ -2119,7 +2127,7 @@ SILC_FSM_STATE(silc_client_command_kick)
   SilcBuffer idp, idp2;
   SilcClientEntry target;
   SilcDList clients = NULL;
-  char *name;
+  char *name, tmp[512];
 
   if (cmd->argc < 3) {
     SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO,
@@ -2133,7 +2141,15 @@ SILC_FSM_STATE(silc_client_command_kick)
       COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL);
       goto out;
     }
-    name = conn->current_channel->channel_name;
+
+    if (client->internal->params->full_channel_names)
+      silc_snprintf(tmp, sizeof(tmp), conn->current_channel->channel_name);
+    else
+      silc_snprintf(tmp, sizeof(tmp), "%s%s%s",
+                   conn->current_channel->channel_name,
+                   conn->current_channel->server[0] ? "@" : "",
+                   conn->current_channel->server);
+    name = tmp;
   } else {
     name = cmd->argv[1];
   }
@@ -2521,7 +2537,7 @@ SILC_FSM_STATE(silc_client_command_leave)
   SilcClient client = conn->client;
   SilcChannelEntry channel;
   SilcBuffer idp;
-  char *name;
+  char *name, tmp[512];
 
   if (cmd->argc != 2) {
     SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO,
@@ -2535,7 +2551,15 @@ SILC_FSM_STATE(silc_client_command_leave)
       COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL);
       goto out;
     }
-    name = conn->current_channel->channel_name;
+
+    if (client->internal->params->full_channel_names)
+      silc_snprintf(tmp, sizeof(tmp), conn->current_channel->channel_name);
+    else
+      silc_snprintf(tmp, sizeof(tmp), "%s%s%s",
+                   conn->current_channel->channel_name,
+                   conn->current_channel->server[0] ? "@" : "",
+                   conn->current_channel->server);
+    name = tmp;
   } else {
     name = cmd->argv[1];
   }
@@ -2580,7 +2604,7 @@ SILC_FSM_STATE(silc_client_command_users)
 {
   SilcClientCommandContext cmd = fsm_context;
   SilcClientConnection conn = cmd->conn;
-  char *name;
+  char *name, tmp[512];
 
   if (cmd->argc != 2) {
     SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO,
@@ -2594,7 +2618,15 @@ SILC_FSM_STATE(silc_client_command_users)
       COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL);
       goto out;
     }
-    name = conn->current_channel->channel_name;
+
+    if (conn->client->internal->params->full_channel_names)
+      silc_snprintf(tmp, sizeof(tmp), conn->current_channel->channel_name);
+    else
+      silc_snprintf(tmp, sizeof(tmp), "%s%s%s",
+                   conn->current_channel->channel_name,
+                   conn->current_channel->server[0] ? "@" : "",
+                   conn->current_channel->server);
+    name = tmp;
   } else {
     name = cmd->argv[1];
   }
index 4cb7db069b29f7d5d144ff6f2fae2549314568fc..3c0f56a88995527008a07b4c9b16c2daf88a6aea 100644 (file)
@@ -677,7 +677,8 @@ SILC_FSM_STATE(silc_client_command_reply_identify)
     }
 
     /* Notify application */
-    silc_client_command_callback(cmd, channel_entry, name, info);
+    silc_client_command_callback(cmd, channel_entry,
+                                channel_entry->channel_name, info);
     silc_client_unref_channel(client, conn, channel_entry);
     break;
   }
@@ -800,7 +801,8 @@ SILC_FSM_STATE(silc_client_command_reply_list)
   }
 
   /* Notify application */
-  silc_client_command_callback(cmd, channel_entry, name, topic, usercount);
+  silc_client_command_callback(cmd, channel_entry, channel_entry->channel_name,
+                              topic, usercount);
 
  out:
   silc_client_unref_channel(client, conn, channel_entry);
@@ -1302,7 +1304,7 @@ SILC_FSM_STATE(silc_client_command_reply_join)
   silc_hash_table_list(channel->user_list, &htl);
 
   /* Notify application */
-  silc_client_command_callback(cmd, channel_name, channel, mode, &htl,
+  silc_client_command_callback(cmd, channel->channel_name, channel, mode, &htl,
                               topic, cipher, hmac, channel->founder_key,
                               channel->channel_pubkeys, channel->user_limit);
 
index 569b2ab23164fd587559f9a0856f9ea319ff506c..898204a18f46663a571c0c38202d924fb9d3f089 100644 (file)
@@ -665,13 +665,16 @@ typedef struct SilcClientParamsStruct {
      %H  full hostname - the full hostname of the client
 
      Example format strings: "%n#%a"     (fe. nick#2, nick#3)
-                             "%n@%h%a"   (fe. nick@host, nick@host2)
-                             "%a!%n@%h"  (fe. nick@host, 2!nick@host)
+                             "%n#%h%a"   (fe. nick#host, nick#host2)
+                             "%a!%n#%h"  (fe. nick#host, 2!nick#host)
 
      Note that there must always be some separator characters around '%n'
      format.  It is not possible to put format characters before or after
      '%n' without separators (such ash '#').  Also note that the separator
      character should be a character that cannot be part of normal nickname.
+     Note that, using '@' as a separator is not recommended as the nickname
+     string may contain it to separate a server name from the nickname (eg.
+     nickname@silcnet.org).
   */
   char nickname_format[32];
 
@@ -683,6 +686,21 @@ typedef struct SilcClientParamsStruct {
      value. */
   SilcBool nickname_force_format;
 
+  /* If this is set to TRUE then all nickname strings returned by the library
+     and stored by the library are in the format of 'nickname@server', eg.
+     nickname@silcnet.org.  If this is FALSE then the server name of the
+     nickname is available only from the SilcClientEntry structure.  When this
+     is TRUE the server name is still parsed to SilcClientEntry. */
+  SilcBool full_nicknames;
+
+  /* If this is set to TRUE then all channel name strings returned by the
+     library and stored by the library are in the format of 'channel@server',
+     eg. silc@silcnet.org.  If this is FALSE then the server name of the
+     channel is available only from the SilcChannelEntry structure.  When this
+     is TRUE the server name is still parsed to SilcChannelEntry.  Note that,
+     not all SILC server versions return such channel name strings. */
+  SilcBool full_channel_names;
+
   /* If this is set to TRUE, the silcclient library will not register and
      deregister the cipher, pkcs, hash and hmac algorithms. The application
      itself will need to handle that. */
index 7685978ec8836ad83e0e072442369259da20dec0..4b57f859bcde386d125d05cc3be20e44160df1ad 100644 (file)
@@ -78,7 +78,7 @@
  * SOURCE
  */
 struct SilcClientEntryStruct {
-  char nickname[128 + 1];           /* Nickname */
+  char nickname[256 + 1];           /* Nickname */
   char username[128 + 1];           /* Username */
   char hostname[256 + 1];           /* Hostname */
   char server  [256 + 1];           /* SILC server name */
@@ -124,6 +124,7 @@ struct SilcClientEntryStruct {
  */
 struct SilcChannelEntryStruct {
   char *channel_name;               /* Channel name */
+  char server[256 + 1];                     /* SILC server name */
   char *topic;                      /* Current topic, may be NULL */
   SilcPublicKey founder_key;        /* Founder key, may be NULL */
   SilcDList channel_pubkeys;        /* Channel public keys, may be NULL */