Added SilcPublicKey to SilcClientEntry.
authorPekka Riikonen <priikone@silcnet.org>
Sun, 22 Feb 2004 16:25:55 +0000 (16:25 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 22 Feb 2004 16:25:55 +0000 (16:25 +0000)
Fixed the get_clients_whois to work with attributes correctly.

CHANGES
lib/silcclient/client_internal.h
lib/silcclient/command.h
lib/silcclient/command_reply.c
lib/silcclient/idlist.c
lib/silcclient/silcclient.h

diff --git a/CHANGES b/CHANGES
index e48d7389cbd07763e536ee7c9b9cb3e025dee006..61a90f08e03995c7d00fdf717a5df3f925ddd2d6 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,18 @@
+Sun Feb 22 19:03:59 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added public key to the SIlcClientEntry.  Affected files
+         are lib/silcclient/silcclient.h, command_reply.c, idlist.c
+
+       * Fixed the get_clients_whois reply processing to return
+         exactly same entries server returned.  Makes it possible
+         to search using attributes.  Affected file is
+         lib/silcclient/idlist.c.
+
+Sat Feb 21 19:21:57 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Save founder key to SilcChannelEntry.  Affected files are
+         lib/silcclient/silcclient.h, command_reply.c, idlist.c.
+
 Fri Feb 20 20:37:38 EET 2004  Pekka Riikonen <priikone@silcnet.org>
 
        * Call the monitor callback with _CLOSED status from the
index 4155d61ed93e77a40f49d779d8f81329e2a96bb8..37558019f236b32718855e5141388bc0c398025b 100644 (file)
@@ -293,5 +293,9 @@ SilcBuffer silc_client_attributes_process(SilcClient client,
 void silc_client_packet_queue_purge(SilcClient client,
                                    SilcSocketConnection sock);
 SILC_TASK_CALLBACK_GLOBAL(silc_client_rekey_callback);
+void
+silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd,
+                                    SilcStatus status,
+                                    bool notify);
 
 #endif
index de06296d540c22c5b11c6ea349bee9e4da10ee70..c6c597de1cb49f038bb03bc0ca96935819c0fb00 100644 (file)
@@ -1,6 +1,6 @@
 /*
 
-  command.h 
+  command.h
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
@@ -122,7 +122,7 @@ void silc_client_command_pending_del(SilcClientConnection conn,
 SilcClientCommandPendingCallbacks
 silc_client_command_pending_check(SilcClientConnection conn,
                                  SilcClientCommandReplyContext ctx,
-                                 SilcCommand command, 
+                                 SilcCommand command,
                                  SilcUInt16 ident,
                                  SilcUInt32 *callbacks_count);
 void silc_client_command_process(SilcClient client,
index 02e6c330f17f6ed1f4f2607d9c7ce7f0308b18ad..6cb2c1d771a74dcedb4c68adb5d5113d80d00fb0 100644 (file)
@@ -160,7 +160,7 @@ void silc_client_command_reply_free(SilcClientCommandReplyContext cmd)
   }
 }
 
-static void
+void
 silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd,
                                     SilcStatus status,
                                     bool notify)
@@ -968,7 +968,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
   SilcUInt32 argc, mode = 0, len, list_count;
   char *topic, *tmp, *channel_name = NULL, *hmac;
   SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
-  SilcPublicKey founder_key = NULL;
   SilcBufferStruct chpklist;
   int i;
 
@@ -1042,6 +1041,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
   }
 
   conn->current_channel = channel;
+  channel->mode = mode;
 
   /* Get hmac */
   hmac = silc_argument_get_arg_type(cmd->args, 11, NULL);
@@ -1129,8 +1129,12 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
 
   /* Get founder key */
   tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
-  if (tmp)
-    silc_pkcs_public_key_payload_decode(tmp, len, &founder_key);
+  if (tmp) {
+    if (channel->founder_key)
+      silc_pkcs_public_key_free(channel->founder_key);
+    channel->founder_key = NULL;
+    silc_pkcs_public_key_payload_decode(tmp, len, &channel->founder_key);
+  }
 
   /* Get channel public key list */
   tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
@@ -1146,13 +1150,12 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
   COMMAND_REPLY((SILC_ARGS, channel_name, channel, mode, 0,
                 keyp ? keyp->head : NULL, NULL,
                 NULL, topic, hmac, list_count, client_id_list,
-                client_mode_list, founder_key, tmp ? &chpklist : NULL));
+                client_mode_list, channel->founder_key,
+                tmp ? &chpklist : NULL));
 
  out:
   SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
   silc_client_command_reply_free(cmd);
-  if (founder_key)
-    silc_pkcs_public_key_free(founder_key);
   silc_buffer_free(keyp);
   silc_buffer_free(client_id_list);
   silc_buffer_free(client_mode_list);
