Merged silc_1_1_branch to trunk.
[silc.git] / apps / irssi / src / silc / core / client_ops.c
index 67cc80b9d5bf97b67b5c7ed7077571ada94adb0b..38e90d0844553855d9cc38cc2497756754e37975 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 - 2006 Pekka Riikonen
+  Copyright (C) 2001 - 2007 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
@@ -553,7 +553,7 @@ void silc_private_message(SilcClient client, SilcClientConnection conn,
 
   server = conn == NULL ? NULL : conn->context;
   memset(userhost, 0, sizeof(userhost));
-  if (sender->username)
+  if (sender->username[0])
     snprintf(userhost, sizeof(userhost) - 1, "%s@%s",
             sender->username, sender->hostname);
 
@@ -568,11 +568,11 @@ void silc_private_message(SilcClient client, SilcClientConnection conn,
 
   if (flags & SILC_MESSAGE_FLAG_DATA) {
     silc_emit_mime_sig(server,
-               sender->nickname ?
+               sender->nickname[0] ?
                (WI_ITEM_REC *)query_find(SERVER(server), sender->nickname) :
                NULL,
                message, message_len,
-               sender->nickname ? sender->nickname : "[<unknown>]",
+               sender->nickname[0] ? sender->nickname : "[<unknown>]",
                flags & SILC_MESSAGE_FLAG_SIGNED ? verified : -1);
     message = NULL;
   }
@@ -593,24 +593,24 @@ void silc_private_message(SilcClient client, SilcClientConnection conn,
                        cp, message_len);
       if (flags & SILC_MESSAGE_FLAG_SIGNED)
         signal_emit("message silc signed_private_action", 6, server, cp,
-                   sender->nickname ? sender->nickname : "[<unknown>]",
-                   sender->username ? userhost : NULL,
+                   sender->nickname[0] ? sender->nickname : "[<unknown>]",
+                   sender->username[0] ? userhost : NULL,
                    NULL, verified);
       else
         signal_emit("message silc private_action", 5, server, cp,
-                   sender->nickname ? sender->nickname : "[<unknown>]",
-                   sender->username ? userhost : NULL, NULL);
+                   sender->nickname[0] ? sender->nickname : "[<unknown>]",
+                   sender->username[0] ? userhost : NULL, NULL);
       silc_free(dm);
     } else {
       if (flags & SILC_MESSAGE_FLAG_SIGNED)
         signal_emit("message silc signed_private_action", 6, server, message,
-                   sender->nickname ? sender->nickname : "[<unknown>]",
-                   sender->username ? userhost : NULL,
+                   sender->nickname[0] ? sender->nickname : "[<unknown>]",
+                   sender->username[0] ? userhost : NULL,
                    NULL, verified);
       else
         signal_emit("message silc private_action", 5, server, message,
-                   sender->nickname ? sender->nickname : "[<unknown>]",
-                   sender->username ? userhost : NULL, NULL);
+                   sender->nickname[0] ? sender->nickname : "[<unknown>]",
+                   sender->username[0] ? userhost : NULL, NULL);
     }
   else if (flags & SILC_MESSAGE_FLAG_NOTICE)
     if(flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
@@ -625,24 +625,24 @@ void silc_private_message(SilcClient client, SilcClientConnection conn,
                        cp, message_len);
       if (flags & SILC_MESSAGE_FLAG_SIGNED)
         signal_emit("message silc signed_private_notice", 6, server, cp,
-                   sender->nickname ? sender->nickname : "[<unknown>]",
-                   sender->username ? userhost : NULL,
+                   sender->nickname[0] ? sender->nickname : "[<unknown>]",
+                   sender->username[0] ? userhost : NULL,
                    NULL, verified);
       else
         signal_emit("message silc private_notice", 5, server, cp,
-                   sender->nickname ? sender->nickname : "[<unknown>]",
-                   sender->username ? userhost : NULL, NULL);
+                   sender->nickname[0] ? sender->nickname : "[<unknown>]",
+                   sender->username[0] ? userhost : NULL, NULL);
       silc_free(dm);
     } else {
       if (flags & SILC_MESSAGE_FLAG_SIGNED)
         signal_emit("message silc signed_private_notice", 6, server, message,
-                   sender->nickname ? sender->nickname : "[<unknown>]",
-                   sender->username ? userhost : NULL,
+                   sender->nickname[0] ? sender->nickname : "[<unknown>]",
+                   sender->username[0] ? userhost : NULL,
                    NULL, verified);
       else
         signal_emit("message silc private_notice", 5, server, message,
-                   sender->nickname ? sender->nickname : "[<unknown>]",
-                   sender->username ? userhost : NULL, NULL);
+                   sender->nickname[0] ? sender->nickname : "[<unknown>]",
+                   sender->username[0] ? userhost : NULL, NULL);
     }
   else {
     if (flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
@@ -659,24 +659,24 @@ void silc_private_message(SilcClient client, SilcClientConnection conn,
                     cp, message_len);
       if (flags & SILC_MESSAGE_FLAG_SIGNED)
         signal_emit("message signed_private", 5, server, cp,
-                 sender->nickname ? sender->nickname : "[<unknown>]",
-                 sender->username ? userhost : NULL, verified);
+                 sender->nickname[0] ? sender->nickname : "[<unknown>]",
+                 sender->username[0] ? userhost : NULL, verified);
       else
         signal_emit("message private", 4, server, cp,
-                 sender->nickname ? sender->nickname : "[<unknown>]",
-                 sender->username ? userhost : NULL);
+                 sender->nickname[0] ? sender->nickname : "[<unknown>]",
+                 sender->username[0] ? userhost : NULL);
       silc_free(dm);
       return;
     }
 
     if (flags & SILC_MESSAGE_FLAG_SIGNED)
       signal_emit("message signed_private", 5, server, message,
-              sender->nickname ? sender->nickname : "[<unknown>]",
-              sender->username ? userhost : NULL, verified);
+              sender->nickname[0] ? sender->nickname : "[<unknown>]",
+              sender->username[0] ? userhost : NULL, verified);
     else
       signal_emit("message private", 4, server, message,
-              sender->nickname ? sender->nickname : "[<unknown>]",
-              sender->username ? userhost : NULL);
+              sender->nickname[0] ? sender->nickname : "[<unknown>]",
+              sender->username[0] ? userhost : NULL);
   }
 }
 
