updates.
[silc.git] / apps / irssi / src / silc / core / client_ops.c
index ca4f64317649bcccf4b2bdf4efdd94c9da0698e1..79be2e8c7b4eef61cc9c1e9d7bbbcd1e63e4c332 100644 (file)
@@ -45,7 +45,7 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
                                SilcVerifyPublicKey completion, void *context);
 
 void silc_say(SilcClient client, SilcClientConnection conn,
-                    char *msg, ...)
+             SilcClientMessageType type, char *msg, ...)
 {
   SILC_SERVER_REC *server;
   va_list va;
@@ -76,10 +76,9 @@ void silc_say_error(char *msg, ...)
 /* 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. */
 
-void 
-silc_channel_message(SilcClient client, SilcClientConnection conn,
-                    SilcClientEntry sender, SilcChannelEntry channel,
-                    SilcMessageFlags flags, char *msg)
+void silc_channel_message(SilcClient client, SilcClientConnection conn,
+                         SilcClientEntry sender, SilcChannelEntry channel,
+                         SilcMessageFlags flags, char *msg)
 {
   SILC_SERVER_REC *server;
   SILC_NICK_REC *nick;
@@ -87,28 +86,31 @@ silc_channel_message(SilcClient client, SilcClientConnection conn,
   
   server = conn == NULL ? NULL : conn->context;
   chanrec = silc_channel_find_entry(server, channel);
+  if (!chanrec)
+    return;
   
   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);
+                      MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_ACTION, 
+                       nick == NULL ? "[<unknown>]" : nick->nick, msg);
   else if (flags & SILC_MESSAGE_FLAG_NOTICE)
     printformat_module("fe-common/silc", server, channel->channel_name,
-                      MSGLEVEL_NOTICES, SILCTXT_CHANNEL_NOTICE, msg);
+                      MSGLEVEL_NOTICES, SILCTXT_CHANNEL_NOTICE, 
+                       nick == NULL ? "[<unknown>]" : nick->nick, msg);
   else
     signal_emit("message public", 6, server, msg,
                nick == NULL ? "[<unknown>]" : nick->nick,
-               nick == NULL ? NULL : nick->host,
+               nick == NULL ? "" : nick->host == NULL ? "" : nick->host,
                chanrec->name, nick);
 }
 
 /* Private message to the client. The `sender' is the nickname of the
    sender received in the packet. */
 