@@ -1960,9 +1963,14 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey)
       silc_hash_make(cmd->client->sha1hash, tmp + 4, len - 4,
                     client_entry->fingerprint);
     }
+    if (!client_entry->public_key) {
+      client_entry->public_key = public_key;
+      public_key = NULL;
+    }
 
     /* Notify application */
-    COMMAND_REPLY((SILC_ARGS, id_type, client_entry, public_key));
+    COMMAND_REPLY((SILC_ARGS, id_type, client_entry,
+                  client_entry->public_key));
   } else if (id_type == SILC_ID_SERVER) {
     /* Received server's public key */
     server_id = silc_id_payload_get_id(idp);
index 38864297a5ab08ded2a0c9fc5dc27a1b481dcd71..c6dbd425db380ecda3f7da15a70d6358bf6179ae 100644 (file)
@@ -121,9 +121,12 @@ typedef struct {
   SilcGetClientCallback completion;
   void *context;
   char *nickname;
-  char *server;
+  SilcClientEntry *clients;
+  SilcUInt32 clients_count;
 } *GetClientInternal;
 
+/* Completion for IDENTIFY */
+
 SILC_CLIENT_CMD_FUNC(get_client_callback)
 {
   GetClientInternal i = (GetClientInternal)context;
@@ -142,10 +145,126 @@ SILC_CLIENT_CMD_FUNC(get_client_callback)
   }
 
   silc_free(i->nickname);
-  silc_free(i->server);
   silc_free(i);
 }
 
+/* Completion for WHOIS */
+
+SILC_CLIENT_CMD_FUNC(get_client_callback_wc)
+{
+  GetClientInternal i = (GetClientInternal)context;
+  SilcClientCommandReplyContext cmd = context2;
+  SilcClientID *client_id = NULL;
+  SilcClientEntry client_entry = NULL;
+  unsigned char *id_data;
+  SilcUInt32 len;
+
+  /* Get the client entry just returned from server */
+  id_data = silc_argument_get_arg_type(cmd->args, 2, &len);
+  if (id_data)
+    client_id = silc_id_payload_parse_id(id_data, len, NULL);
+  if (client_id)
+    client_entry = silc_client_get_client_by_id(i->client,
+                                               i->conn, client_id);
+  if (!client_entry) {
+    if (!SILC_STATUS_IS_ERROR(cmd->status) &&
+       cmd->status != SILC_STATUS_OK &&
+       cmd->status != SILC_STATUS_LIST_END) {
+      silc_free(client_id);
+      return;
+    }
+
+    i->completion(i->client, i->conn, i->clients, i->clients_count,
+                 i->context);
+    silc_free(client_id);
+    silc_free(i->clients);
+    silc_free(i->nickname);
+    silc_free(i);
+    return;
+  }
+
+  /* Save the client */
+  i->clients = silc_realloc(i->clients,
+                           (sizeof(*i->clients) * (i->clients_count + 1)));
+  i->clients[i->clients_count] = client_entry;
+  i->clients_count++;
+
+  /* Return if more data is expected */
+  if (cmd->status != SILC_STATUS_OK &&
+      cmd->status != SILC_STATUS_LIST_END) {
+    silc_free(client_id);
+    return;
+  }
+
+  i->completion(i->client, i->conn, i->clients, i->clients_count,
+               i->context);
+
+  silc_free(client_id);
+  silc_free(i->clients);
+  silc_free(i->nickname);
+  silc_free(i);
+}
+
+/* Our own WHOIS reply processor. */
+
+SILC_CLIENT_CMD_FUNC(get_client_callback_w)
+{
+  SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
+  SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
+
+  SILC_LOG_DEBUG(("Start"));
+
+  if (!silc_command_get_status(cmd->payload, NULL, NULL)) {
+    if (SILC_STATUS_IS_ERROR(cmd->status))
+      goto out;
+    if (cmd->status == SILC_STATUS_LIST_END)
+      goto out;
+    goto err;
+  }
+
+  /* Save WHOIS info */
+  silc_client_command_reply_whois_save(cmd, cmd->status, FALSE);
+
+  /* Call pending completion for each reply */
+  if (cmd->status != SILC_STATUS_OK &&
+      cmd->status != SILC_STATUS_LIST_END) {
+    if (cmd->callbacks[0].callback)
+      (*cmd->callbacks[0].callback)(cmd->callbacks[0].context, cmd);
+    silc_client_command_reply_free(cmd);
+    return;
+  }
+
+ out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
+
+ err:
+  /* If we received notify for invalid ID we'll remove the ID if we
+     have it cached. */
+  if (cmd->error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
+    SilcClientEntry client_entry;
+    SilcUInt32 tmp_len;
+    unsigned char *tmp =
+      silc_argument_get_arg_type(silc_command_get_args(cmd->payload),
+                                2, &tmp_len);
+    if (tmp) {
+      SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
+      if (client_id) {
+       client_entry = silc_client_get_client_by_id(cmd->client, conn,
+                                                   client_id);
+       if (client_entry)
+         silc_client_del_client(cmd->client, conn, client_entry);
+       silc_free(client_id);
+      }
+    }
+  }
+
+  /* Unregister this command reply */
+  silc_client_command_unregister(cmd->client, SILC_COMMAND_WHOIS,
+                                NULL, silc_client_command_reply_whois_i,
+                                cmd->ident);
+  silc_client_command_reply_free(cmd);
+}
+
 /* Finds client entry or entries by the `nickname' and `server'. The
    completion callback will be called when the client entries has been found.
 
@@ -166,18 +285,17 @@ void silc_client_get_clients_i(SilcClient client,
 {
   GetClientInternal i;
   int len;
-  char *userhost;
+  char *userhost = NULL;
 
   assert(client && conn);
 
-  if (!nickname)
+  if (!nickname && !attributes)
     return;
 
   i = silc_calloc(1, sizeof(*i));
   i->client = client;
   i->conn = conn;
-  i->nickname = strdup(nickname);
-  i->server = server ? strdup(server) : NULL;
+  i->nickname = nickname ? strdup(nickname) : NULL;
   i->completion = completion;
   i->context = context;
 
@@ -187,7 +305,7 @@ void silc_client_get_clients_i(SilcClient client,
     silc_strncat(userhost, len, nickname, strlen(nickname));
     silc_strncat(userhost, len, "@", 1);
     silc_strncat(userhost, len, server, strlen(server));
-  } else {
+  } else if (nickname) {
     userhost = silc_memdup(nickname, strlen(nickname));
   }
 
@@ -200,21 +318,26 @@ void silc_client_get_clients_i(SilcClient client,
     silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY,
                             conn->cmd_ident, 1, 1, userhost,
                             strlen(userhost));
+
+    /* Add pending callback */
+    silc_client_command_pending(conn, command, conn->cmd_ident,
+                               silc_client_command_get_client_callback,
+                               (void *)i);
   } else {
     silc_client_command_register(client, command, NULL, NULL,
-                                silc_client_command_reply_whois_i, 0,
+                                silc_client_command_get_client_callback_w, 0,
                                 ++conn->cmd_ident);
     /* Send the command */
     silc_client_command_send(client, conn, command, conn->cmd_ident, 2,
-                            1, userhost, strlen(userhost),
+                            1, userhost, userhost ? strlen(userhost) : 0,
                             3, attributes ? attributes->data : NULL,
                             attributes ? attributes->len : 0);
-  }
 