@@ -704,7 +704,7 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
   char buf[512];
   char *name, *tmp, *cipher, *hmac;
   GSList *list1, *list_tmp;
-  SilcDList chpks;
+  SilcDList chpks, clients;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -729,11 +729,10 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
     name = va_arg(va, char *);
     client_entry = va_arg(va, SilcClientEntry);
 
-    memset(buf, 0, sizeof(buf));
-    snprintf(buf, sizeof(buf) - 1, "%s@%s",
-            client_entry->username, client_entry->hostname);
-    signal_emit("message invite", 4, server, channel ? channel->channel_name :
-               name, client_entry->nickname, buf);
+    silc_snprintf(buf, sizeof(buf) - 1, "%s@%s",
+                 client_entry->username, client_entry->hostname);
+    signal_emit("message invite", 4, server, name,
+               client_entry->nickname, buf);
     break;
 
   case SILC_NOTIFY_TYPE_JOIN:
@@ -749,7 +748,10 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
     if (client_entry == server->conn->local_entry) {
       /* You joined to channel */
       chanrec = silc_channel_find(server, channel->channel_name);
-      if (chanrec != NULL && !chanrec->joined)
+      if (chanrec == NULL)
+       chanrec = silc_channel_create(server, channel->channel_name,
+                                       channel->channel_name, TRUE);
+      if (!chanrec->joined)
        chanrec->entry = channel;
     } else {
       chanrec = silc_channel_find_entry(server, channel);
@@ -761,12 +763,41 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
     }
 
     memset(buf, 0, sizeof(buf));