-void 
-silc_private_message(SilcClient client, SilcClientConnection conn,
-                    SilcClientEntry sender, SilcMessageFlags flags,
+void silc_private_message(SilcClient client, SilcClientConnection conn,
+                         SilcClientEntry sender, SilcMessageFlags flags,
                          char *msg)
 {
   SILC_SERVER_REC *server;
@@ -153,7 +155,7 @@ static NOTIFY_REC notifies[] = {
 };
 
 void silc_notify(SilcClient client, SilcClientConnection conn,
-                       SilcNotifyType type, ...)
+                SilcNotifyType type, ...)
 {
   SILC_SERVER_REC *server;
   va_list va;
@@ -171,7 +173,8 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
     signal_emit(signal, 2, server, va);
   } else {
     /* Unknown notify */
-    printtext(server, NULL, MSGLEVEL_CRAP, "Unknown notify type %d", type);
+    printformat_module("fe-common/silc", server, NULL,
+                      MSGLEVEL_CRAP, SILCTXT_UNKNOWN_NOTIFY, type);
   }
 
   va_end(va);
@@ -181,11 +184,15 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
    or connecting failed.  This is also the first time application receives
    the SilcClientConnection objecet which it should save somewhere. */
 
-void 
-silc_connect(SilcClient client, SilcClientConnection conn, int success)
+void silc_connect(SilcClient client, SilcClientConnection conn, int success)
 {
   SILC_SERVER_REC *server = conn->context;
 
+  if (!server && !success) {
+    silc_client_close_connection(client, NULL, conn);
+    return;
+  }
+
   if (success) {
     server->connected = TRUE;
     signal_emit("event connected", 1, server);
@@ -198,8 +205,7 @@ silc_connect(SilcClient client, SilcClientConnection conn, int success)
 
 /* Called to indicate that connection was disconnected to the server. */
 
-void 
-silc_disconnect(SilcClient client, SilcClientConnection conn)
+void silc_disconnect(SilcClient client, SilcClientConnection conn)
 {
   SILC_SERVER_REC *server = conn->context;
 
@@ -218,21 +224,37 @@ silc_disconnect(SilcClient client, SilcClientConnection conn)
    after application has called the command. Just to tell application
    that the command really was processed. */
 
-void 
-silc_command(SilcClient client, SilcClientConnection conn, 
-            SilcClientCommandContext cmd_context, int success,
-            SilcCommand command)
+void silc_command(SilcClient client, SilcClientConnection conn, 
+                 SilcClientCommandContext cmd_context, int success,
+                 SilcCommand command)
 {
+  SILC_SERVER_REC *server = conn->context;
+
+  if (!success)
+    return;
+
+  switch(command) {
+  case SILC_COMMAND_INVITE:
+    printformat_module("fe-common/silc", server, NULL,
+                      MSGLEVEL_CRAP, SILCTXT_CHANNEL_INVITING,
+                      cmd_context->argv[2], 
+                      (cmd_context->argv[1][0] == '*' ?
+                       (char *)conn->current_channel->channel_name :
+                       (char *)cmd_context->argv[1]));
+    break;
+  default:
+    break;
+  }
 }
 
 /* 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)
+static void silc_client_join_get_users(SilcClient client,
+                                      SilcClientConnection conn,
+                                      SilcClientEntry *clients,
+                                      uint32 clients_count,
+                                      void *context)
 {
   SilcChannelEntry channel = (SilcChannelEntry)context;
   SilcChannelUser chu;
@@ -311,9 +333,10 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
   switch(command) {
   case SILC_COMMAND_WHOIS:
     {
-      char buf[1024], *nickname, *username, *realname;
+      char buf[1024], *nickname, *username, *realname, *nick;
       uint32 idle, mode;
       SilcBuffer channels;
+      SilcClientEntry client_entry;
       
       if (status == SILC_STATUS_ERR_NO_SUCH_NICK ||
          status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
@@ -331,7 +354,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
       if (!success)
        return;
       
-      (void)va_arg(vp, SilcClientEntry);
+      client_entry = va_arg(vp, SilcClientEntry);
       nickname = va_arg(vp, char *);
       username = va_arg(vp, char *);
       realname = va_arg(vp, char *);
@@ -339,9 +362,14 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
       mode = va_arg(vp, uint32);
       idle = va_arg(vp, uint32);
       
+      silc_parse_userfqdn(nickname, &nick, NULL);
+      printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
+                        SILCTXT_WHOIS_USERINFO, nickname, 
+                        client_entry->username, client_entry->hostname,
+                        nick, client_entry->nickname);
       printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
-                        SILCTXT_WHOIS_USERINFO, nickname, username, 
-                        realname);
+                        SILCTXT_WHOIS_REALNAME, realname);
+      silc_free(nick);
 
       if (channels) {
        SilcDList list = silc_channel_payload_parse_list(channels);
@@ -431,21 +459,27 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
     {
       SilcChannelEntry channel;
       char *invite_list;
+      SilcArgumentPayload args;
+      int argc = 0;
       
       if (!success)
        return;
       
-      /* XXX should use irssi routines */
-      
       channel = va_arg(vp, SilcChannelEntry);
       invite_list = va_arg(vp, char *);
-      
+
+      args = silc_command_get_args(cmd_payload);
+      if (args)
+       argc = silc_argument_get_arg_num(args);
+
       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);
+       printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
+                          SILCTXT_CHANNEL_INVITE_LIST, channel->channel_name,
+                          invite_list);
+      else if (argc == 3)
+       printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
+                          SILCTXT_CHANNEL_NO_INVITE_LIST, 
+                          channel->channel_name);
     }
     break;
 
@@ -457,6 +491,9 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
       SilcBuffer client_id_list;
       uint32 list_count;
 
+      if (!success)
+       return;
+
       channel = va_arg(vp, char *);
       channel_entry = va_arg(vp, SilcChannelEntry);
       modei = va_arg(vp, uint32);
