updates.
authorPekka Riikonen <priikone@silcnet.org>
Sun, 27 May 2001 11:04:55 +0000 (11:04 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 27 May 2001 11:04:55 +0000 (11:04 +0000)
17 files changed:
CHANGES
TODO
apps/irssi/config
apps/irssi/default.theme
apps/irssi/src/fe-common/silc/module-formats.c
apps/irssi/src/fe-common/silc/module-formats.h
apps/irssi/src/silc/core/Makefile.am
apps/irssi/src/silc/core/client_ops.c
apps/irssi/src/silc/core/client_ops.h [new file with mode: 0644]
apps/irssi/src/silc/core/clientutil.c
apps/irssi/src/silc/core/clientutil.h
apps/irssi/src/silc/core/module.h
apps/irssi/src/silc/core/silc-channels.c
apps/irssi/src/silc/core/silc-core.c
apps/irssi/src/silc/core/silc-queries.c
apps/irssi/src/silc/core/silc-queries.h
apps/irssi/src/silc/core/silc-servers.c

diff --git a/CHANGES b/CHANGES
index cf2daaaa7bc363955a686103ff58e0984a3c0697..67d656c84e3bf01fbe37dda0a6204b7e53f17db4 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,11 @@
+Sun May 27 12:39:48 EEST 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+       * Fixed the private message sending in the Irssi SILC client,
+         added local command KEY to the Irssi SILC client.
+
+         Added key management and key agreement message formats to the
+         irssi/src/fe-common/silc/module-formats.[ch].
+
 Sat May 26 17:43:42 EEST 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
 
        * Fixed channel joining notify handling, cumode notify handling
diff --git a/TODO b/TODO
index 04e9e8d04fe56ce291ad12b07f8de5deeab3ae0b..60920cdaa24ffa8c2cca10c446ed6cab6aa0cded 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,6 +1,14 @@
 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 Add local commands to list the current server and client public keys
    that the user has.  And a local command to dump the contents of the
    public key to the screen.
index 0d21cd5dbdd6cae81da1f0e9e2d2840c315b282c..38dc7478ba3bf1d5d7b36c705e650cd2a647012c 100644 (file)
@@ -55,6 +55,7 @@ settings = {
     autoclose_windows = "no";
     use_msgs_window = "no";
     autocreate_windows = "no";
+    autocreate_query_level = "none";
   };
   "fe-text" = { topicbar = "no"; mail_counter = "yes"; indent = "8"; };
 };
index 45570475285e3d64b5a58fab9e54fad3df986a8c..321f3bb5e9164c1de9521180856c6a3b83da0016 100644 (file)
@@ -183,13 +183,13 @@ abstracts = {
   # private message from you, $0 = "msg", $1 = target nick
   ownprivmsg = "->*%c$1-%n* %g";
 
+  # private message in query
+  privmsgnick = "*%c$0%n* ";
+
   # own private message in query
-  ownprivmsgnick = "{msgnick  $0-}%g";
+  ownprivmsgnick = "->*%c$0%n* %g$1-";
   ownprivnick = "$0-";
 
-  # private message in query
-  privmsgnick = "{msgnick  $0-%n}";
-
 
   ##
   ## other IRC events
index 4e591058a8a6fb68150000206fda546e9eae2665..70d61a60bea360e416fe269d041eaba82e31ea2e 100644 (file)
@@ -38,7 +38,7 @@ FORMAT_REC fecommon_silc_formats[] = {
        { "ownaction", "{ownaction $0}", 1, { 0 } },
        { "ownnotice", "{ownnotice $0}", 1, { 0 } },
 
-       /* WHOIS and WHOWAS messages */
+       /* WHOIS, WHOWAS and USERS (alias WHO) messages */
        { NULL, "Who Queries", 0 },
 
        { "whois", "{nick $0} {nickhost $1}%: realname : $2", 3, { 0, 0, 0 } },
@@ -46,6 +46,8 @@ FORMAT_REC fecommon_silc_formats[] = {
        { "whois_modes", " modes    : $0", 1, { 0 } },
        { "whois_idle", " idle     : $0", 1, { 0 } },
        { "whowas", "{nick $0} was {nickhost $1} ($2)", 3, { 0, 0, 0 } },
+       { "users_header", "Users on {channelhilight $0}", 1, { 0 } },
+       { "users", " %|{nick $[!20]0} $[!5]1 $2 {comment {hilight $3}}", 4, { 0, 0, 0, 0 } },
 
        /* Key management and key agreement */
        { NULL, "Key Management And Key Agreement", 0 },
@@ -66,5 +68,13 @@ FORMAT_REC fecommon_silc_formats[] = {
        { "key_agreement_failure", "Key agreement failed with {nick $0}", 1, { 0 } },
        { "key_agreement_timeout", "Timeout during key agreement. The key agreement was not performed with {nick $0}", 1, { 0 } },
 
+       /* Key management and key agreement */
+       { NULL, "Misc", 0 },
+
+       { "server_oper", "You are now {hilight server operator}", 0, { 0 } },
+       { "router_oper", "You are now {hilight SILC operator}", 0, { 0 } },
+       { "list_header", "  Channel                              Users   Topic", 0, { 0 } },
+       { "list", "  %|{channelhilight $[36]0} {hilight $[7]1} $2", 3, { 0, 0, 0 } },
+
        { NULL, NULL, 0 }
 };
index c0e9e86c668294cc7116f7730f8a6c4dc99e4a02..640e3e734e5b86e68a7d0f55b820726f4cf683b4 100644 (file)
@@ -42,6 +42,8 @@ enum {
   SILCTXT_WHOIS_MODES,
   SILCTXT_WHOIS_IDLE,
   SILCTXT_WHOWAS_USERINFO,
+  SILCTXT_USERS_HEADER,
+  SILCTXT_USERS,
 
   SILCTXT_FILL_3,
 
@@ -61,6 +63,13 @@ enum {
   SILCTXT_KEY_AGREEMENT_FAILURE,
   SILCTXT_KEY_AGREEMENT_TIMEOUT,
 
+  SILCTXT_FILL_4,
+
+  SILCTXT_SERVER_OPER,
+  SILCTXT_ROUTER_OPER,
+  SILCTXT_LIST_HEADER,
+  SILCTXT_LIST,
+
 };
 
 extern FORMAT_REC fecommon_silc_formats[];
index 387d87fed4479a6155bd0fbf18921363e4aabf1d..039d40577e7b52ca9b2b6e2ceb27caebfac42001 100644 (file)
@@ -24,6 +24,7 @@ INCLUDES = \
 noinst_LIBRARIES=libsilc_core.a
 
 libsilc_core_a_SOURCES = \
+       client_ops.c \
        clientutil.c \
        clientconfig.c \
        silc-channels.c \
@@ -35,6 +36,9 @@ libsilc_core_a_SOURCES = \
 
 noinst_HEADERS = \
        module.h \
+       client_ops.h \
+       clientutil.h \
+       clientconfig.h \
        silc-channels.h \
        silc-core.h \
        silc-nicklist.h \
index ca4f64317649bcccf4b2bdf4efdd94c9da0698e1..f609dcee1c45b14dbb2d611f9c4ee5b335799406 100644 (file)
@@ -519,14 +519,11 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
     {
       char *topic, *name;
       int usercount;
-      unsigned char buf[256], tmp[16];
-      int i, len;
+      char users[20];
       
       if (!success)
        return;
       
-      /* XXX should use irssi routines */
-      
       (void)va_arg(vp, SilcChannelEntry);
       name = va_arg(vp, char *);
       topic = va_arg(vp, char *);
@@ -534,35 +531,13 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
       
       if (status == SILC_STATUS_LIST_START ||
          status == SILC_STATUS_OK)
-       silc_say(client, conn, 
-                "  Channel                                  Users     Topic");
-      
-      memset(buf, 0, sizeof(buf));
-      strncat(buf, "  ", 2);
-      len = strlen(name);
-      strncat(buf, name, len > 40 ? 40 : len);
-      if (len < 40)
-       for (i = 0; i < 40 - len; i++)
-         strcat(buf, " ");
-      strcat(buf, " ");
-      
-      memset(tmp, 0, sizeof(tmp));
-      if (usercount) {
-       snprintf(tmp, sizeof(tmp), "%d", usercount);
-       strcat(buf, tmp);
-      }
-      len = strlen(tmp);
-      if (len < 10)
-       for (i = 0; i < 10 - len; i++)
-         strcat(buf, " ");
-      strcat(buf, " ");
-      
-      if (topic) {
-       len = strlen(topic);
-       strncat(buf, topic, len);
-      }
-      
-      silc_say(client, conn, "%s", buf);
+       printformat_module("fe-common/silc", server, NULL,
+                          MSGLEVEL_CRAP, SILCTXT_LIST_HEADER);
+
+      snprintf(users, sizeof(users) - 1, "%d", usercount);
+      printformat_module("fe-common/silc", server, NULL,
+                        MSGLEVEL_CRAP, SILCTXT_LIST,
+                        name, users, topic ? topic : "");
     }
     break;
     
@@ -580,88 +555,50 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
     break;
     
   case SILC_COMMAND_OPER:
-    silc_say(client, conn, "You are now server operator");
+    printformat_module("fe-common/silc", server, NULL,
+                      MSGLEVEL_CRAP, SILCTXT_SERVER_OPER);
     break;
     
   case SILC_COMMAND_SILCOPER:
-    silc_say(client, conn, "You are now SILC operator");
+    printformat_module("fe-common/silc", server, NULL,
+                      MSGLEVEL_CRAP, SILCTXT_ROUTER_OPER);
     break;
     
   case SILC_COMMAND_USERS: 
     {
       SilcChannelEntry channel;
       SilcChannelUser chu;
-      int line_len;
-      char *line;
       
       if (!success)
        return;
       
       channel = va_arg(vp, SilcChannelEntry);
       
-      /* There are two ways to do this, either parse the list (that
-        the command_reply sends (just take it with va_arg()) or just
-        traverse the channel's client list.  I'll do the latter.  See
-        JOIN command reply for example for the list. */
-      
-      silc_say(client, conn, "Users on %s", channel->channel_name);
-       
-      line = silc_calloc(1024, sizeof(*line));
-      line_len = 1024;
+      printformat_module("fe-common/silc", server, channel->channel_name,
+                        MSGLEVEL_CRAP, SILCTXT_USERS_HEADER,
+                        channel->channel_name);
+
       silc_list_start(channel->clients);
       while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
        SilcClientEntry e = chu->client;
-       int i, len1;
-       char *m, tmp[80];
-       
-       memset(line, 0, line_len);
-       
-       if (strlen(e->nickname) + strlen(e->server) + 100 > line_len) {
-         silc_free(line);
-         line_len += strlen(e->nickname) + strlen(e->server) + 100;
-         line = silc_calloc(line_len, sizeof(*line));
-       }
-       
-       memset(tmp, 0, sizeof(tmp));
-       m = silc_client_chumode_char(chu->mode);
-       
-       strncat(line, " ", 1);
-       strncat(line, e->nickname, strlen(e->nickname));
-       strncat(line, e->server ? "@" : "", 1);
-       
-       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, " ");
-       }
+       char stat[5], *mode;
        
+       memset(stat, 0, sizeof(stat));
+       mode = silc_client_chumode_char(chu->mode);
        if (e->mode & SILC_UMODE_GONE)
-         strcat(line, "  G");
+         strcat(stat, "G");
        else
-         strcat(line, "  H");
-       strcat(tmp, m ? m : "");
-       strncat(line, tmp, strlen(tmp));
-       
-       if (strlen(tmp) < 5)
-         for (i = 0; i < 5 - strlen(tmp); i++)
-           strcat(line, " ");
-       
-       strcat(line, e->username ? e->username : "");
-       
-       silc_say(client, conn, "%s", line);
-       
-       if (m)
-         silc_free(m);
+         strcat(stat, "H");
+       if (mode)
+         strcat(stat, mode);
+
+       printformat_module("fe-common/silc", server, channel->channel_name,
+                          MSGLEVEL_CRAP, SILCTXT_USERS,
+                          e->nickname, stat, e->username, 
+                          e->realname ? e->realname : "");
+       if (mode)
+         silc_free(mode);
       }
-      
-      silc_free(line);
     }
     break;
 
diff --git a/apps/irssi/src/silc/core/client_ops.h b/apps/irssi/src/silc/core/client_ops.h
new file mode 100644 (file)
index 0000000..c92ed02
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+
+  client_ops.h
+
+  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+  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
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+*/
+
+#ifndef CLIENT_OPS_H
+#define CLIENT_OPS_H
+
+void silc_say(SilcClient client, SilcClientConnection conn, char *msg, ...);
+void silc_say_error(char *msg, ...);
+void silc_channel_message(SilcClient client, SilcClientConnection conn,
+                         SilcClientEntry sender, 
+                         SilcChannelEntry channel, 
+                         SilcMessageFlags flags, char *msg);
+void silc_private_message(SilcClient client, SilcClientConnection conn,
+                         SilcClientEntry sender, 
+                         SilcMessageFlags flags, char *msg);
+void silc_notify(SilcClient client, SilcClientConnection conn, 
+                SilcNotifyType type, ...);
+void silc_command(SilcClient client, SilcClientConnection conn, 
+                 SilcClientCommandContext cmd_context, int success,
+                 SilcCommand command);
+void silc_command_reply(SilcClient client, SilcClientConnection conn,
+                       SilcCommandPayload cmd_payload, int success,
+                       SilcCommand command, SilcCommandStatus status, ...);
+void silc_connect(SilcClient client, SilcClientConnection conn, int success);
+void silc_disconnect(SilcClient client, SilcClientConnection conn);
+void silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
+                        SilcAskPassphrase completion, void *context);
+void silc_verify_public_key(SilcClient client, SilcClientConnection conn,
+                           SilcSocketType conn_type, unsigned char *pk, 
+                           uint32 pk_len, SilcSKEPKType pk_type,
+                           SilcVerifyPublicKey completion, void *context);
+int silc_get_auth_method(SilcClient client, SilcClientConnection conn,
+                        char *hostname, uint16 port,
+                        SilcProtocolAuthMeth *auth_meth,
+                        unsigned char **auth_data,
+                        uint32 *auth_data_len);
+void silc_failure(SilcClient client, SilcClientConnection conn, 
+                 SilcProtocol protocol, void *failure);
+int silc_key_agreement(SilcClient client, SilcClientConnection conn,
+                      SilcClientEntry client_entry, char *hostname,
+                      int port,
+                      SilcKeyAgreementCallback *completion,
+                      void **context);
+#endif
index 77607adc6f644c5964424c06b357fb61ec852713..cbd0c1846c8de564f7e6b25c7523ef0a61d82a51 100644 (file)
 #include "fe-common/core/printtext.h"
 #include "fe-common/core/keyboard.h"
 
