updates.
authorPekka Riikonen <priikone@silcnet.org>
Thu, 1 Feb 2001 18:04:08 +0000 (18:04 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Thu, 1 Feb 2001 18:04:08 +0000 (18:04 +0000)
CHANGES
apps/silcd/command.c
apps/silcd/command_reply.c
apps/silcd/packet_receive.c
apps/silcd/packet_send.c
apps/silcd/server.c
apps/silcd/testi2.conf
lib/silcclient/command.c
lib/silcclient/command.h
lib/silcclient/command_reply.c
lib/silcclient/idlist.c

diff --git a/CHANGES b/CHANGES
index b147d9083cb69c22f26e26951eff682b55ce8fe5..b2c25a0743e291ab3a1de21f067398a2fb1ab34e 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,35 @@
+Thu Feb  1 21:32:27 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+       * Fixed some minor bugs in client when sending WHOIS command.  The
+         arguments was in wrong order.
+
+       * Removed statis function add_to_channel from server in 
+         silcd/command.c that was previously used with the joining but
+         is obsolete now.
+
+       * Tested USERS command in router environment successfully with two
+         routers, two servers and two clients.
+
+Thu Feb  1 00:54:26 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+       * Reorganized the USERS command and command reply in client library
+         in lib/silcclient/command.c and lib/silcclient/command_reply.c.
+         When the command is given by user we register a pending command
+         callback that will reprocess the command after the reply has been
+         received from the server.  When reprocessing the packet we then
+         display the information.  Thus, the USERS information is displayed
+         now in the command callback instead of in the command reply
+         callback.  The processing of the command is same as previously
+         when server has sent the command reply in the JOINing process.
+
+       * Added to USERS command in silcd/command_reply.c to join the client,
+         we didn't use to know about, to the channel after we've created
+         a client entry for it.  Also, for clienet we did know already still
+         check whether it is on the channel or not and add it if not.
+
+       * Removed silc_server_command_join_notify as the function and its
+         use was obsolete.
+
 Tue Jan 30 22:39:15 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
 
        * Changed the client's pending command handling to the same as the
index b7f9f680b60ad734945b42ed05a6d2c460e35744..31420b44950b2248be275fd32a3c46306c607eff 100644 (file)
@@ -40,7 +40,8 @@ silc_server_command_send_status_data(SilcServerCommandContext cmd,
 static void silc_server_command_free(SilcServerCommandContext cmd);
 void silc_server_command_send_users(SilcServer server,
                                    SilcSocketConnection sock,
-                                   SilcChannelEntry channel);
+                                   SilcChannelEntry channel,
+                                   int pending);
 
 /* Server command list. */
 SilcServerCommand silc_command_list[] =
@@ -325,7 +326,7 @@ silc_server_command_whois_parse(SilcServerCommandContext cmd,
   int i, k;
 
   /* If client ID is in the command it must be used instead of nickname */
-  tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
+  tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
   if (!tmp) {
     /* No ID, get the nickname@server string and parse it. */
     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
@@ -919,7 +920,7 @@ silc_server_command_identify_from_client(SilcServerCommandContext cmd)
 {
   SilcServer server = cmd->server;
   char *nick = NULL, *server_name = NULL;
-  int count = 0, clients_count; 
+  int count = 0, clients_count = 0
   SilcClientEntry *clients = NULL, entry;
   SilcClientID **client_id = NULL;
   unsigned int client_id_count = 0;
@@ -1052,7 +1053,7 @@ silc_server_command_identify_from_server(SilcServerCommandContext cmd)
 {
   SilcServer server = cmd->server;
   char *nick = NULL, *server_name = NULL;
-  int count = 0, clients_count;
+  int count = 0, clients_count = 0;
   SilcClientEntry *clients = NULL, entry;
   SilcClientID **client_id = NULL;
   unsigned int client_id_count = 0;
@@ -1114,9 +1115,17 @@ silc_server_command_identify_from_server(SilcServerCommandContext cmd)
 
   if (!clients) {
     /* Such a client really does not exist in the SILC network. */
-    silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
-                                        SILC_STATUS_ERR_NO_SUCH_NICK,
-                                        3, nick, strlen(nick));
+    if (!client_id_count) {
+      silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
+                                          SILC_STATUS_ERR_NO_SUCH_NICK,
+                                          3, nick, strlen(nick));
+    } else {
+      SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
+      silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
+                                          SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
+                                          2, idp->data, idp->len);
+      silc_buffer_free(idp);
+    }
     goto out;
   }
 
@@ -1619,63 +1628,20 @@ SILC_SERVER_CMD_FUNC(oper)
 {
 }
 
-typedef struct {
-  char *channel_name;
-  char *nickname;
-  char *username;
-  char *hostname;
-  SilcChannelEntry channel;
-  SilcServer server;
-  SilcClientEntry client;
-} JoinInternalContext;
-
-SILC_TASK_CALLBACK(silc_server_command_join_notify)
-{
-  JoinInternalContext *ctx = (JoinInternalContext *)context;
-
-  if (ctx->channel->key && ctx->channel->key_len) {
-    SilcBuffer clidp;
-
-    clidp = silc_id_payload_encode(ctx->client->id, SILC_ID_CLIENT);
-
-    silc_server_send_notify_to_channel(ctx->server, ctx->channel, FALSE,
-                                      SILC_NOTIFY_TYPE_JOIN, 1,
-                                      clidp->data, clidp->len);
-#if 0
-    /* Send NEW_CHANNEL_USER packet to primary route */
-    silc_server_send_new_channel_user(server, server->router->connection,
-                                     server->server_type == SILC_SERVER ?
-                                     FALSE : TRUE,
-                                     channel->id, SILC_ID_CHANNEL_LEN,
-                                     client->id, SILC_ID_CLIENT_LEN);
-#endif
-
-    /* Send USERS command reply to the joined channel so the user sees who
-       is currently on the channel. */
-    silc_server_command_send_users(ctx->server, ctx->client->connection, 
-                                  ctx->channel);
-
-    silc_buffer_free(clidp);
-    silc_free(ctx);
-  } else {
-    silc_task_register(ctx->server->timeout_queue, fd,
-                      silc_server_command_join_notify, context,
-                      0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
-  }
-}
-
 /* Assembles USERS command and executes it. This is called when client
    joins to a channel and we wan't to send USERS command reply to the 
    client. */
 
 void silc_server_command_send_users(SilcServer server,
                                    SilcSocketConnection sock,
-                                   SilcChannelEntry channel)
+                                   SilcChannelEntry channel,
+                                   int pending)
 {
   SilcServerCommandContext cmd;
   SilcBuffer buffer, idp;
   SilcPacketContext *packet = silc_packet_context_alloc();
 
+  /* Create USERS command packet and process it. */
   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
   buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
                                          1, idp->data, idp->len);
@@ -1692,51 +1658,27 @@ void silc_server_command_send_users(SilcServer server,
   cmd->packet = silc_packet_context_dup(packet);
   cmd->pending = FALSE;
 
-  silc_server_command_users((void *)cmd);
+  if (pending) {
+    /* If this function was called from pending command then instead of
+       processing the command now, register a pending command callback which
+       will process it after we've received the automatic USERS command 
+       reply. */
+    silc_server_command_pending(server, SILC_COMMAND_USERS, 0,
+                               silc_server_command_users, (void *)cmd);
+    cmd->pending = TRUE;
+    silc_free(buffer);
+    silc_free(idp);
+    return;
+  }
 
+  /* Process USERS command. */
+  silc_server_command_users((void *)cmd);
   silc_free(buffer);
   silc_free(idp);
   silc_packet_context_free(packet);
 }
 
-/* Internal routine that is called after router has replied to server's
-   JOIN command it forwarded to the router. The route has joined and possibly
-   creaetd the channel. This function adds the client to the channel's user
-   list. */
-
-SILC_SERVER_CMD_FUNC(add_to_channel)
-{
-  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
-  SilcServer server = cmd->server;
-  SilcClientEntry client;
-  SilcChannelEntry channel;
-  SilcChannelClientEntry chl;
-  char *channel_name;
-
-  /* Get channel name */
-  channel_name = silc_argument_get_arg_type(cmd->args, 1, NULL);
-
-  /* Get client entry */
-  client = (SilcClientEntry)cmd->sock->user_data;
-
-  /* Get channel entry */
-  channel = silc_idlist_find_channel_by_name(server->local_list, 
-                                            channel_name, NULL);
-  if (channel) {
-    /* Join the client to the channel by adding it to channel's user list.
-       Add also the channel to client entry's channels list for fast cross-
-       referencing. */
-    chl = silc_calloc(1, sizeof(*chl));
-    //chl->mode = SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO;
-    chl->client = client;
-    chl->channel = channel;
-    silc_list_add(channel->user_list, chl);
-    silc_list_add(client->channels, chl);
-  }
-
-  silc_server_command_free(cmd);
-}
-
 /* Internal routine to join channel. The channel sent to this function
    has been either created or resolved from ID lists. This joins the sent
    client to the channel. */
@@ -1897,34 +1839,24 @@ static void silc_server_command_join_channel(SilcServer server,
   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
                          reply->data, reply->len, FALSE);
 
-  if (!cmd->pending)
+  if (!cmd->pending) {
     /* Send JOIN notify to locally connected clients on the channel */
     silc_server_send_notify_to_channel(server, channel, FALSE,
                                       SILC_NOTIFY_TYPE_JOIN, 1,
                                       clidp->data, clidp->len);
 
-  /* Send NEW_CHANNEL_USER packet to our primary router */
-  if (!cmd->pending && !server->standalone)
-    silc_server_send_new_channel_user(server, server->router->connection,
-                                     server->server_type == SILC_SERVER ?
-                                     FALSE : TRUE,
-                                     channel->id, SILC_ID_CHANNEL_LEN,
-                                     client->id, SILC_ID_CLIENT_LEN);
+    /* Send NEW_CHANNEL_USER packet to our primary router */
+    if (!server->standalone)
+      silc_server_send_new_channel_user(server, server->router->connection,
+                                       server->server_type == SILC_SERVER ?
+                                       FALSE : TRUE,
+                                       channel->id, SILC_ID_CHANNEL_LEN,
+                                       client->id, SILC_ID_CLIENT_LEN);
+  }
 
   /* Send USERS command reply to the joined channel so the user sees who
      is currently on the channel. */
-  silc_server_command_send_users(server, sock, channel);
-
-  /*
-
-    FAQ:
-
-   * Kuinka USERS komento händlätään serverissä kun router lähettää sen
-   serverille joka on lähettäny sille clientin puolesta JOIN komennon?
-   
-   R: Serverin pitää ymmärtää USERS comman replyjä.
-
-  */
+  silc_server_command_send_users(server, sock, channel, cmd->pending);
 
   silc_buffer_free(reply);
   silc_buffer_free(clidp);
@@ -2846,23 +2778,25 @@ SILC_SERVER_CMD_FUNC(users)
   SilcChannelClientEntry chl;
   SilcChannelID *id;
   SilcBuffer packet;
-  unsigned char *tmp;
-  unsigned int tmp_len;
+  unsigned char *channel_id;
+  unsigned int channel_id_len;
   SilcBuffer client_id_list;
   SilcBuffer client_mode_list;
   SilcBuffer idp;
+  unsigned char lc[4];
+  unsigned int list_count = 0;
   unsigned short ident = silc_command_get_ident(cmd->payload);
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 2);
 
   /* Get Channel ID */
-  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
-  if (!tmp) {
+  channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
+  if (!channel_id) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID);
     goto out;
   }