-    if (client_entry->username)
-    snprintf(buf, sizeof(buf) - 1, "%s@%s",
-            client_entry->username, client_entry->hostname);
+    if (client_entry->username[0])
+      snprintf(buf, sizeof(buf) - 1, "%s@%s",
+              client_entry->username, client_entry->hostname);
     signal_emit("message join", 4, server, channel->channel_name,
                client_entry->nickname,
-               client_entry->username == NULL ? "" : buf);
+               !client_entry->username[0] ? "" : buf);
+
+    /* If there are multiple same nicknames on channel now, tell it to user. */
+    if (client_entry != server->conn->local_entry) {
+      char *nick, tmp[32];
+      int count = 0;
+
+      silc_client_nickname_parse(client, conn, client_entry->nickname, &nick);
+      clients = silc_client_get_clients_local(client, conn, nick, TRUE);
+      if (!clients || silc_dlist_count(clients) < 2) {
+       silc_free(nick);
+       silc_client_list_free(client, conn, clients);
+       break;
+      }
+      silc_dlist_start(clients);
+      while ((client_entry2 = silc_dlist_get(clients)))
+       if (silc_client_on_channel(channel, client_entry2))
+         count++;
+      if (count > 1) {
+       silc_snprintf(tmp, sizeof(tmp), "%d", silc_dlist_count(clients));
+       printformat_module("fe-common/silc", server, channel->channel_name,
+                          MSGLEVEL_CRAP, SILCTXT_CHANNEL_MANY_NICKS,
+                          tmp, nick);
+       printformat_module("fe-common/silc", server, channel->channel_name,
+                          MSGLEVEL_CRAP, SILCTXT_CHANNEL_USER_APPEARS,
+                          buf, client_entry->nickname);
+      }
+      silc_client_list_free(client, conn, clients);
+      silc_free(nick);
+    }
     break;
 
   case SILC_NOTIFY_TYPE_LEAVE:
@@ -784,7 +815,7 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
       snprintf(buf, sizeof(buf) - 1, "%s@%s",
               client_entry->username, client_entry->hostname);
     signal_emit("message part", 5, server, channel->channel_name,
-               client_entry->nickname,  client_entry->username ?
+               client_entry->nickname,  client_entry->username[0] ?
                buf : "", client_entry->nickname);
 
     chanrec = silc_channel_find_entry(server, channel);
@@ -793,6 +824,35 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
       if (nickrec != NULL)
        nicklist_remove(CHANNEL(chanrec), NICK(nickrec));
     }
+
+    /* If there is only one client with this same nickname on channel now
+       change it to the base format if it is formatted nickname. */
+    if (channel) {
+      silc_client_nickname_parse(client, conn, client_entry->nickname, &name);
+      clients = silc_client_get_clients_local(client, conn, name, TRUE);
+      if (!clients || silc_dlist_count(clients) != 2) {
+       silc_free(name);
+       silc_client_list_free(client, conn, clients);
+       break;
+      }
+      silc_dlist_start(clients);
+      client_entry2 = silc_dlist_get(clients);
+      if (client_entry2 == client_entry)
+        client_entry2 = silc_dlist_get(clients);
+      if (silc_client_on_channel(channel, client_entry2)) {
+       silc_snprintf(buf, sizeof(buf), "%s", client_entry2->nickname);
+       silc_client_nickname_format(client, conn, client_entry2, TRUE);
+       if (!silc_utf8_strcasecmp(buf, client_entry2->nickname)) {
+         nicklist_rename_unique(SERVER(server), client_entry2, buf,
+                                client_entry2, client_entry2->nickname);
+         printformat_module("fe-common/silc", server, channel->channel_name,
+                            MSGLEVEL_CRAP, SILCTXT_CHANNEL_USER_APPEARS,
+                            buf, client_entry2->nickname);
+       }
+      }
+      silc_client_list_free(client, conn, clients);
+      silc_free(name);
+    }
     break;
 
   case SILC_NOTIFY_TYPE_SIGNOFF:
@@ -804,23 +864,16 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
 
     client_entry = va_arg(va, SilcClientEntry);
     tmp = va_arg(va, char *);
+    channel = va_arg(va, SilcChannelEntry);
 
-#if 0
     silc_server_free_ftp(server, client_entry);
-#endif
 
-    /* Print only if we have the nickname.  If this cliente has just quit
-       when we were only resolving it, it is possible we don't have the
-       nickname. */
-    if (client_entry->nickname) {
-      memset(buf, 0, sizeof(buf));
-      if (client_entry->username)
-        snprintf(buf, sizeof(buf) - 1, "%s@%s",
-                client_entry->username, client_entry->hostname);
-      signal_emit("message quit", 4, server, client_entry->nickname,
-                 client_entry->username ? buf : "",
-                 tmp ? tmp : "");
-    }
+    memset(buf, 0, sizeof(buf));
+    if (client_entry->username)
+      snprintf(buf, sizeof(buf) - 1, "%s@%s",
+              client_entry->username, client_entry->hostname);
+    signal_emit("message quit", 4, server, client_entry->nickname,
+               client_entry->username[0] ? buf : "", tmp ? tmp : "");
 
     list1 = nicklist_get_same_unique(SERVER(server), client_entry);
     for (list_tmp = list1; list_tmp != NULL; list_tmp =
@@ -830,6 +883,35 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
 
       nicklist_remove(channel, nickrec);
     }