@@ -469,22 +506,19 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
       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)
+      if (!chanrec)
        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);
+      mode = silc_client_chmode(modei, 
+                               channel_entry->channel_key->cipher->name,
+                               channel_entry->hmac->hmac->name);
       g_free_not_null(chanrec->mode);
       chanrec->mode = g_strdup(mode == NULL ? "" : mode);
       signal_emit("channel mode changed", 1, chanrec);
@@ -519,14 +553,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 +565,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;
     
@@ -575,93 +584,67 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
       
       mode = va_arg(vp, uint32);
       
-      /* XXX todo */
+      if (mode & SILC_UMODE_SERVER_OPERATOR)
+       printformat_module("fe-common/silc", server, NULL,
+                          MSGLEVEL_CRAP, SILCTXT_SERVER_OPER);
+
+      if (mode & SILC_UMODE_ROUTER_OPERATOR)
+       printformat_module("fe-common/silc", server, NULL,
+                          MSGLEVEL_CRAP, SILCTXT_ROUTER_OPER);
     }
     break;
     
   case SILC_COMMAND_OPER:
-    silc_say(client, conn, "You are now server operator");
+    if (!success)
+      return;
+
+    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");
+    if (!success)
+      return;
+
+    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;
 
@@ -673,16 +656,17 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
       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);
+       printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
+                          SILCTXT_CHANNEL_BAN_LIST, channel->channel_name,
+                          ban_list);
       else
-       silc_say(client, conn, "%s ban list not set", channel->channel_name);
+       printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
+                          SILCTXT_CHANNEL_NO_BAN_LIST, 
+                          channel->channel_name);
     }
     break;
     
@@ -694,20 +678,29 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
       unsigned char *pk;
       uint32 pk_len;
       
+      if (!success)
+       return;
+      
       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,
+
+      if (public_key) {
+       pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+       
+       silc_verify_public_key_internal(client, conn, 
+                                       (id_type == SILC_ID_CLIENT ?
+                                        SILC_SOCKET_TYPE_CLIENT :
+                                        SILC_SOCKET_TYPE_SERVER),
                                        pk, pk_len, SILC_SKE_PK_TYPE_SILC,
                                        NULL, NULL);
+       silc_free(pk);
+      } else {
+       printformat_module("fe-common/silc", server, NULL,
+                          MSGLEVEL_CRAP, SILCTXT_GETKEY_NOKEY);
       }
-      
-      silc_free(pk);
     }
+    break;
     
   case SILC_COMMAND_TOPIC:
     {
@@ -730,9 +723,14 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
        printformat_module("fe-common/silc", server, channel->channel_name,
                           MSGLEVEL_CRAP, SILCTXT_CHANNEL_TOPIC,
                           channel->channel_name, topic);
+      } else {
+       printformat_module("fe-common/silc", server, channel->channel_name,
+                          MSGLEVEL_CRAP, SILCTXT_CHANNEL_TOPIC_NOT_SET,
+                          channel->channel_name);
       }
     }
     break;
+
   }
 
   va_end(vp);
@@ -770,12 +768,13 @@ static void verify_public_key_completion(const char *line, void *context)
     if (verify->completion)
       verify->completion(FALSE, verify->context);
 
-    silc_say(verify->client, 
-            verify->conn, "Will not accept the %s key", verify->entity);
+    printformat_module("fe-common/silc", NULL, NULL,
+                      MSGLEVEL_CRAP, SILCTXT_PUBKEY_DISCARD, verify->entity);
   }
 
   silc_free(verify->filename);
   silc_free(verify->entity);
+  silc_free(verify->pk);
   silc_free(verify);
 }
 