-  id = silc_id_payload_parse_id(tmp, tmp_len);
+  id = silc_id_payload_parse_id(channel_id, channel_id_len);
 
   /* If we are server and we don't know about this channel we will send
      the command to our router. If we know about the channel then we also
@@ -2923,19 +2857,25 @@ SILC_SERVER_CMD_FUNC(users)
     /* Client's mode on channel */
     SILC_PUT32_MSB(chl->mode, client_mode_list->data);
     silc_buffer_pull(client_mode_list, 4);
+
+    list_count++;
   }
   silc_buffer_push(client_id_list, 
                   client_id_list->data - client_id_list->head);
   silc_buffer_push(client_mode_list, 
                   client_mode_list->data - client_mode_list->head);
 
+  /* List count */
+  SILC_PUT32_MSB(list_count, lc);
+
   /* Send reply */
   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
                                                SILC_STATUS_OK, 0, 4,
-                                               2, tmp, tmp_len,
-                                               3, client_id_list->data,
+                                               2, channel_id, channel_id_len,
+                                               3, lc, 4,
+                                               4, client_id_list->data,
                                                client_id_list->len,
-                                               4, client_mode_list->data,
+                                               5, client_mode_list->data,
                                                client_mode_list->len);
   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
                          packet->data, packet->len, FALSE);