+
+    /* If there is only one client with this same nickname on channel now
+       change it to the base format if it is formatted nickname. */
+    if (channel) {
+      silc_client_nickname_parse(client, conn, client_entry->nickname, &name);
+      clients = silc_client_get_clients_local(client, conn, name, TRUE);
+      if (!clients || silc_dlist_count(clients) != 2) {
+       silc_free(name);
+       silc_client_list_free(client, conn, clients);
+       break;
+      }
+      silc_dlist_start(clients);
+      client_entry2 = silc_dlist_get(clients);
+      if (client_entry2 == client_entry)
+        client_entry2 = silc_dlist_get(clients);
+      if (silc_client_on_channel(channel, client_entry2)) {
+       silc_snprintf(buf, sizeof(buf), "%s", client_entry2->nickname);
+       silc_client_nickname_format(client, conn, client_entry2, TRUE);
+       if (!silc_utf8_strcasecmp(buf, client_entry2->nickname)) {
+         nicklist_rename_unique(SERVER(server), client_entry2, buf,
+                                client_entry2, client_entry2->nickname);
+         printformat_module("fe-common/silc", server, channel->channel_name,
+                            MSGLEVEL_CRAP, SILCTXT_CHANNEL_USER_APPEARS,
+                            buf, client_entry2->nickname);
+       }
+      }
+      silc_client_list_free(client, conn, clients);
+      silc_free(name);
+    }
     break;
 
   case SILC_NOTIFY_TYPE_TOPIC_SET:
@@ -895,19 +977,18 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
     SILC_LOG_DEBUG(("Notify: NICK_CHANGE"));
 
     client_entry = va_arg(va, SilcClientEntry);
-    client_entry2 = va_arg(va, SilcClientEntry);
+    name = va_arg(va, char *);                /* old nickname */
 
-    if (!strcmp(client_entry->nickname, client_entry2->nickname))
+    if (!strcmp(client_entry->nickname, name))
       break;
 
     memset(buf, 0, sizeof(buf));
     snprintf(buf, sizeof(buf) - 1, "%s@%s",
-            client_entry2->username, client_entry2->hostname);
+            client_entry->username, client_entry->hostname);
     nicklist_rename_unique(SERVER(server),
-                          client_entry, client_entry->nickname,
-                          client_entry2, client_entry2->nickname);
-    signal_emit("message nick", 4, server, client_entry2->nickname,
-               client_entry->nickname, buf);
+                          client_entry, name,
+                          client_entry, client_entry->nickname);
+    signal_emit("message nick", 4, server, client_entry->nickname, name, buf);
     break;
 
   case SILC_NOTIFY_TYPE_CMODE_CHANGE:
@@ -1175,9 +1256,7 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
                      "server signoff");
        }
 
-#if 0
        silc_server_free_ftp(server, client_entry);