-  /* Add pending callback */
-  silc_client_command_pending(conn, command, conn->cmd_ident,
-                             silc_client_command_get_client_callback,
-                             (void *)i);
+    /* Add pending callback */
+    silc_client_command_pending(conn, command, conn->cmd_ident,
+                               silc_client_command_get_client_callback_wc,
+                               (void *)i);
+  }
   silc_free(userhost);
 }
 
@@ -903,6 +1026,8 @@ void silc_client_del_client_entry(SilcClient client,
   silc_free(client_entry->server);
   silc_free(client_entry->id);
   silc_free(client_entry->fingerprint);
+  if (client_entry->public_key)
+    silc_pkcs_public_key_free(client_entry->public_key);
   silc_hash_table_free(client_entry->channels);
   if (client_entry->send_key)
     silc_cipher_free(client_entry->send_key);
@@ -1001,6 +1126,8 @@ bool silc_client_del_channel(SilcClient client, SilcClientConnection conn,
   silc_free(channel->channel_name);
   silc_free(channel->topic);
   silc_free(channel->id);
+  if (channel->founder_key)
+    silc_pkcs_public_key_free(channel->founder_key);
   silc_free(channel->key);
   if (channel->channel_key)
     silc_cipher_free(channel->channel_key);
index 3f337ec99c6dfd7d938e3527c3f9a6a6e62f9d92..21674db82e1c8d7fbe41c33a7a655d444b08a374 100644 (file)
@@ -211,6 +211,7 @@ struct SilcClientEntryStruct {
   SilcDList attrs;             /* Requested Attributes (maybe NULL) */
   unsigned char *fingerprint;  /* Fingerprint of client's public key */
   SilcUInt32 fingerprint_len;  /* Length of the fingerprint */
+  SilcPublicKey public_key;    /* User's public key, may be NULL */
 
   /* Private message keys */
   SilcCipher send_key;         /* Private message key for sending */
@@ -256,6 +257,7 @@ struct SilcChannelEntryStruct {
   SilcChannelID *id;                        /* Channel ID */
   SilcUInt32 mode;                          /* Channel mode, ChannelModes. */
   char *topic;                              /* Current topic, may be NULL */
+  SilcPublicKey founder_key;                /* Founder key, may be NULL */
 
   /* All clients that has joined this channel.  The key to the table is the
      SilcClientEntry and the context is SilcChannelUser context. */