index 073bf822477dc3332e990347004644c83f8ef499..d5f3dbffd3dfe2c955681ad7c196cd02222d4789 100644 (file)
@@ -325,10 +325,11 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
       }
     }
 
-    if (nickname && client->nickname) {
+    if (nickname && client->nickname)
       silc_free(client->nickname);
+
+    if (nickname)
       client->nickname = nick;
-    }
 
     if (username && client->username) {
       silc_free(client->username);
@@ -573,12 +574,23 @@ SILC_SERVER_CMD_REPLY_FUNC(users)
       /* We don't have that client anywhere, add it. The client is added
         to global list since server didn't have it in the lists so it must be 
         global. */
-      silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
-                            client_id, NULL, NULL);
+      client = silc_idlist_add_client(server->global_list, NULL, NULL, 
+                                     NULL, client_id, cmd->sock->user_data, 
+                                     NULL);
     } else {
       /* We have the client already. */
       silc_free(client_id);
     }
+
+    if (!silc_server_client_on_channel(client, channel)) {
+      /* Client was not on the channel, add it. */
+      SilcChannelClientEntry chl = silc_calloc(1, sizeof(*chl));
+      chl->client = client;
+      chl->mode = mode;
+      chl->channel = channel;
+      silc_list_add(channel->user_list, chl);
+      silc_list_add(client->channels, chl);
+    }
   }
 
   silc_buffer_free(client_id_list);