-#endif
 
        list1 = nicklist_get_same_unique(SERVER(server), client_entry);
        for (list_tmp = list1; list_tmp != NULL; list_tmp =
@@ -1276,7 +1355,7 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
    after application has called the command. Just to tell application
    that the command really was processed. */
 
-static bool cmode_list_chpks = FALSE;
+static SilcBool cmode_list_chpks = FALSE;
 
 void silc_command(SilcClient client, SilcClientConnection conn,
                  SilcBool success, SilcCommand command, SilcStatus status,
@@ -1333,10 +1412,26 @@ void silc_getkey_cb(bool success, void *context)
   char *name = (getkey->id_type == SILC_ID_CLIENT ?
                ((SilcClientEntry)getkey->entry)->nickname :
                ((SilcServerEntry)getkey->entry)->server_name);
+  SilcPublicKey public_key = (getkey->id_type == SILC_ID_CLIENT ?
+                             ((SilcClientEntry)getkey->entry)->public_key :
+                             ((SilcServerEntry)getkey->entry)->public_key);
+  SilcSILCPublicKey silc_pubkey;
+
+  silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key);
 
   if (success) {
-    printformat_module("fe-common/silc", NULL, NULL,
-                      MSGLEVEL_CRAP, SILCTXT_PUBKEY_VERIFIED, entity, name);
+    if (getkey->id_type == SILC_ID_CLIENT)
+      printformat_module("fe-common/silc", NULL, NULL,
+                        MSGLEVEL_CRAP, SILCTXT_PUBKEY_VERIFIED_CLIENT,
+                        name,
+                        silc_pubkey->identifier.realname ?
+                        silc_pubkey->identifier.realname : "",
+                        silc_pubkey->identifier.email ?
+                        silc_pubkey->identifier.email : "");
+    else
+      printformat_module("fe-common/silc", NULL, NULL,
+                        MSGLEVEL_CRAP, SILCTXT_PUBKEY_VERIFIED,
+                        entity, name);
   } else {
     printformat_module("fe-common/silc", NULL, NULL,
                       MSGLEVEL_CRAP, SILCTXT_PUBKEY_NOTVERIFIED,
@@ -1485,7 +1580,7 @@ void silc_command_reply(SilcClient client, SilcClientConnection conn,
   switch(command) {
   case SILC_COMMAND_WHOIS:
     {
-      char buf[1024], *nickname, *username, *realname, nick[128 + 1];
+      char buf[1024], *nickname, *username, *realname, *nick;
       unsigned char *fingerprint;
       SilcUInt32 idle, mode, *user_modes;
       SilcDList channels;
@@ -1526,13 +1621,14 @@ void silc_command_reply(SilcClient client, SilcClientConnection conn,
       user_modes = va_arg(vp, SilcUInt32 *);
       attrs = va_arg(vp, SilcDList);
 
-      silc_parse_userfqdn(nickname, nick, sizeof(nick), NULL, 0);
+      silc_client_nickname_parse(client, conn, client_entry->nickname, &nick);
       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_REALNAME, realname);
+      silc_free(nick);
 
       if (channels && user_modes) {
        SilcChannelPayload entry;
@@ -1640,6 +1736,20 @@ void silc_command_reply(SilcClient client, SilcClientConnection conn,
       NICK_REC *ownnick;
 
       if (SILC_STATUS_IS_ERROR(status)) {
+       if (status == SILC_STATUS_ERR_NO_SUCH_SERVER) {
+         char *tmp = va_arg(vp, char *);
+         if (tmp)
+           silc_say_error("JOIN: %s: %s", tmp,
+                          silc_get_status_message(status));
+         return;
+       }
+       if (status == SILC_STATUS_ERR_NO_SUCH_CHANNEL) {
+         char *tmp = va_arg(vp, char *);
+         if (tmp)
+           silc_say_error("JOIN: %s: %s", tmp,
+                          silc_get_status_message(status));
+         return;
+       }
        silc_say_error("JOIN: %s", silc_get_status_message(status));
        return;
       }
@@ -1686,7 +1796,7 @@ void silc_command_reply(SilcClient client, SilcClientConnection conn,
 
       /* Get user list */
       while (silc_hash_table_get(user_list, NULL, (void *)&chu)) {
-       if (!chu->client->nickname)
+       if (!chu->client->nickname[0])
          continue;
        if (chu->mode & SILC_CHANNEL_UMODE_CHANFO)
          founder = chu->client;
@@ -1905,7 +2015,7 @@ void silc_command_reply(SilcClient client, SilcClientConnection conn,
        SilcClientEntry e = chu->client;
        char stat[5], *mode;
 
-       if (!e->nickname)
+       if (!e->nickname[0])
          continue;
 
        memset(stat, 0, sizeof(stat));
@@ -1932,8 +2042,8 @@ void silc_command_reply(SilcClient client, SilcClientConnection conn,
        printformat_module("fe-common/silc", server, channel->channel_name,
                           MSGLEVEL_CRAP, SILCTXT_USERS,
                           e->nickname, stat,
-                          e->username ? e->username : "",
-                          e->hostname ? e->hostname : "",
+                          e->username[0] ? e->username : "",
+                          e->hostname[0] ? e->hostname : "",
                           e->realname ? e->realname : "");
        if (mode)
          silc_free(mode);
@@ -2220,6 +2330,28 @@ void silc_command_reply(SilcClient client, SilcClientConnection conn,
       silc_free(file);
     }
     break;
+
+  case SILC_COMMAND_KILL:
+    {
+      SilcClientEntry client_entry;
+
+      if (SILC_STATUS_IS_ERROR(status)) {
+       silc_say_error("KILL: %s", silc_get_status_message(status));
+       return;
+      }
+
+      client_entry = va_arg(vp, SilcClientEntry);
+      if (!client_entry || !client_entry->nickname[0])
+       break;
+
+      /* Print this only if the killed client isn't joined on channels.
+        If it is, we receive KILLED notify and we'll print this there. */
+      if (!silc_hash_table_count(client_entry->channels))
+       printformat_module("fe-common/silc", server, NULL,
+                          MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED,
+                          client_entry->nickname,
+                          conn->local_entry->nickname, "");
+    }
   }
 }
 
@@ -2279,6 +2411,7 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
   char file[256], filename[256], filename2[256], *ipf, *hostf = NULL;
   char *fingerprint, *babbleprint, *format;
   SilcPublicKey local_pubkey;
+  SilcSILCPublicKey silc_pubkey;
   SilcUInt16 port;
   const char *hostname, *ip;
   unsigned char *pk;
@@ -2307,10 +2440,13 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
     return;
   }
 
+  silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key);
+
   pw = getpwuid(getuid());
   if (!pw) {
     if (completion)
       completion(FALSE, context);
+    silc_free(pk);
     return;
   }
 
@@ -2382,6 +2518,13 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
     printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
                       SILCTXT_PUBKEY_RECEIVED,verify->entity_name ?
                       verify->entity_name : entity);
+    if (conn_type == SILC_CONN_CLIENT && name &&
+       silc_pubkey->identifier.realname)
+      printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
+                        SILCTXT_PUBKEY_RECEIVED_CLIENT, name,
+                        silc_pubkey->identifier.realname,
+                        silc_pubkey->identifier.email ?
+                        silc_pubkey->identifier.email : "");
     printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
                       SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint);
     printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
@@ -2392,6 +2535,8 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
                            format, 0, verify);
     g_free(format);
     silc_free(fingerprint);
+    silc_free(babbleprint);
+    silc_free(pk);
     return;
   } else {
     /* The key already exists, verify it. */
@@ -2404,6 +2549,13 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
                         SILCTXT_PUBKEY_RECEIVED,verify->entity_name ?
                         verify->entity_name : entity);
+      if (conn_type == SILC_CONN_CLIENT && name &&
+         silc_pubkey->identifier.realname)
+       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
+                          SILCTXT_PUBKEY_RECEIVED_CLIENT, name,
+                          silc_pubkey->identifier.realname,
+                          silc_pubkey->identifier.email ?
+                          silc_pubkey->identifier.email : "");
       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
                         SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint);
       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
@@ -2416,6 +2568,8 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
                              format, 0, verify);
       g_free(format);
       silc_free(fingerprint);