-/* Asks yes/no from user on the input line. Returns TRUE on "yes" and
-   FALSE on "no". */
-
-void silc_client_ask_yes_no(char *prompt, SIGNAL_FUNC func)
-{
-  keyboard_entry_redirect(func, prompt, 0, NULL);
-}
-
 /* Lists supported (builtin) ciphers */
 
 void silc_client_list_ciphers()
index 7a3b946dccfd0ed053bf45638b9edcd121f865a1..ab7c0208b75654d4c49e3939699e125986d7f055 100644 (file)
@@ -24,7 +24,6 @@
 #include "signals.h"
 
 /* Prototypes */
-void silc_client_ask_yes_no(char *prompt, SIGNAL_FUNC func);
 char *silc_client_get_input(const char *prompt);
 void silc_client_list_ciphers();
 void silc_client_list_hash_funcs();
index aadd81610fd0c7695fd2f628138cdf1e12caf1a6..b3c19a49b4e9e54069c8d33284deee00c32749f2 100644 (file)
@@ -6,6 +6,7 @@
 #undef VERSION
 #include "silcincludes.h"
 #include "clientlibincludes.h"
+#include "client_ops.h"
 #include "silc-core.h"
 
 #define SILC_PROTOCOL (chat_protocol_lookup("SILC"))
index 85255669809a30b43f467da031af41bba6530fca..57678937fe86bfbe5a4289b624fd0c9f36039476 100644 (file)
@@ -545,6 +545,488 @@ static void command_away(const char *data, SILC_SERVER_REC *server,
   /* XXX TODO */
 }
 