index 890e4cd3e847d85135587e0b84ea483114c71539..37575a32b828bbbfb6ed095106cb33da231dff19 100644 (file)
@@ -325,7 +325,7 @@ void silc_server_replace_id(SilcServer server,
      we will broadcast it. The sending socket really cannot be router or
      the router is buggy. If this packet is coming from router then it must
      have the broadcast flag set already and we won't do anything. */
-  if (server->server_type == SILC_ROUTER &&
+  if (!server->standalone && server->server_type == SILC_ROUTER &&
       sock->type == SILC_SOCKET_TYPE_SERVER &&
       !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
     SILC_LOG_DEBUG(("Broadcasting received Replace ID packet"));
index 70911cf0a4db4ba0d2943f3f20c9741be830d49d..3d89b5064a1d2aa82d2164ce747786bb134cc520 100644 (file)
@@ -395,10 +395,7 @@ void silc_server_packet_send_to_channel(SilcServer server,
       continue;
     }
 
-    if (server->server_type == SILC_ROUTER && !route)
-      continue;
-
-    if (server->server_type == SILC_SERVER && client->router)
+    if (client && client->router)
       continue;
 
     /* Send to locally connected client */
index c562e8685663d558d3b0b4eb7fdea49fc3435e99..4a55bac69f4db50002d00590654d0d272c935504 100644 (file)
@@ -1630,10 +1630,11 @@ void silc_server_free_sock_user_data(SilcServer server,
       /* XXX must take some info to history before freeing */
 
       /* Send REMOVE_ID packet to routers. */
-      silc_server_send_remove_id(server, server->router->connection,
-                                server->server_type == SILC_SERVER ?
-                                FALSE : TRUE, user_data->id, 
-                                SILC_ID_CLIENT_LEN, SILC_ID_CLIENT);
+      if (!server->standalone)
+       silc_server_send_remove_id(server, server->router->connection,
+                                  server->server_type == SILC_SERVER ?
+                                  FALSE : TRUE, user_data->id, 
+                                  SILC_ID_CLIENT_LEN, SILC_ID_CLIENT);
 
       /* Free the client entry and everything in it */
       silc_idlist_del_data(user_data);
index 4007fc60e7d3c7f9f2c4c9f58e3c885baf373d6e..984d93b2c3ada808bc7810dc6e06ab2c5ba1cfe6 100644 (file)
@@ -16,10 +16,10 @@ sha1::64:20
 Mun huone:Mun servo:Pekka Riikonen:priikone@poseidon.pspt.fi
 
 [ServerInfo]
-lassi.kuo.fi.ssh.com:10.2.1.7:Kuopio, Finland:1334
+lassi.kuo.fi.ssh.com:212.146.8.246:Kuopio, Finland:1334
 
 [ListenPort]
-10.2.1.7:10.2.1.7:1334
+212.146.8.246:212.146.8.246:1334
 
 [Logging]
 infologfile:silcd2.log:10000
@@ -40,10 +40,10 @@ errorlogfile:silcd2.log:10000
 [AdminConnection]
 
 [ServerConnection]
-10.2.1.7:passwd:priikone:1333:1:1
+212.146.8.246:passwd:priikone:1333:1:1
 
 [RouterConnection]
-10.2.1.7:passwd:priikone:1335:1:1:0
+212.146.8.246:passwd:priikone:1335:1:1:0
 
 [DenyConnection]
 [RedirectClient]
index c543ed904100058a3d20008c59310ced3979a0b8..bed9099548068f9ae7e1c5be52f4c4c29b74e572 100644 (file)
@@ -1172,6 +1172,7 @@ SILC_CLIENT_CMD_FUNC(users)
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
   SilcClientConnection conn = cmd->conn;
   SilcIDCacheEntry id_cache = NULL;
+  SilcChannelEntry channel;
   SilcBuffer buffer, idp;
   char *name;
 
@@ -1213,25 +1214,79 @@ SILC_CLIENT_CMD_FUNC(users)
     goto out;
   }
 
-  /* Send USERS command to the server */
-  idp = silc_id_payload_encode(id_cache->id, SILC_ID_CHANNEL);
-  buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1, 
-                                         1, idp->data, idp->len);
-  silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL, 
-                         0, NULL, NULL, buffer->data, buffer->len, TRUE);
-  silc_buffer_free(buffer);
-  silc_buffer_free(idp);
+  channel = (SilcChannelEntry)id_cache->context;
+
+  if (!cmd->pending) {
+    /* Send USERS command to the server */
+    idp = silc_id_payload_encode(id_cache->id, SILC_ID_CHANNEL);
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1, 
+                                           1, idp->data, idp->len);
+    silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, 
+                           NULL, 0, NULL, NULL, buffer->data, 
+                           buffer->len, TRUE);
+    silc_buffer_free(buffer);
+    silc_buffer_free(idp);
+
+    /* Register pending callback which will recall this command callback with
+       same context and reprocesses the command. When reprocessing we actually
+       display the information on the screen. */
+    silc_client_command_pending(conn, SILC_COMMAND_USERS, 0, 
+                               silc_client_command_users, context);
+    cmd->pending = TRUE;
+    return;
+  }
+
+  if (cmd->pending) {
+    /* Pending command. Now we've resolved the information from server and
+       we are ready to display the information on screen. */
+    int i;
+    SilcChannelUser chu;
+
+    cmd->client->ops->say(cmd->client, conn, "Users on %s", 
+                         channel->channel_name);
 
-  /* Register dummy pending command that will tell the reply command
-     that user called this command. Server may send reply to this command
-     even if user did not send this command thus we want to handle things
-     differently when user sent the command. This is dummy and won't be
-     executed. */
-  /* XXX this is kludge and should be removed after pending command reply 
-     support is added. Currently only commands may be pending not command
-     replies. */
-  silc_client_command_pending(conn, SILC_COMMAND_USERS, 0, 
-                             silc_client_command_users, NULL);
+    silc_list_start(channel->clients);
+    while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
+      SilcClientEntry e = chu->client;
+      char *m, tmp[80], line[80], len1;
+
+      memset(line, 0, sizeof(line));
+      memset(tmp, 0, sizeof(tmp));
+      m = silc_client_chumode_char(chu->mode);
+
+      strcat(line, " ");
+      strcat(line, e->nickname);
+      strcat(line, e->server ? "@" : "");
+
+      len1 = 0;
+      if (e->server)
+       len1 = strlen(e->server);
+      strncat(line, e->server ? e->server : "", len1 > 30 ? 30 : len1);
+
+      len1 = strlen(line);
+      if (len1 >= 30) {
+       memset(&line[29], 0, len1 - 29);
+      } else {
+       for (i = 0; i < 30 - len1 - 1; i++)
+         strcat(line, " ");
+      }
+
+      strcat(line, "  H");
+      strcat(tmp, m ? m : "");
+      strcat(line, tmp);
+
+      if (strlen(tmp) < 5)
+       for (i = 0; i < 5 - strlen(tmp); i++)
+         strcat(line, " ");
+
+      strcat(line, e->username ? e->username : "");
+
+      cmd->client->ops->say(cmd->client, conn, "%s", line);
+
+      if (m)
+       silc_free(m);
+    }
+  }
 
   /* Notify application */
   COMMAND;