+      silc_free(babbleprint);
+      silc_free(pk);
       return;
     }
 
@@ -2425,6 +2579,13 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
                         SILCTXT_PUBKEY_RECEIVED,verify->entity_name ?
                         verify->entity_name : entity);
+      if (conn_type == SILC_CONN_CLIENT && name &&
+         silc_pubkey->identifier.realname)
+       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
+                          SILCTXT_PUBKEY_RECEIVED_CLIENT, name,
+                          silc_pubkey->identifier.realname,
+                          silc_pubkey->identifier.email ?
+                          silc_pubkey->identifier.email : "");
       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
                         SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint);
       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
@@ -2437,14 +2598,24 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
                              format, 0, verify);
       g_free(format);
       silc_free(fingerprint);
+      silc_free(babbleprint);
+      silc_free(pk);
       return;
     }
+    silc_pkcs_public_key_free(local_pubkey);
 
     /* Compare the keys */
     if (memcmp(encpk, pk, encpk_len)) {
       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
                         SILCTXT_PUBKEY_RECEIVED,verify->entity_name ?
                         verify->entity_name : entity);
+      if (conn_type == SILC_CONN_CLIENT && name &&
+         silc_pubkey->identifier.realname)
+       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
+                          SILCTXT_PUBKEY_RECEIVED_CLIENT, name,
+                          silc_pubkey->identifier.realname,
+                          silc_pubkey->identifier.email ?
+                          silc_pubkey->identifier.email : "");
       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
                         SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint);
       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