@@ -786,7 +785,7 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
                                SilcVerifyPublicKey completion, void *context)
 {
   int i;
-  char file[256], filename[256], *fingerprint;
+  char file[256], filename[256], *fingerprint, *format;
   struct passwd *pw;
   struct stat st;
   char *entity = ((conn_type == SILC_SOCKET_TYPE_SERVER ||
@@ -795,8 +794,9 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
   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);
+    printformat_module("fe-common/silc", NULL, NULL,
+                      MSGLEVEL_CRAP, SILCTXT_PUBKEY_UNSUPPORTED, 
+                      entity, pk_type);
     if (completion)
       completion(FALSE, context);
     return;
@@ -839,7 +839,8 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
   verify->conn = conn;
   verify->filename = strdup(filename);
   verify->entity = strdup(entity);
-  verify->pk = pk;
+  verify->pk = silc_calloc(pk_len, sizeof(*verify->pk));
+  memcpy(verify->pk, pk, pk_len);
   verify->pk_len = pk_len;
   verify->pk_type = pk_type;
   verify->completion = completion;
@@ -849,13 +850,15 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
   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);
-
+    printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                      SILCTXT_PUBKEY_RECEIVED, entity);
+    printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                      SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint);
+    format = format_get_text("fe-common/silc", NULL, NULL, NULL,
+                            SILCTXT_PUBKEY_ACCEPT);
     keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion,
-                           "Would you like to accept the key (y/n)? ", 0,
-                           verify);
+                           format, 0, verify);
+    g_free(format);
     silc_free(fingerprint);
     return;
   } else {
@@ -869,15 +872,17 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
                                   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);
+       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                          SILCTXT_PUBKEY_RECEIVED, entity);
+       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                          SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint);
+       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                          SILCTXT_PUBKEY_COULD_NOT_LOAD, entity);
+       format = format_get_text("fe-common/silc", NULL, NULL, NULL,
+                                SILCTXT_PUBKEY_ACCEPT_ANYWAY);
        keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion,
-                               "Would you like to accept the key "
-                               "anyway (y/n)? ", 0,
-                               verify);
+                               format, 0, verify);
+       g_free(format);
        silc_free(fingerprint);
        return;
       }
@@ -885,36 +890,40 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
     /* 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);
+      printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                        SILCTXT_PUBKEY_RECEIVED, entity);
+      printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                        SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint);
+      printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                        SILCTXT_PUBKEY_MALFORMED, entity);
+      format = format_get_text("fe-common/silc", NULL, NULL, NULL,
+                              SILCTXT_PUBKEY_ACCEPT_ANYWAY);
       keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion,
-                             "Would you like to accept the key "
-                             "anyway (y/n)? ", 0,
-                             verify);
+                             format, 0, verify);
+      g_free(format);
       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");
+      printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                        SILCTXT_PUBKEY_RECEIVED, entity);
+      printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                        SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint);
+      printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                        SILCTXT_PUBKEY_NO_MATCH, entity);
+      printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                        SILCTXT_PUBKEY_MAYBE_EXPIRED, entity);
+      printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                        SILCTXT_PUBKEY_MITM_ATTACK, entity);
 
       /* Ask user to verify the key and save it */
+      format = format_get_text("fe-common/silc", NULL, NULL, NULL,
+                              SILCTXT_PUBKEY_ACCEPT_ANYWAY);
       keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion,
-                             "Would you like to accept the key "
-                             "anyway (y/n)? ", 0,
-                             verify);
+                             format, 0, verify);
+      g_free(format);
       silc_free(fingerprint);
       return;
     }
@@ -958,7 +967,7 @@ void ask_passphrase_completion(const char *passphrase, void *context)
 }
 
 void silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
-                               SilcAskPassphrase completion, void *context)
+                        SilcAskPassphrase completion, void *context)
 {
   AskPassphrase p = silc_calloc(1, sizeof(*p));
   p->completion = completion;
@@ -968,27 +977,69 @@ void silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
                          "Passphrase: ", ENTRY_REDIRECT_FLAG_HIDDEN, p);
 }
 