+typedef struct {
+  int type;                    /* 1 = msg, 2 = channel */
+  SILC_SERVER_REC *server;
+} *KeyInternal;
+
+static SilcSKEKeyMaterial *curr_key = NULL;
+
+/* Key agreement callback that is called after the key agreement protocol
+   has been performed. This is called also if error occured during the
+   key agreement protocol. The `key' is the allocated key material and
+   the caller is responsible of freeing it. The `key' is NULL if error
+   has occured. The application can freely use the `key' to whatever
+   purpose it needs. See lib/silcske/silcske.h for the definition of
+   the SilcSKEKeyMaterial structure. */
+
+static void keyagr_completion(SilcClient client,
+                             SilcClientConnection conn,
+                             SilcClientEntry client_entry,
+                             SilcKeyAgreementStatus status,
+                             SilcSKEKeyMaterial *key,
+                             void *context)
+{
+  KeyInternal i = (KeyInternal)context;
+
+  curr_key = NULL;
+
+  switch(status) {
+  case SILC_KEY_AGREEMENT_OK:
+    printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
+                      SILCTXT_KEY_AGREEMENT_OK, client_entry->nickname);
+
+    if (i->type == 1) {
+      /* Set the private key for this client */
+      silc_client_del_private_message_key(client, conn, client_entry);
+      silc_client_add_private_message_key_ske(client, conn, client_entry,
+                                             NULL, key);
+      printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
+                        SILCTXT_KEY_AGREEMENT_PRIVMSG, 
+                        client_entry->nickname);
+      silc_ske_free_key_material(key);
+    }
+    
+    break;
+    
+  case SILC_KEY_AGREEMENT_ERROR:
+    printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
+                      SILCTXT_KEY_AGREEMENT_ERROR, client_entry->nickname);
+    break;
+    
+  case SILC_KEY_AGREEMENT_FAILURE:
+    printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
+                      SILCTXT_KEY_AGREEMENT_FAILURE, client_entry->nickname);
+    break;
+    
+  case SILC_KEY_AGREEMENT_TIMEOUT:
+    printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
+                      SILCTXT_KEY_AGREEMENT_TIMEOUT, client_entry->nickname);
+    break;
+    
+  default:
+    break;
+  } 
+
+  if (i)
+    silc_free(i);
+}
+
+/* Local command KEY. This command is used to set and unset private
+   keys for channels, set and unset private keys for private messages
+   with remote clients and to send key agreement requests and
+   negotiate the key agreement protocol with remote client.  The
+   key agreement is supported only to negotiate private message keys,
+   it currently cannot be used to negotiate private keys for channels,
+   as it is not convenient for that purpose. */
+
+typedef struct {
+  SILC_SERVER_REC *server;
+  char *data;
+  WI_ITEM_REC *item;
+} *KeyGetClients;
+
+/* Callback to be called after client information is resolved from the
+   server. */
+
+SILC_CLIENT_CMD_FUNC(key_get_clients)
+{
+  KeyGetClients internal = (KeyGetClients)context;
+  signal_emit("command key", 3, internal->data, internal->server,
+             internal->item);
+  silc_free(internal->data);
+  silc_free(internal);
+}
+
+static void command_key(const char *data, SILC_SERVER_REC *server,
+                       WI_ITEM_REC *item)
+{
+  SilcClientConnection conn = server->conn;
+  SilcClientEntry client_entry = NULL;
+  SilcChannelEntry channel_entry = NULL;
+  uint32 num = 0;
+  char *nickname = NULL, *serv = NULL, *tmp;
+  int command = 0, port = 0, type = 0;
+  char *hostname = NULL;
+  KeyInternal internal = NULL;
+  uint32 argc = 0;
+  unsigned char **argv;
+  uint32 *argv_lens, *argv_types;
+  if (!IS_SILC_SERVER(server) || !server->connected)
+    cmd_return_error(CMDERR_NOT_CONNECTED);
+
+  /* Now parse all arguments */
+  tmp = g_strconcat("KEY", " ", data, NULL);
+  silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 7);
+  g_free(tmp);
+
+  if (argc < 4) {
+    silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
+            "set|unset|agreement|negotiate [<arguments>]");
+    return;
+  }
+
+  /* Get type */
+  if (!strcasecmp(argv[1], "msg"))
+    type = 1;
+  if (!strcasecmp(argv[1], "channel"))
+    type = 2;
+
+  if (type == 0) {
+    silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
+            "set|unset|agreement|negotiate [<arguments>]");
+    return;
+  }
+
+  if (type == 1) {
+    if (argv[2][0] == '*') {
+      nickname = "*";
+    } else {
+      /* Parse the typed nickname. */
+      if (!silc_parse_nickname(argv[2], &nickname, &serv, &num)) {
+       silc_say(silc_client, conn, "Bad nickname");
+       return;
+      }
+      
+      /* Find client entry */
+      client_entry = silc_idlist_get_client(silc_client, conn, nickname, 
+                                           serv, num, TRUE);
+      if (!client_entry) {
+       KeyGetClients inter = silc_calloc(1, sizeof(*inter));
+       inter->server = server;
+       inter->data = strdup(data);
+       inter->item = item;
+
+       /* Client entry not found, it was requested thus mark this to be
+          pending command. */
+       silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, 
+                                   conn->cmd_ident, 
+                                   NULL, silc_client_command_key_get_clients, 
+                                   inter);
+       goto out;
+      }
+    }
+  }
+
+  if (type == 2) {
+    /* Get channel entry */
+    char *name;
+
+    if (argv[2][0] == '*') {
+      if (!conn->current_channel) {
+       if (nickname)
+         silc_free(nickname);
+       if (serv)
+         silc_free(serv);
+       cmd_return_error(CMDERR_NOT_JOINED);
+      }
+      name = conn->current_channel->channel_name;
+    } else {
+      name = argv[2];
+    }
+
+    channel_entry = silc_client_get_channel(silc_client, conn, name);
+    if (!channel_entry) {
+      if (nickname)
+       silc_free(nickname);
+      if (serv)
+       silc_free(serv);
+      cmd_return_error(CMDERR_NOT_JOINED);
+    }
+  }
+
+  /* Set command */
+  if (!strcasecmp(argv[3], "set")) {
+    command = 1;
+
+    if (argc == 4) {
+      if (curr_key && type == 1 && client_entry) {
+       silc_client_del_private_message_key(silc_client, conn, client_entry);
+       silc_client_add_private_message_key_ske(silc_client, conn, 
+                                               client_entry, NULL, curr_key);
+       goto out;
+      }
+    }
+
+    if (argc >= 5) {
+      if (type == 1 && client_entry) {
+       /* Set private message key */
+       
+       silc_client_del_private_message_key(silc_client, conn, client_entry);
+
+       if (argc >= 6)
+         silc_client_add_private_message_key(silc_client, conn, client_entry,
+                                             argv[5], argv[4],
+                                             argv_lens[4],
+                                             (argv[4][0] == '*' ?
+                                              TRUE : FALSE));
+       else
+         silc_client_add_private_message_key(silc_client, conn, client_entry,
+                                             NULL, argv[4],
+                                             argv_lens[4],
+                                             (argv[4][0] == '*' ?
+                                              TRUE : FALSE));
+
+       /* Send the key to the remote client so that it starts using it
+          too. */
+       silc_client_send_private_message_key(silc_client, conn, 
+                                            client_entry, TRUE);
+      } else if (type == 2) {
+       /* Set private channel key */
+       char *cipher = NULL, *hmac = NULL;
+
+       if (!(channel_entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
+         printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
+                            SILCTXT_CH_PRIVATE_KEY_NOMODE, 
+                            channel_entry->channel_name);
+         goto out;
+       }
+
+       if (argc >= 6)
+         cipher = argv[5];
+       if (argc >= 7)
+         hmac = argv[6];
+
+       if (!silc_client_add_channel_private_key(silc_client, conn, 
+                                                channel_entry,
+                                                cipher, hmac,
+                                                argv[4],
+                                                argv_lens[4])) {
+         printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
+                            SILCTXT_CH_PRIVATE_KEY_ERROR, 
+                            channel_entry->channel_name);
+         goto out;
+       }
+
+       printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
+                          SILCTXT_CH_PRIVATE_KEY_ADD, 
+                          channel_entry->channel_name);
+      }
+    }
+
+    goto out;
+  }
+  
+  /* Unset command */
+  if (!strcasecmp(argv[3], "unset")) {
+    command = 2;
+
+    if (type == 1 && client_entry) {
+      /* Unset private message key */
+      silc_client_del_private_message_key(silc_client, conn, client_entry);
+    } else if (type == 2) {
+      /* Unset channel key(s) */
+      SilcChannelPrivateKey *keys;
+      uint32 keys_count;
+      int number;
+
+      if (argc == 4)
+       silc_client_del_channel_private_keys(silc_client, conn, 
+                                            channel_entry);
+
+      if (argc > 4) {
+       number = atoi(argv[4]);
+       keys = silc_client_list_channel_private_keys(silc_client, conn, 
+                                                    channel_entry,
+                                                    &keys_count);
+       if (!keys)
+         goto out;
+
+       if (!number || number > keys_count) {
+         silc_client_free_channel_private_keys(keys, keys_count);
+         goto out;
+       }
+
+       silc_client_del_channel_private_key(silc_client, conn, channel_entry,
+                                           keys[number - 1]);
+       silc_client_free_channel_private_keys(keys, keys_count);
+      }
+
+      goto out;
+    }
+  }
+
+  /* List command */
+  if (!strcasecmp(argv[3], "list")) {
+    command = 3;
+
+    if (type == 1) {
+      SilcPrivateMessageKeys keys;
+      uint32 keys_count;
+      int k, i, len;
+      char buf[1024];
+
+      keys = silc_client_list_private_message_keys(silc_client, conn, 
+                                                  &keys_count);
+      if (!keys)
+       goto out;
+
+      /* list the private message key(s) */
+      if (nickname[0] == '*') {
+       printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
+                          SILCTXT_PRIVATE_KEY_LIST);
+       for (k = 0; k < keys_count; k++) {
+         memset(buf, 0, sizeof(buf));
+         strncat(buf, "  ", 2);
+         len = strlen(keys[k].client_entry->nickname);
+         strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
+         if (len < 30)
+           for (i = 0; i < 30 - len; i++)
+             strcat(buf, " ");
+         strcat(buf, " ");
+         
+         len = strlen(keys[k].cipher);
+         strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
+         if (len < 14)
+           for (i = 0; i < 14 - len; i++)
+             strcat(buf, " ");
+         strcat(buf, " ");
+
+         if (keys[k].key)
+           strcat(buf, "<hidden>");
+         else
+           strcat(buf, "*generated*");
+
+         silc_say(silc_client, conn, "%s", buf);
+       }
+      } else {
+       printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
+                          SILCTXT_PRIVATE_KEY_LIST_NICK,
+                          client_entry->nickname);
+       for (k = 0; k < keys_count; k++) {
+         if (keys[k].client_entry != client_entry)
+           continue;
+
+         memset(buf, 0, sizeof(buf));
+         strncat(buf, "  ", 2);
+         len = strlen(keys[k].client_entry->nickname);
+         strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
+         if (len < 30)
+           for (i = 0; i < 30 - len; i++)
+             strcat(buf, " ");
+         strcat(buf, " ");
+         
+         len = strlen(keys[k].cipher);
+         strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
+         if (len < 14)
+           for (i = 0; i < 14 - len; i++)
+             strcat(buf, " ");
+         strcat(buf, " ");
+
+         if (keys[k].key)
+           strcat(buf, "<hidden>");
+         else
+           strcat(buf, "*generated*");
+
+         silc_say(silc_client, conn, "%s", buf);
+       }
+      }
+
+      silc_client_free_private_message_keys(keys, keys_count);
+    } else if (type == 2) {
+      SilcChannelPrivateKey *keys;
+      uint32 keys_count;
+      int k, i, len;
+      char buf[1024];
+
+      keys = silc_client_list_channel_private_keys(silc_client, conn, 
+                                                  channel_entry,
+                                                  &keys_count);
+      if (!keys)
+       goto out;
+      
+      printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
+                        SILCTXT_CH_PRIVATE_KEY_LIST,
+                        channel_entry->channel_name);
+      for (k = 0; k < keys_count; k++) {
+       memset(buf, 0, sizeof(buf));
+       strncat(buf, "  ", 2);
+
+       len = strlen(keys[k]->cipher->cipher->name);
+       strncat(buf, keys[k]->cipher->cipher->name, len > 16 ? 16 : len);
+       if (len < 16)
+         for (i = 0; i < 16 - len; i++)
+           strcat(buf, " ");
+       strcat(buf, " ");
+       
+       len = strlen(keys[k]->hmac->hmac->name);
+       strncat(buf, keys[k]->hmac->hmac->name, len > 16 ? 16 : len);
+       if (len < 16)
+         for (i = 0; i < 16 - len; i++)
+           strcat(buf, " ");
+       strcat(buf, " ");
+       
+       strcat(buf, "<hidden>");
+
+       silc_say(silc_client, conn, "%s", buf);
+      }
+      
+      silc_client_free_channel_private_keys(keys, keys_count);
+    }
+
+    goto out;
+  }
+
+  /* Send command is used to send key agreement */
+  if (!strcasecmp(argv[3], "agreement")) {
+    command = 4;
+
+    if (argc >= 5)
+      hostname = argv[4];
+    if (argc >= 6)
+      port = atoi(argv[5]);
+
+    internal = silc_calloc(1, sizeof(*internal));
+    internal->type = type;
+    internal->server = server;
+  }
+
+  /* Start command is used to start key agreement (after receiving the
+     key_agreement client operation). */
+  if (!strcasecmp(argv[3], "negotiate")) {
+    command = 5;
+
+    if (argc >= 5)
+      hostname = argv[4];
+    if (argc >= 6)
+      port = atoi(argv[5]);
+
+    internal = silc_calloc(1, sizeof(*internal));
+    internal->type = type;
+    internal->server = server;
+  }
+
+  if (command == 0) {
+    silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
+            "set|unset|agreement|negotiate [<arguments>]");
+    goto out;
+  }
+
+  if (command == 4 && client_entry) {
+    printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
+                      SILCTXT_KEY_AGREEMENT, argv[2]);
+    silc_client_send_key_agreement(silc_client, conn, client_entry, hostname, 
+                                  port, 120, keyagr_completion, internal);
+    goto out;
+  }
+
+  if (command == 5 && client_entry && hostname) {
+    printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
+                      SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
+    silc_client_perform_key_agreement(silc_client, conn, client_entry, 
+                                     hostname, port, keyagr_completion, 
+                                     internal);
+    goto out;
+  }
+
+ out:
+  if (nickname)
+    silc_free(nickname);
+  if (serv)
+    silc_free(serv);
+}
+
 void silc_channels_init(void)
 {
   signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
@@ -570,6 +1052,7 @@ void silc_channels_init(void)
   command_bind("me", MODULE_NAME, (SIGNAL_FUNC) command_me);
   command_bind("notice", MODULE_NAME, (SIGNAL_FUNC) command_notice);
   command_bind("away", MODULE_NAME, (SIGNAL_FUNC) command_away);
+  command_bind("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
 
   silc_nicklist_init();
 }
@@ -601,6 +1084,7 @@ void silc_channels_deinit(void)
   command_unbind("me", (SIGNAL_FUNC) command_me);
   command_unbind("notice", (SIGNAL_FUNC) command_notice);
   command_unbind("away", (SIGNAL_FUNC) command_away);
+  command_unbind("key", (SIGNAL_FUNC) command_key);
 
   silc_nicklist_deinit();
 }