index dfe4f586d4d19349b8bfae98cc576791bbb727f3..a9cb241a77fd77371ed43c335e19ae80ba15ec8c 100644 (file)
@@ -70,12 +70,11 @@ typedef struct {
   unsigned char **argv;
   unsigned int *argv_lens;
   unsigned int *argv_types;
+  int pending;                 /* Command is being re-processed when TRUE */
 } *SilcClientCommandContext;
 
 /* Structure holding pending commands. If command is pending it will be
    executed after command reply has been executed. */
-/* XXX This support may added for commands as well and not just command
-   replies, if needed later. */
 typedef struct SilcClientCommandPendingStruct {
   SilcCommand reply_cmd;
   SilcCommandCb callback;
index 51716566cbf05f438ea72fd3cb553fd07f375cad..85fa37da45556fccc6b3672eacffa64488cdce2a 100644 (file)
@@ -1103,11 +1103,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
     SILC_GET16_MSB(idp_len, client_id_list->data + 2);
     idp_len += 4;
     client_id = silc_id_payload_parse_id(client_id_list->data, idp_len);
-    silc_buffer_pull(client_id_list, idp_len);
 
     /* Mode */
     SILC_GET32_MSB(mode, client_mode_list->data);
-    silc_buffer_pull(client_mode_list, 4);
 
     /* Check if we have this client cached already. */
     if (!silc_idcache_find_by_id_one(conn->client_cache, (void *)client_id,
@@ -1135,6 +1133,9 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
       silc_free(client_id);
       id_cache = NULL;
     }
+
+    silc_buffer_pull(client_id_list, idp_len);
+    silc_buffer_pull(client_mode_list, 4);
   }
 
   /* Query the client information from server if the list included clients
@@ -1171,54 +1172,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
   /* We have all the clients on the channel cached now. Create a nice
      output for user interface and notify application. */
 
-  if (cmd->callback) {
-    /* User has called USERS command on user interface. */
-    cmd->client->ops->say(cmd->client, conn, "Users on %s", 
-                         channel->channel_name);
-    
-    silc_list_start(channel->clients);
-    while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
-      SilcClientEntry e = chu->client;
-      char *m, tmp[80], line[80], len1;
-
-      memset(line, 0, sizeof(line));
-      memset(tmp, 0, sizeof(tmp));
-      m = silc_client_chumode_char(chu->mode);
-
-      strcat(line, " ");
-      strcat(line, e->nickname);
-      strcat(line, e->server ? "@" : "");
-
-      len1 = 0;
-      if (e->server)
-       len1 = strlen(e->server);
-      strncat(line, e->server ? e->server : "", len1 > 30 ? 30 : len1);
-
-      len1 = strlen(line);
-      if (len1 >= 30) {
-       memset(&line[29], 0, len1 - 29);
-      } else {
-       for (i = 0; i < 30 - len1 - 1; i++)
-         strcat(line, " ");
-      }
-
-      strcat(line, "  H");
-      strcat(tmp, m ? m : "");
-      strcat(line, tmp);
-
-      if (strlen(tmp) < 5)
-       for (i = 0; i < 5 - strlen(tmp); i++)
-         strcat(line, " ");
-
-      strcat(line, e->username ? e->username : "");
-
-      cmd->client->ops->say(cmd->client, conn, "%s", line);
-
-      if (m)
-       silc_free(m);
-    }
-
-  } else {
+  if (!cmd->callback) {
     /* Server has sent us USERS reply even when we haven't actually sent
        USERS command. This is normal behaviour when joining to a channel.
        Display some nice information on the user interface. */
index a14dc63e1c372c094fba0bdfa22a60e580123cc4..9638ee1226ff02c25f80a7de95729e0edb0f24b0 100644 (file)
@@ -123,7 +123,7 @@ SilcClientEntry silc_idlist_get_client_by_id(SilcClient client,
     } else {
       SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
       silc_client_send_command(client, conn, SILC_COMMAND_WHOIS, 1,
-                              2, idp->data, idp->len);
+                              3, idp->data, idp->len);
       return NULL;
     }
   }