+typedef struct {
+  SilcGetAuthMeth completion;
+  void *context;
+} *InternalGetAuthMethod;
+
+/* Callback called when we've received the authentication method information
+   from the server after we've requested it. This will get the authentication
+   data from the user if needed. */
+
+static void silc_get_auth_method_callback(SilcClient client,
+                                         SilcClientConnection conn,
+                                         SilcAuthMethod auth_meth,
+                                         void *context)
+{
+  InternalGetAuthMethod internal = (InternalGetAuthMethod)context;
+
+  switch (auth_meth) {
+  case SILC_AUTH_NONE:
+    /* No authentication required. */
+    (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
+    break;
+  case SILC_AUTH_PASSWORD:
+    /* Do not ask the passphrase from user, the library will ask it if
+       we do not provide it here. */
+    (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
+    break;
+  case SILC_AUTH_PUBLIC_KEY:
+    /* Do not get the authentication data now, the library will generate
+       it using our default key, if we do not provide it here. */
+    /* XXX In the future when we support multiple local keys and multiple
+       local certificates we will need to ask from user which one to use. */
+    (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
+    break;
+  }
+
+  silc_free(internal);
+}
+
 /* 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. */
 
-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_get_auth_method(SilcClient client, SilcClientConnection conn,
+                         char *hostname, uint16 port,
+                         SilcGetAuthMeth completion, void *context)
 {
+  InternalGetAuthMethod internal;
 
   /* 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;
+  /* If we do not have this connection configured by the user in a
+     configuration file then resolve the authentication method from the
+     server for this session. */
+  internal = silc_calloc(1, sizeof(*internal));
+  internal->completion = completion;
+  internal->context = context;
 
-  return TRUE;
+  silc_client_request_authentication_method(client, conn, 
+                                           silc_get_auth_method_callback,
+                                           internal);
 }
 
 /* Notifies application that failure packet was received.  This is called
@@ -998,38 +1049,47 @@ int silc_get_auth_method(SilcClient client, SilcClientConnection conn,
    must explicitly cast it to correct type.  Usually `failure' is 32 bit
    failure type (see protocol specs for all protocol failure types). */
 
-void 
-silc_failure(SilcClient client, SilcClientConnection conn, 
-            SilcProtocol protocol, void *failure)
+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)");
+      printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                        SILCTXT_KE_BAD_VERSION);
     if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY)
-      silc_say_error("Server does not support your public key type");
+      printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                        SILCTXT_KE_UNSUPPORTED_PUBLIC_KEY);
     if (status == SILC_SKE_STATUS_UNKNOWN_GROUP)
-      silc_say_error("Server does not support one of your proposed KE group");
+      printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                        SILCTXT_KE_UNKNOWN_GROUP);
     if (status == SILC_SKE_STATUS_UNKNOWN_CIPHER)
-      silc_say_error("Server does not support one of your proposed cipher");
+      printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                        SILCTXT_KE_UNKNOWN_CIPHER);
     if (status == SILC_SKE_STATUS_UNKNOWN_PKCS)
-      silc_say_error("Server does not support one of your proposed PKCS");
+      printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                        SILCTXT_KE_UNKNOWN_PKCS);
     if (status == SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION)
-      silc_say_error("Server does not support one of your proposed "
-                    "hash function");
+      printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                        SILCTXT_KE_UNKNOWN_HASH_FUNCTION);
     if (status == SILC_SKE_STATUS_UNKNOWN_HMAC)
-      silc_say_error("Server does not support one of your proposed HMAC");
+      printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                        SILCTXT_KE_UNKNOWN_HMAC);
     if (status == SILC_SKE_STATUS_INCORRECT_SIGNATURE)
-      silc_say_error("Incorrect signature");
+      printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                        SILCTXT_KE_INCORRECT_SIGNATURE);
+    if (status == SILC_SKE_STATUS_INVALID_COOKIE)
+      printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                        SILCTXT_KE_INVALID_COOKIE);
   }
 
   if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
     uint32 err = (uint32)failure;
 
     if (err == SILC_AUTH_FAILED)
-      silc_say(client, conn, "Authentication failed");
+      printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                        SILCTXT_AUTH_FAILED);
   }
 }
 
@@ -1046,7 +1106,7 @@ int silc_key_agreement(SilcClient client, SilcClientConnection conn,
                       SilcKeyAgreementCallback *completion,
                       void **context)
 {
-  char portstr[6];
+  char portstr[12];
 
   /* We will just display the info on the screen and return FALSE and user
      will have to start the key agreement with a command. */