@@ -2463,7 +2634,9 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
                              format, 0, verify);
       g_free(format);
       silc_free(fingerprint);
+      silc_free(babbleprint);
       silc_free(encpk);
+      silc_free(pk);
       return;
     }
 
@@ -2472,10 +2645,12 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
       completion(TRUE, context);
     silc_free(encpk);
     silc_free(fingerprint);
+    silc_free(babbleprint);
     silc_free(verify->filename);
     silc_free(verify->entity);
     silc_free(verify->entity_name);
     silc_free(verify);
+    silc_free(pk);
   }
 }
 
@@ -2525,82 +2700,60 @@ void silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
 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. */
+} *GetAuthMethod;
 
-static void silc_get_auth_method_callback(SilcClient client,
-                                         SilcClientConnection conn,
-                                         SilcAuthMethod auth_meth,
-                                         void *context)
+static void silc_get_auth_ask_passphrase(const unsigned char *passphrase,
+                                        SilcUInt32 passphrase_len,
+                                        void *context)
 {
-  InternalGetAuthMethod internal = (InternalGetAuthMethod)context;
-
-  SILC_LOG_DEBUG(("Start"));
-
-  switch (auth_meth) {
-  case SILC_AUTH_NONE:
-    /* No authentication required. */
-    (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
-    break;
-  case SILC_AUTH_PASSWORD:
-    {
-      /* Check whether we find the password for this server in our
-        configuration.  If not, then don't provide so library will ask
-        it from the user. */
-      SERVER_SETUP_REC *setup = server_setup_find_port(conn->remote_host,
-                                                      conn->remote_port);
-      if (!setup || !setup->password) {
-       (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
-       break;
-      }
-
-      (*internal->completion)(TRUE, auth_meth, setup->password,
-                             strlen(setup->password), 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);
+  GetAuthMethod a = context;
+  a->completion(passphrase ? SILC_AUTH_PASSWORD : SILC_AUTH_NONE,
+               passphrase, passphrase_len, a->context);
+  silc_free(a);
 }
 
-/* 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. */
+/* Find authentication data by hostname and port. The hostname may be IP
+   address as well.*/
 
 void silc_get_auth_method(SilcClient client, SilcClientConnection conn,
                          char *hostname, SilcUInt16 port,
+                         SilcAuthMethod auth_meth,
                          SilcGetAuthMeth completion, void *context)
 {
-  InternalGetAuthMethod internal;
+  SERVER_SETUP_REC *setup;
 
   SILC_LOG_DEBUG(("Start"));
 
-  /* 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;
-
-#if 0
-  silc_client_request_authentication_method(client, conn,
-                                           silc_get_auth_method_callback,
-                                           internal);
-#else
-  completion(TRUE, SILC_AUTH_NONE, NULL, 0, context);
-#endif
+  if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
+    /* Returning NULL will cause library to use our private key configured
+       for this connection */
+    completion(SILC_AUTH_PUBLIC_KEY, NULL, 0, context);
+    return;
+  }
+
+  /* Check whether we find the password for this server in our
+     configuration.  If it's set, always send it server. */
+  setup = server_setup_find_port(hostname, port);
+  if (setup && setup->password) {
+    completion(SILC_AUTH_PASSWORD, setup->password, strlen(setup->password),
+              context);
+    return;
+  }
+
+  /* Didn't find password.  If server wants it, ask it from user. */
+  if (auth_meth == SILC_AUTH_PASSWORD) {
+    GetAuthMethod a;
+    a = silc_calloc(1, sizeof(*a));
+    if (a) {
+      a->completion = completion;
+      a->context = context;
+      silc_ask_passphrase(client, conn, silc_get_auth_ask_passphrase, a);
+      return;
+    }
+  }
+
+  /* No authentication */
+  completion(SILC_AUTH_NONE, NULL, 0, context);
 }
 
 /* Asks whether the user would like to perform the key agreement protocol.