updates.
[silc.git] / apps / silcd / command.c
index e9ee59679446ce6942d3a17a1944803a7c91246d..7055636ae6ec285bffcc07a9a79f0c5761116972 100644 (file)
@@ -297,9 +297,11 @@ silc_server_command_dup(SilcServerCommandContext ctx)
    with `context' when reply has been received.  It can be SILC_COMMAND_NONE
    to match any command with the `ident'.  If `ident' is non-zero
    the `callback' will be executed when received reply with command
-   identifier `ident'. */
+   identifier `ident'. If there already exists pending command for the
+   specified command, ident, callback and context this function has no
+   effect. */
 
-void silc_server_command_pending(SilcServer server,
+bool silc_server_command_pending(SilcServer server,
                                 SilcCommand reply_cmd,
                                 uint16 ident,
                                 SilcServerPendingDestructor destructor,
@@ -308,6 +310,16 @@ void silc_server_command_pending(SilcServer server,
 {
   SilcServerCommandPending *reply;
 
+  /* Check whether identical pending already exists for same command,
+     ident, callback and callback context. If it does then it would be
+     error to register it again. */
+  silc_dlist_start(server->pending_commands);
+  while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
+    if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
+       reply->callback == callback && reply->context == context)
+      return FALSE;
+  }
+
   reply = silc_calloc(1, sizeof(*reply));
   reply->reply_cmd = reply_cmd;
   reply->ident = ident;
@@ -315,6 +327,8 @@ void silc_server_command_pending(SilcServer server,
   reply->callback = callback;
   reply->destructor = destructor;
   silc_dlist_add(server->pending_commands, reply);
+
+  return TRUE;
 }
 
 /* Deletes pending command by reply command type. */
@@ -736,17 +750,6 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
     if (!entry)
       continue;
 
-#if 1
-    /* XXX REMOVE */
-    /* Sanity check, however these should never fail. However, as
-       this sanity check has been added here they have failed. */
-    if (!entry->nickname || !entry->username || !entry->userinfo) {
-      SILC_LOG_ERROR(("********* if (!entry->nickname || !entry->username "
-                     "|| !entry->userinfo) triggered: should have not!"));
-      continue;
-    }
-#endif
-
     if (k >= 1)
       status = SILC_STATUS_LIST_ITEM;
     if (valid_count > 1 && k == valid_count - 1)
@@ -1117,25 +1120,6 @@ silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
     if (clients_count > 1 && i == clients_count - 1)
       status = SILC_STATUS_LIST_END;
 
-    /* Sanity check, however these should never fail. However, as
-       this sanity check has been added here they have failed. */
-    if (!entry->nickname || !entry->username || !entry->userinfo) {
-      SILC_LOG_ERROR(("********* if (!entry->nickname || !entry->username "
-                     "|| !entry->userinfo) triggered: should have not!"));
-      continue;
-    }
-
-#if 1
-    /* XXX REMOVE */
-    /* Sanity check, however these should never fail. However, as
-       this sanity check has been added here they have failed. */
-    if (!entry->nickname || !entry->username) {
-      SILC_LOG_ERROR(("********* if (!entry->nickname || !entry->username) "
-                     "triggered: should have not!"));
-      continue;
-    }
-#endif
-      
     /* Send WHOWAS reply */
     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
     tmp = silc_argument_get_first_arg(cmd->args, NULL);
@@ -1796,7 +1780,7 @@ silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
 
     /* Process all valid client entries and send command replies */
 
-    if (len > 1)
+    if (valid_count > 1)
       status = SILC_STATUS_LIST_START;
 
     for (i = 0, k = 0; i < clients_count; i++) {
@@ -1956,6 +1940,7 @@ silc_server_command_identify_process(SilcServerCommandContext cmd)
                                           &count);
   if (ret < 1)
     return ret;
+  ret = 0;
 
   /* Check that all mandatory fields are present and request those data
      from the server who owns the client if necessary. */
@@ -2118,7 +2103,7 @@ silc_server_command_list_send_reply(SilcServerCommandContext cmd,
                                    SilcChannelEntry *gch,
                                    uint32 gch_count)
 {
-  int i;
+  int i, k;
   SilcBuffer packet, idp;
   SilcChannelEntry entry;
   SilcCommandStatus status;
@@ -2126,27 +2111,34 @@ silc_server_command_list_send_reply(SilcServerCommandContext cmd,
   char *topic;
   unsigned char usercount[4];
   uint32 users;
+  int valid_lcount = 0, valid_rcount = 0;
 
-  for (i = 0; i < lch_count; i++)
+  for (i = 0; i < lch_count; i++) {
     if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
       lch[i] = NULL;
-  for (i = 0; i < gch_count; i++)
+    else
+      valid_lcount++;
+  }
+  for (i = 0; i < gch_count; i++) {
     if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
       gch[i] = NULL;
+    else
+      valid_rcount++;
+  }
 
   status = SILC_STATUS_OK;
   if ((lch_count + gch_count) > 1)
     status = SILC_STATUS_LIST_START;
 
   /* Local list */
-  for (i = 0; i < lch_count; i++) {
+  for (i = 0, k = 0; i < lch_count; i++) {
     entry = lch[i];
     if (!entry)
       continue;
 
-    if (i >= 1)
+    if (k >= 1)
       status = SILC_STATUS_LIST_ITEM;
-    if (i >= 1 && i == lch_count - 1 && !gch_count)
+    if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
       status = SILC_STATUS_LIST_END;
 
     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
@@ -2174,17 +2166,18 @@ silc_server_command_list_send_reply(SilcServerCommandContext cmd,
                            packet->len, FALSE);
     silc_buffer_free(packet);
     silc_buffer_free(idp);
+    k++;
   }
 
   /* Global list */
-  for (i = 0; i < gch_count; i++) {
+  for (i = 0, k = 0; i < gch_count; i++) {
     entry = gch[i];
     if (!entry)
       continue;
 
-    if (i >= 1)
+    if (k >= 1)
       status = SILC_STATUS_LIST_ITEM;
-    if (i >= 1 && i == gch_count - 1)
+    if (valid_rcount > 1 && k == valid_rcount - 1)
       status = SILC_STATUS_LIST_END;
 
     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
@@ -2212,6 +2205,7 @@ silc_server_command_list_send_reply(SilcServerCommandContext cmd,
                            packet->len, FALSE);
     silc_buffer_free(packet);
     silc_buffer_free(idp);
+    k++;
   }
 }
 
@@ -3159,8 +3153,7 @@ static void silc_server_command_join_channel(SilcServer server,
     }
   
     if (!passphrase || !channel->passphrase ||
-        memcmp(channel->passphrase, passphrase,
-               strlen(channel->passphrase))) {
+        memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
                                            SILC_STATUS_ERR_BAD_PASSWORD);
       goto out;
@@ -3489,11 +3482,15 @@ SILC_SERVER_CMD_FUNC(join)
   if (cmd->pending && context2) {
     SilcServerCommandReplyContext reply = 
       (SilcServerCommandReplyContext)context2;
+
     if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
       tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
       SILC_GET32_MSB(created, tmp);
       create_key = FALSE;      /* Router returned the key already */
     }
+
+    if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS)
+      created = TRUE;
   }
 
   /* If the channel does not have global users and is also empty the client