index 2b823ed244d920ad43c127bac8647aae11635733..4cfcd54dde5f3f1755130e273b096bf9e0928cf1 100644 (file)
@@ -59,1098 +59,6 @@ SilcSimContext **sims = NULL;
 uint32 sims_count = 0;
 #endif
 
-static void silc_say(SilcClient client, SilcClientConnection conn,
-                    char *msg, ...);
-static void 
-silc_channel_message(SilcClient client, SilcClientConnection conn,
-                    SilcClientEntry sender, SilcChannelEntry channel,
-                    SilcMessageFlags flags, char *msg);
-static void 
-silc_private_message(SilcClient client, SilcClientConnection conn,
-                    SilcClientEntry sender, SilcMessageFlags flags,
-                    char *msg);
-static void silc_notify(SilcClient client, SilcClientConnection conn,
-                       SilcNotifyType type, ...);
-static void 
-silc_connect(SilcClient client, SilcClientConnection conn, int success);
-static void 
-silc_disconnect(SilcClient client, SilcClientConnection conn);
-static void 
-silc_command(SilcClient client, SilcClientConnection conn, 
-            SilcClientCommandContext cmd_context, int success,
-            SilcCommand command);
-static void 
-silc_command_reply(SilcClient client, SilcClientConnection conn,
-                  SilcCommandPayload cmd_payload, int success,
-                  SilcCommand command, SilcCommandStatus status, ...);
-static void 
-silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
-                               SilcSocketType conn_type, unsigned char *pk, 
-                               uint32 pk_len, SilcSKEPKType pk_type,
-                               SilcVerifyPublicKey completion, void *context);
-static void 
-silc_verify_public_key(SilcClient client, SilcClientConnection conn,
-                      SilcSocketType conn_type, unsigned char *pk, 
-                      uint32 pk_len, SilcSKEPKType pk_type,
-                      SilcVerifyPublicKey completion, void *context);
-static void silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
-                               SilcAskPassphrase completion, void *context);
-static int 
-silc_get_auth_method(SilcClient client, SilcClientConnection conn,
-                    char *hostname, uint16 port,
-                    SilcProtocolAuthMeth *auth_meth,
-                    unsigned char **auth_data,
-                    uint32 *auth_data_len);
-static void 
-silc_failure(SilcClient client, SilcClientConnection conn, 
-            SilcProtocol protocol, void *failure);
-static int 
-silc_key_agreement(SilcClient client, SilcClientConnection conn,
-                  SilcClientEntry client_entry, char *hostname,
-                  int port,
-                  SilcKeyAgreementCallback *completion,
-                  void **context);
-
-static void silc_say(SilcClient client, SilcClientConnection conn,
-                    char *msg, ...)
-{
-  SILC_SERVER_REC *server;
-  va_list va;
-  char *str;
-
-  server = conn == NULL ? NULL : conn->context;
-  
-  va_start(va, msg);
-  str = g_strdup_vprintf(msg, va);
-  printtext(server, NULL, MSGLEVEL_CRAP, "%s", str);
-  g_free(str);
-  va_end(va);
-}
-
-static void silc_say_error(char *msg, ...)
-{
-  va_list va;
-  char *str;
-
-  va_start(va, msg);
-  str = g_strdup_vprintf(msg, va);
-  printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "%s", str);
-
-  g_free(str);
-  va_end(va);
-}
-
-/* Message for a channel. The `sender' is the nickname of the sender 
-   received in the packet. The `channel_name' is the name of the channel. */
-
-static void 
-silc_channel_message(SilcClient client, SilcClientConnection conn,
-                    SilcClientEntry sender, SilcChannelEntry channel,
-                    SilcMessageFlags flags, char *msg)
-{
-  SILC_SERVER_REC *server;
-  SILC_NICK_REC *nick;
-  SILC_CHANNEL_REC *chanrec;
-  
-  server = conn == NULL ? NULL : conn->context;
-  chanrec = silc_channel_find_entry(server, channel);
-  
-  nick = silc_nicklist_find(chanrec, sender);
-
-  if (flags & SILC_MESSAGE_FLAG_ACTION)
-    printformat_module("fe-common/silc", server, channel->channel_name,
-                      MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_ACTION, msg);
-  else if (flags & SILC_MESSAGE_FLAG_NOTICE)
-    printformat_module("fe-common/silc", server, channel->channel_name,
-                      MSGLEVEL_NOTICES, SILCTXT_CHANNEL_NOTICE, msg);
-  else
-    signal_emit("message public", 6, server, msg,
-               nick == NULL ? "[<unknown>]" : nick->nick,
-               nick == NULL ? NULL : nick->host,
-               chanrec->name, nick);
-}
-
-/* Private message to the client. The `sender' is the nickname of the
-   sender received in the packet. */
-
-static void 
-silc_private_message(SilcClient client, SilcClientConnection conn,
-                    SilcClientEntry sender, SilcMessageFlags flags,
-                         char *msg)
-{
-  SILC_SERVER_REC *server;
-  
-  server = conn == NULL ? NULL : conn->context;
-  signal_emit("message private", 4, server, msg,
-             sender->nickname ? sender->nickname : "[<unknown>]",
-             sender->username ? sender->username : NULL);
-}
-
-/* Notify message to the client. The notify arguments are sent in the
-   same order as servers sends them. The arguments are same as received
-   from the server except for ID's.  If ID is received application receives
-   the corresponding entry to the ID. For example, if Client ID is received
-   application receives SilcClientEntry.  Also, if the notify type is
-   for channel the channel entry is sent to application (even if server
-   does not send it). */
-
-typedef struct {
-  int type;
-  const char *name;
-} NOTIFY_REC;
-
-#define MAX_NOTIFY (sizeof(notifies)/sizeof(notifies[0]))
-static NOTIFY_REC notifies[] = {
-  { SILC_NOTIFY_TYPE_NONE,             NULL },
-  { SILC_NOTIFY_TYPE_INVITE,           "invite" },
-  { SILC_NOTIFY_TYPE_JOIN,             "join" },
-  { SILC_NOTIFY_TYPE_LEAVE,            "leave" },
-  { SILC_NOTIFY_TYPE_SIGNOFF,          "signoff" },
-  { SILC_NOTIFY_TYPE_TOPIC_SET,                "topic" },
-  { SILC_NOTIFY_TYPE_NICK_CHANGE,      "nick" },
-  { SILC_NOTIFY_TYPE_CMODE_CHANGE,     "cmode" },
-  { SILC_NOTIFY_TYPE_CUMODE_CHANGE,    "cumode" },
-  { SILC_NOTIFY_TYPE_MOTD,             "motd" },
-  { SILC_NOTIFY_TYPE_CHANNEL_CHANGE,   "channel_change" },
-  { SILC_NOTIFY_TYPE_SERVER_SIGNOFF,   "server_signoff" },
-  { SILC_NOTIFY_TYPE_KICKED,           "kick" },
-  { SILC_NOTIFY_TYPE_KILLED,           "kill" },
-  { SILC_NOTIFY_TYPE_UMODE_CHANGE,      "umode" },
-  { SILC_NOTIFY_TYPE_BAN,               "ban" },
-};
-
-static void silc_notify(SilcClient client, SilcClientConnection conn,
-                       SilcNotifyType type, ...)
-{
-  SILC_SERVER_REC *server;
-  va_list va;
-  
-  server = conn == NULL ? NULL : conn->context;
-  va_start(va, type);
-  
-  if (type == SILC_NOTIFY_TYPE_NONE) {
-    /* Some generic notice from server */
-    printtext(server, NULL, MSGLEVEL_CRAP, "%s", (char *)va_arg(va, char *));
-  } else if (type < MAX_NOTIFY) {
-    /* Send signal about the notify event */
-    char signal[50];
-    g_snprintf(signal, sizeof(signal), "silc event %s", notifies[type].name);
-    signal_emit(signal, 2, server, va);
-  } else {
-    /* Unknown notify */
-    printtext(server, NULL, MSGLEVEL_CRAP, "Unknown notify type %d", type);
-  }
-
-  va_end(va);
-}
-
-/* Called to indicate that connection was either successfully established
-   or connecting failed.  This is also the first time application receives
-   the SilcClientConnection objecet which it should save somewhere. */
-
-static void 
-silc_connect(SilcClient client, SilcClientConnection conn, int success)
-{
-  SILC_SERVER_REC *server = conn->context;
-
-  if (success) {
-    server->connected = TRUE;
-    signal_emit("event connected", 1, server);
-  } else {
-    server->connection_lost = TRUE;
-    server->conn->context = NULL;
-    server_disconnect(SERVER(server));
-  }
-}
-
-/* Called to indicate that connection was disconnected to the server. */
-
-static void 
-silc_disconnect(SilcClient client, SilcClientConnection conn)
-{
-  SILC_SERVER_REC *server = conn->context;
-
-  server->conn->context = NULL;
-  server->conn = NULL;
-  server->connection_lost = TRUE;
-  server_disconnect(SERVER(server));
-}
-
-/* Command handler. This function is called always in the command function.
-   If error occurs it will be called as well. `conn' is the associated
-   client connection. `cmd_context' is the command context that was
-   originally sent to the command. `success' is FALSE if error occured
-   during command. `command' is the command being processed. It must be
-   noted that this is not reply from server. This is merely called just
-   after application has called the command. Just to tell application
-   that the command really was processed. */
-
-static void 
-silc_command(SilcClient client, SilcClientConnection conn, 
-            SilcClientCommandContext cmd_context, int success,
-            SilcCommand command)
-{
-}
-
-/* Client info resolving callback when JOIN command reply is received.
-   This will cache all users on the channel. */
-
-void silc_client_join_get_users(SilcClient client,
-                               SilcClientConnection conn,
-                               SilcClientEntry *clients,
-                               uint32 clients_count,
-                               void *context)
-{
-  SilcChannelEntry channel = (SilcChannelEntry)context;
-  SilcChannelUser chu;
-  SILC_SERVER_REC *server = conn->context;
-  SILC_CHANNEL_REC *chanrec;
-  SilcClientEntry founder = NULL;
-  NICK_REC *ownnick;
-
-  if (!clients)
-    return;
-
-  chanrec = silc_channel_find(server, channel->channel_name);
-  if (chanrec == NULL)
-    return;
-
-  silc_list_start(channel->clients);
-  while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
-    if (chu->mode & SILC_CHANNEL_UMODE_CHANFO)
-      founder = chu->client;
-    silc_nicklist_insert(chanrec, chu, FALSE);
-  }
-
-  ownnick = NICK(silc_nicklist_find(chanrec, conn->local_entry));
-  nicklist_set_own(CHANNEL(chanrec), ownnick);
-  signal_emit("channel joined", 1, chanrec);
-
-  if (chanrec->topic)
-    printformat_module("fe-common/silc", server, channel->channel_name,
-                      MSGLEVEL_CRAP, SILCTXT_CHANNEL_TOPIC,
-                      channel->channel_name, chanrec->topic);
-
-  fe_channels_nicklist(CHANNEL(chanrec), CHANNEL_NICKLIST_FLAG_ALL);
-
-  if (founder) {
-    if (founder == conn->local_entry)
-      printformat_module("fe-common/silc", 
-                        server, channel->channel_name, MSGLEVEL_CRAP,
-                        SILCTXT_CHANNEL_FOUNDER_YOU,
-                        channel->channel_name);
-    else
-      printformat_module("fe-common/silc", 
-                        server, channel->channel_name, MSGLEVEL_CRAP,
-                        SILCTXT_CHANNEL_FOUNDER,
-                        channel->channel_name, founder->nickname);
-  }
-}
-
-/* Command reply handler. This function is called always in the command reply
-   function. If error occurs it will be called as well. Normal scenario
-   is that it will be called after the received command data has been parsed
-   and processed. The function is used to pass the received command data to
-   the application. 
-
-   `conn' is the associated client connection. `cmd_payload' is the command
-   payload data received from server and it can be ignored. It is provided
-   if the application would like to re-parse the received command data,
-   however, it must be noted that the data is parsed already by the library
-   thus the payload can be ignored. `success' is FALSE if error occured.
-   In this case arguments are not sent to the application. `command' is the
-   command reply being processed. The function has variable argument list
-   and each command defines the number and type of arguments it passes to the
-   application (on error they are not sent). */
-
-static void 
-silc_command_reply(SilcClient client, SilcClientConnection conn,
-                  SilcCommandPayload cmd_payload, int success,
-                  SilcCommand command, SilcCommandStatus status, ...)
-
-{
-  SILC_SERVER_REC *server = conn->context;
-  SILC_CHANNEL_REC *chanrec;
-  va_list vp;
-
-  va_start(vp, status);
-
-  switch(command) {
-  case SILC_COMMAND_WHOIS:
-    {
-      char buf[1024], *nickname, *username, *realname;
-      uint32 idle, mode;
-      SilcBuffer channels;
-      
-      if (status == SILC_STATUS_ERR_NO_SUCH_NICK ||
-         status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
-       char *tmp;
-       tmp = silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
-                                        3, NULL);
-       if (tmp)
-         silc_say_error("%s: %s", tmp, 
-                        silc_client_command_status_message(status));
-       else
-         silc_say_error("%s", silc_client_command_status_message(status));
-       break;
-      }
-      
-      if (!success)
-       return;
-      
-      (void)va_arg(vp, SilcClientEntry);
-      nickname = va_arg(vp, char *);
-      username = va_arg(vp, char *);
-      realname = va_arg(vp, char *);
-      channels = va_arg(vp, SilcBuffer);
-      mode = va_arg(vp, uint32);
-      idle = va_arg(vp, uint32);
-      
-      printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
-                        SILCTXT_WHOIS_USERINFO, nickname, username, 
-                        realname);
-
-      if (channels) {
-       SilcDList list = silc_channel_payload_parse_list(channels);
-       if (list) {
-         SilcChannelPayload entry;
-         memset(buf, 0, sizeof(buf));
-         silc_dlist_start(list);
-         while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
-           char *m = silc_client_chumode_char(silc_channel_get_mode(entry));
-           uint32 name_len;
-           char *name = silc_channel_get_name(entry, &name_len);
-           
-           if (m)
-             strncat(buf, m, strlen(m));
-           strncat(buf, name, name_len);
-           strncat(buf, " ", 1);
-           silc_free(m);
-         }
-
-         printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
-                            SILCTXT_WHOIS_CHANNELS, buf);
-         silc_channel_payload_list_free(list);
-       }
-      }
-      
-      if (mode) {
-       memset(buf, 0, sizeof(buf));
-
-       if ((mode & SILC_UMODE_SERVER_OPERATOR) ||
-           (mode & SILC_UMODE_ROUTER_OPERATOR)) {
-         strcat(buf, (mode & SILC_UMODE_SERVER_OPERATOR) ?
-                "Server Operator " :
-                (mode & SILC_UMODE_ROUTER_OPERATOR) ?
-                "SILC Operator " : "[Unknown mode] ");
-       }
-       if (mode & SILC_UMODE_GONE)
-         strcat(buf, "away");
-
-       printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
-                          SILCTXT_WHOIS_MODES, buf);
-      }
-      
-      if (idle && nickname) {
-       memset(buf, 0, sizeof(buf));
-       snprintf(buf, sizeof(buf) - 1, "%lu %s",
-                idle > 60 ? (idle / 60) : idle,
-                idle > 60 ? "minutes" : "seconds");
-
-       printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
-                          SILCTXT_WHOIS_IDLE, buf);
-      }
-    }
-    break;
-    
-  case SILC_COMMAND_WHOWAS:
-    {
-      char *nickname, *username, *realname;
-      
-      if (status == SILC_STATUS_ERR_NO_SUCH_NICK ||
-         status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
-       char *tmp;
-       tmp = silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
-                                        3, NULL);
-       if (tmp)
-         silc_say_error("%s: %s", tmp, 
-                        silc_client_command_status_message(status));
-       else
-         silc_say_error("%s", silc_client_command_status_message(status));
-       break;
-      }
-      
-      if (!success)
-       return;
-      
-      (void)va_arg(vp, SilcClientEntry);
-      nickname = va_arg(vp, char *);
-      username = va_arg(vp, char *);
-      realname = va_arg(vp, char *);
-      
-      printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
-                        SILCTXT_WHOWAS_USERINFO, nickname, username, 
-                        realname ? realname : "");
-    }
-    break;
-    
-  case SILC_COMMAND_INVITE:
-    {
-      SilcChannelEntry channel;
-      char *invite_list;
-      
-      if (!success)
-       return;
-      
-      /* XXX should use irssi routines */
-      
-      channel = va_arg(vp, SilcChannelEntry);
-      invite_list = va_arg(vp, char *);
-      
-      if (invite_list)
-       silc_say(client, conn, "%s invite list: %s", channel->channel_name,
-                invite_list);
-      else
-       silc_say(client, conn, "%s invite list not set", 
-                channel->channel_name);
-    }
-    break;
-
-  case SILC_COMMAND_JOIN: 
-    {
-      char *channel, *mode, *topic;
-      uint32 modei;
-      SilcChannelEntry channel_entry;
-      SilcBuffer client_id_list;
-      uint32 list_count;
-
-      channel = va_arg(vp, char *);
-      channel_entry = va_arg(vp, SilcChannelEntry);
-      modei = va_arg(vp, uint32);
-      (void)va_arg(vp, uint32);
-      (void)va_arg(vp, unsigned char *);
-      (void)va_arg(vp, unsigned char *);
-      (void)va_arg(vp, unsigned char *);
-      topic = va_arg(vp, char *);
-      (void)va_arg(vp, unsigned char *);
-      list_count = va_arg(vp, uint32);
-      client_id_list = va_arg(vp, SilcBuffer);
-
-      if (!success)
-       return;
-
-      chanrec = silc_channel_find(server, channel);
-      if (chanrec != NULL && !success)
-       channel_destroy(CHANNEL(chanrec));
-      else if (chanrec == NULL && success)
-       chanrec = silc_channel_create(server, channel, TRUE);
-      
-      if (topic) {
-       g_free_not_null(chanrec->topic);
-       chanrec->topic = *topic == '\0' ? NULL : g_strdup(topic);
-       signal_emit("channel topic changed", 1, chanrec);
-      }
-
-      mode = silc_client_chmode(modei, channel_entry);
-      g_free_not_null(chanrec->mode);
-      chanrec->mode = g_strdup(mode == NULL ? "" : mode);
-      signal_emit("channel mode changed", 1, chanrec);
-
-      /* Resolve the client information */
-      silc_client_get_clients_by_list(client, conn, list_count, client_id_list,
-                                     silc_client_join_get_users, 
-                                     channel_entry);
-      break;
-    }
-
-  case SILC_COMMAND_NICK: 
-    {
-      SilcClientEntry client = va_arg(vp, SilcClientEntry);
-      char *old;
-      
-      if (!success)
-       return;
-
-      old = g_strdup(server->nick);
-      server_change_nick(SERVER(server), client->nickname);
-      nicklist_rename_unique(SERVER(server),
-                            server->conn->local_entry, server->nick,
-                            client, client->nickname);
-      
-      signal_emit("message own_nick", 4, server, server->nick, old, "");
-      g_free(old);
-      break;
-    }
-    
-  case SILC_COMMAND_LIST:
-    {
-      char *topic, *name;
-      int usercount;
-      unsigned char buf[256], tmp[16];
-      int i, len;
-      
-      if (!success)
-       return;
-      
-      /* XXX should use irssi routines */
-      
-      (void)va_arg(vp, SilcChannelEntry);
-      name = va_arg(vp, char *);
-      topic = va_arg(vp, char *);
-      usercount = va_arg(vp, int);
-      
-      if (status == SILC_STATUS_LIST_START ||
-         status == SILC_STATUS_OK)
-       silc_say(client, conn, 
-                "  Channel                                  Users     Topic");
-      
-      memset(buf, 0, sizeof(buf));
-      strncat(buf, "  ", 2);
-      len = strlen(name);
-      strncat(buf, name, len > 40 ? 40 : len);
-      if (len < 40)
-       for (i = 0; i < 40 - len; i++)
-         strcat(buf, " ");
-      strcat(buf, " ");
-      
-      memset(tmp, 0, sizeof(tmp));
-      if (usercount) {
-       snprintf(tmp, sizeof(tmp), "%d", usercount);
-       strcat(buf, tmp);
-      }
-      len = strlen(tmp);
-      if (len < 10)
-       for (i = 0; i < 10 - len; i++)
-         strcat(buf, " ");
-      strcat(buf, " ");
-      
-      if (topic) {
-       len = strlen(topic);
-       strncat(buf, topic, len);
-      }
-      
-      silc_say(client, conn, "%s", buf);
-    }
-    break;
-    
-  case SILC_COMMAND_UMODE:
-    {
-      uint32 mode;
-      
-      if (!success)
-       return;
-      
-      mode = va_arg(vp, uint32);
-      
-      /* XXX todo */
-    }
-    break;
-    
-  case SILC_COMMAND_OPER:
-    silc_say(client, conn, "You are now server operator");
-    break;
-    
-  case SILC_COMMAND_SILCOPER:
-    silc_say(client, conn, "You are now SILC operator");
-    break;
-    
-  case SILC_COMMAND_USERS: 
-    {
-      SilcChannelEntry channel;
-      SilcChannelUser chu;
-      int line_len;
-      char *line;
-      
-      if (!success)
-       return;
-      
-      channel = va_arg(vp, SilcChannelEntry);
-      
-      /* There are two ways to do this, either parse the list (that
-        the command_reply sends (just take it with va_arg()) or just
-        traverse the channel's client list.  I'll do the latter.  See
-        JOIN command reply for example for the list. */
-      
-      silc_say(client, conn, "Users on %s", channel->channel_name);
-       
-      line = silc_calloc(1024, sizeof(*line));
-      line_len = 1024;
-      silc_list_start(channel->clients);
-      while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
-       SilcClientEntry e = chu->client;
-       int i, len1;
-       char *m, tmp[80];
-       
-       memset(line, 0, line_len);
-       
-       if (strlen(e->nickname) + strlen(e->server) + 100 > line_len) {
-         silc_free(line);
-         line_len += strlen(e->nickname) + strlen(e->server) + 100;
-         line = silc_calloc(line_len, sizeof(*line));
-       }
-       
-       memset(tmp, 0, sizeof(tmp));
-       m = silc_client_chumode_char(chu->mode);
-       
-       strncat(line, " ", 1);
-       strncat(line, e->nickname, strlen(e->nickname));
-       strncat(line, e->server ? "@" : "", 1);
-       
-       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, " ");
-       }
-       
-       if (e->mode & SILC_UMODE_GONE)
-         strcat(line, "  G");
-       else
-         strcat(line, "  H");
-       strcat(tmp, m ? m : "");
-       strncat(line, tmp, strlen(tmp));
-       
-       if (strlen(tmp) < 5)
-         for (i = 0; i < 5 - strlen(tmp); i++)
-           strcat(line, " ");
-       
-       strcat(line, e->username ? e->username : "");
-       
-       silc_say(client, conn, "%s", line);
-       
-       if (m)
-         silc_free(m);
-      }
-      
-      silc_free(line);
-    }
-    break;
-
-  case SILC_COMMAND_BAN:
-    {
-      SilcChannelEntry channel;
-      char *ban_list;
-      
-      if (!success)
-       return;
-      
-      /* XXX should use irssi routines */
-          
-      channel = va_arg(vp, SilcChannelEntry);
-      ban_list = va_arg(vp, char *);
-      
-      if (ban_list)
-       silc_say(client, conn, "%s ban list: %s", channel->channel_name,
-                ban_list);
-      else
-       silc_say(client, conn, "%s ban list not set", channel->channel_name);
-    }
-    break;
-    
-  case SILC_COMMAND_GETKEY:
-    {
-      SilcIdType id_type;
-      void *entry;
-      SilcPublicKey public_key;
-      unsigned char *pk;
-      uint32 pk_len;
-      
-      id_type = va_arg(vp, uint32);
-      entry = va_arg(vp, void *);
-      public_key = va_arg(vp, SilcPublicKey);
-      
-      pk = silc_pkcs_public_key_encode(public_key, &pk_len);
-      
-      if (id_type == SILC_ID_CLIENT) {
-       silc_verify_public_key_internal(client, conn, SILC_SOCKET_TYPE_CLIENT,
-                                       pk, pk_len, SILC_SKE_PK_TYPE_SILC,
-                                       NULL, NULL);
-      }
-      
-      silc_free(pk);
-    }
-    
-  case SILC_COMMAND_TOPIC:
-    {
-      SilcChannelEntry channel;
-      char *topic;
-      
-      if (!success)
-       return;
-      
-      channel = va_arg(vp, SilcChannelEntry);
-      topic = va_arg(vp, char *);
-      
-      if (topic) {
-       chanrec = silc_channel_find_entry(server, channel);
-       if (chanrec) {
-         g_free_not_null(chanrec->topic);
-         chanrec->topic = *topic == '\0' ? NULL : g_strdup(topic);
-         signal_emit("channel topic changed", 1, chanrec);
-       }
-       printformat_module("fe-common/silc", server, channel->channel_name,
-                          MSGLEVEL_CRAP, SILCTXT_CHANNEL_TOPIC,
-                          channel->channel_name, topic);
-      }
-    }
-    break;
-  }
-
-  va_end(vp);
-}
-
-/* Internal routine to verify public key. If the `completion' is provided
-   it will be called to indicate whether public was verified or not. */
-
-typedef struct {
-  SilcClient client;
-  SilcClientConnection conn;
-  char *filename;
-  char *entity;
-  unsigned char *pk;
-  uint32 pk_len;
-  SilcSKEPKType pk_type;
-  SilcVerifyPublicKey completion;
-  void *context;
-} *PublicKeyVerify;
-
-static void verify_public_key_completion(const char *line, void *context)
-{
-  PublicKeyVerify verify = (PublicKeyVerify)context;
-
-  if (line[0] == 'Y' || line[0] == 'y') {
-    /* Call the completion */
-    if (verify->completion)
-      verify->completion(TRUE, verify->context);
-
-    /* Save the key for future checking */
-    silc_pkcs_save_public_key_data(verify->filename, verify->pk, 
-                                  verify->pk_len, SILC_PKCS_FILE_PEM);
-  } else {
-    /* Call the completion */
-    if (verify->completion)
-      verify->completion(FALSE, verify->context);
-
-    silc_say(verify->client, 
-            verify->conn, "Will not accept the %s key", verify->entity);
-  }
-
-  silc_free(verify->filename);
-  silc_free(verify->entity);
-  silc_free(verify);
-}
-
-static void 
-silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
-                               SilcSocketType conn_type, unsigned char *pk, 
-                               uint32 pk_len, SilcSKEPKType pk_type,
-                               SilcVerifyPublicKey completion, void *context)
-{
-  int i;
-  char file[256], filename[256], *fingerprint;
-  struct passwd *pw;
-  struct stat st;
-  char *entity = ((conn_type == SILC_SOCKET_TYPE_SERVER ||
-                  conn_type == SILC_SOCKET_TYPE_ROUTER) ? 
-                 "server" : "client");
-  PublicKeyVerify verify;
-
-  if (pk_type != SILC_SKE_PK_TYPE_SILC) {
-    silc_say(client, conn, "We don't support %s public key type %d", 
-            entity, pk_type);
-    if (completion)
-      completion(FALSE, context);
-    return;
-  }
-
-  pw = getpwuid(getuid());
-  if (!pw) {
-    if (completion)
-      completion(FALSE, context);
-    return;
-  }
-
-  memset(filename, 0, sizeof(filename));
-  memset(file, 0, sizeof(file));
-
-  if (conn_type == SILC_SOCKET_TYPE_SERVER ||
-      conn_type == SILC_SOCKET_TYPE_ROUTER) {
-    snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, 
-            conn->sock->hostname, conn->sock->port);
-    snprintf(filename, sizeof(filename) - 1, "%s/.silc/%skeys/%s", 
-            pw->pw_dir, entity, file);
-  } else {
-    /* Replace all whitespaces with `_'. */
-    fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
-    for (i = 0; i < strlen(fingerprint); i++)
-      if (fingerprint[i] == ' ')
-       fingerprint[i] = '_';
-    
-    snprintf(file, sizeof(file) - 1, "%skey_%s.pub", entity, fingerprint);
-    snprintf(filename, sizeof(filename) - 1, "%s/.silc/%skeys/%s", 
-            pw->pw_dir, entity, file);
-    silc_free(fingerprint);
-  }
-
-  /* Take fingerprint of the public key */
-  fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
-
-  verify = silc_calloc(1, sizeof(*verify));
-  verify->client = client;
-  verify->conn = conn;
-  verify->filename = strdup(filename);
-  verify->entity = strdup(entity);
-  verify->pk = pk;
-  verify->pk_len = pk_len;
-  verify->pk_type = pk_type;
-  verify->completion = completion;
-  verify->context = context;
-
-  /* Check whether this key already exists */
-  if (stat(filename, &st) < 0) {
-    /* Key does not exist, ask user to verify the key and save it */
-
-    silc_say(client, conn, "Received %s public key", entity);
-    silc_say(client, conn, "Fingerprint for the %s key is", entity);
-    silc_say(client, conn, "%s", fingerprint);
-
-    keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion,
-                           "Would you like to accept the key (y/n)? ", 0,
-                           verify);
-    silc_free(fingerprint);
-    return;
-  } else {
-    /* The key already exists, verify it. */
-    SilcPublicKey public_key;
-    unsigned char *encpk;
-    uint32 encpk_len;
-
-    /* Load the key file */
-    if (!silc_pkcs_load_public_key(filename, &public_key, 
-                                  SILC_PKCS_FILE_PEM))
-      if (!silc_pkcs_load_public_key(filename, &public_key, 
-                                    SILC_PKCS_FILE_BIN)) {
-       silc_say(client, conn, "Received %s public key", entity);
-       silc_say(client, conn, "Fingerprint for the %s key is", entity);
-       silc_say(client, conn, "%s", fingerprint);
-       silc_say(client, conn, "Could not load your local copy of the %s key",
-                entity);
-       keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion,
-                               "Would you like to accept the key "
-                               "anyway (y/n)? ", 0,
-                               verify);
-       silc_free(fingerprint);
-       return;
-      }
-  
-    /* Encode the key data */
-    encpk = silc_pkcs_public_key_encode(public_key, &encpk_len);
-    if (!encpk) {
-      silc_say(client, conn, "Received %s public key", entity);
-      silc_say(client, conn, "Fingerprint for the %s key is", entity);
-      silc_say(client, conn, "%s", fingerprint);
-      silc_say(client, conn, "Your local copy of the %s key is malformed",
-              entity);
-      keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion,
-                             "Would you like to accept the key "
-                             "anyway (y/n)? ", 0,
-                             verify);
-      silc_free(fingerprint);
-      return;
-    }
-
-    /* Compare the keys */
-    if (memcmp(encpk, pk, encpk_len)) {
-      silc_say(client, conn, "Received %s public key", entity);
-      silc_say(client, conn, "Fingerprint for the %s key is", entity);
-      silc_say(client, conn, "%s", fingerprint);
-      silc_say(client, conn, "%s key does not match with your local copy",
-              entity);
-      silc_say(client, conn, 
-              "It is possible that the key has expired or changed");
-      silc_say(client, conn, "It is also possible that some one is performing "
-                      "man-in-the-middle attack");
-
-      /* Ask user to verify the key and save it */
-      keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion,
-                             "Would you like to accept the key "
-                             "anyway (y/n)? ", 0,
-                             verify);
-      silc_free(fingerprint);
-      return;
-    }
-
-    /* Local copy matched */
-    if (completion)
-      completion(TRUE, context);
-    silc_free(fingerprint);
-  }
-}
-
-/* Verifies received public key. The `conn_type' indicates which entity
-   (server, client etc.) has sent the public key. If user decides to trust
-   the key may be saved as trusted public key for later use. The 
-   `completion' must be called after the public key has been verified. */
-
-static void 
-silc_verify_public_key(SilcClient client, SilcClientConnection conn,
-                      SilcSocketType conn_type, unsigned char *pk, 
-                      uint32 pk_len, SilcSKEPKType pk_type,
-                      SilcVerifyPublicKey completion, void *context)
-{
-  silc_verify_public_key_internal(client, conn, conn_type, pk,
-                                 pk_len, pk_type,
-                                 completion, context);
-}
-
-/* Asks passphrase from user on the input line. */
-
-typedef struct {
-  SilcAskPassphrase completion;
-  void *context;
-} *AskPassphrase;
-
-static void ask_passphrase_completion(const char *passphrase, void *context)
-{
-  AskPassphrase p = (AskPassphrase)context;
-  p->completion((unsigned char *)passphrase, 
-               passphrase ? strlen(passphrase) : 0, p->context);
-  silc_free(p);
-}
-
-static void silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
-                               SilcAskPassphrase completion, void *context)
-{
-  AskPassphrase p = silc_calloc(1, sizeof(*p));
-  p->completion = completion;
-  p->context = context;
-
-  keyboard_entry_redirect((SIGNAL_FUNC)ask_passphrase_completion,
-                         "Passphrase: ", ENTRY_REDIRECT_FLAG_HIDDEN, p);
-}
-
-/* Find authentication method and authentication data by hostname and
-   port. The hostname may be IP address as well. The found authentication
-   method and authentication data is returned to `auth_meth', `auth_data'
-   and `auth_data_len'. The function returns TRUE if authentication method
-   is found and FALSE if not. `conn' may be NULL. */
-
-static int 
-silc_get_auth_method(SilcClient client, SilcClientConnection conn,
-                    char *hostname, uint16 port,
-                    SilcProtocolAuthMeth *auth_meth,
-                    unsigned char **auth_data,
-                    uint32 *auth_data_len)
-{
-
-  /* XXX must resolve from configuration whether this connection has
-     any specific authentication data */
-
-  *auth_meth = SILC_AUTH_NONE;
-  *auth_data = NULL;
-  *auth_data_len = 0;
-
-  return TRUE;
-}
-
-/* Notifies application that failure packet was received.  This is called
-   if there is some protocol active in the client.  The `protocol' is the
-   protocol context.  The `failure' is opaque pointer to the failure
-   indication.  Note, that the `failure' is protocol dependant and application
-   must explicitly cast it to correct type.  Usually `failure' is 32 bit
-   failure type (see protocol specs for all protocol failure types). */
-
-static void 
-silc_failure(SilcClient client, SilcClientConnection conn, 
-            SilcProtocol protocol, void *failure)
-{
-  if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
-    SilcSKEStatus status = (SilcSKEStatus)failure;
-    
-    if (status == SILC_SKE_STATUS_BAD_VERSION)
-      silc_say_error("You are running incompatible client version (it may be "
-                    "too old or too new)");
-    if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY)
-      silc_say_error("Server does not support your public key type");
-    if (status == SILC_SKE_STATUS_UNKNOWN_GROUP)
-      silc_say_error("Server does not support one of your proposed KE group");
-    if (status == SILC_SKE_STATUS_UNKNOWN_CIPHER)
-      silc_say_error("Server does not support one of your proposed cipher");
-    if (status == SILC_SKE_STATUS_UNKNOWN_PKCS)
-      silc_say_error("Server does not support one of your proposed PKCS");
-    if (status == SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION)
-      silc_say_error("Server does not support one of your proposed "
-                    "hash function");
-    if (status == SILC_SKE_STATUS_UNKNOWN_HMAC)
-      silc_say_error("Server does not support one of your proposed HMAC");
-    if (status == SILC_SKE_STATUS_INCORRECT_SIGNATURE)
-      silc_say_error("Incorrect signature");
-  }
-
-  if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
-    uint32 err = (uint32)failure;
-
-    if (err == SILC_AUTH_FAILED)
-      silc_say(client, conn, "Authentication failed");
-  }
-}
-
-/* Asks whether the user would like to perform the key agreement protocol.
-   This is called after we have received an key agreement packet or an
-   reply to our key agreement packet. This returns TRUE if the user wants
-   the library to perform the key agreement protocol and FALSE if it is not
-   desired (application may start it later by calling the function
-   silc_client_perform_key_agreement). */
-
-static int 
-silc_key_agreement(SilcClient client, SilcClientConnection conn,
-                  SilcClientEntry client_entry, char *hostname,
-                  int port,
-                  SilcKeyAgreementCallback *completion,
-                  void **context)
-{
-  char host[256];
-
-  /* We will just display the info on the screen and return FALSE and user
-     will have to start the key agreement with a command. */
-
-  if (hostname) {
-    memset(host, 0, sizeof(host));
-    snprintf(host, sizeof(host) - 1, "(%s on port %d)", hostname, port); 
-  }
-
-  silc_say(client, conn, "%s wants to perform key agreement %s",
-          client_entry->nickname, hostname ? host : "");
-
-  *completion = NULL;
-  *context = NULL;
-
-  return FALSE;
-}
-
-/* SILC client operations */
-SilcClientOperations ops = {
-  silc_say,
-  silc_channel_message,
-  silc_private_message,
-  silc_notify,
-  silc_command,
-  silc_command_reply,
-  silc_connect,
-  silc_disconnect,
-  silc_get_auth_method,
-  silc_verify_public_key,
-  silc_ask_passphrase,
-  silc_failure,
-  silc_key_agreement,
-};
-
 static int my_silc_scheduler(void)
 {
   silc_schedule_one(0);
index ef0090e3215f8707207eb516444bde34ab97cc7e..6717cb3685fa9b1f478c8b57d06a6d8eb1df2e12 100644 (file)
 
 #include "silc-queries.h"
 
-QUERY_REC *silc_query_create(SILC_SERVER_REC *server,
+QUERY_REC *silc_query_create(const char *server_tag,
                             const char *nick, int automatic)
 {
   QUERY_REC *rec;
 
-  g_return_val_if_fail(server == NULL || IS_SILC_SERVER(server), NULL);
   g_return_val_if_fail(nick != NULL, NULL);
 
   rec = g_new0(QUERY_REC, 1);
   rec->chat_type = SILC_PROTOCOL;
   rec->name = g_strdup(nick);
-  rec->server = (SERVER_REC *) server;
+  rec->server_tag = g_strdup(server_tag);
   query_init(rec, automatic);
   return rec;
 }
index 2234054130499501055ceeb241fc2201cc2e3311..9443b59cc7e22b379111241afb0f1359c341b156 100644 (file)
@@ -13,7 +13,7 @@
 #define silc_query_find(server, name) \
        query_find(SERVER(server), name)
 
-QUERY_REC *silc_query_create(SILC_SERVER_REC *server,
+QUERY_REC *silc_query_create(const char *server_tag,
                             const char *nick, int automatic);
 void silc_queries_init(void);
 void silc_queries_deinit(void);
index 50233995048e60bd1ed2302fcf3d7876f6fcceae..46ed033064e78c46761a70389a46b3b18ce5ad3e 100644 (file)
@@ -329,6 +329,7 @@ void silc_server_init(void)
   command_bind("users", MODULE_NAME, (SIGNAL_FUNC) command_self);
   command_bind("list", MODULE_NAME, (SIGNAL_FUNC) command_self);
   command_bind("ban", MODULE_NAME, (SIGNAL_FUNC) command_self);
+  command_bind("oper", MODULE_NAME, (SIGNAL_FUNC) command_self);
   command_bind("silcoper", MODULE_NAME, (SIGNAL_FUNC) command_self);
   command_bind("umode", MODULE_NAME, (SIGNAL_FUNC) command_self);
   command_bind("invite", MODULE_NAME, (SIGNAL_FUNC) command_self);
@@ -360,6 +361,7 @@ void silc_server_deinit(void)
   command_unbind("cumode", (SIGNAL_FUNC) command_self);
   command_unbind("users", (SIGNAL_FUNC) command_self);
   command_unbind("list", (SIGNAL_FUNC) command_self);
+  command_unbind("oper", (SIGNAL_FUNC) command_self);
   command_unbind("silcoper", (SIGNAL_FUNC) command_self);
   command_unbind("umode", (SIGNAL_FUNC) command_self);
   command_unbind("invite", (SIGNAL_FUNC) command_self);