Merged silc_1_1_branch to trunk.
[silc.git] / apps / irssi / src / silc / core / client_ops.c
index 5f1ff5d0f98f9fa9c6f66a008b638a36c46d27bc..38e90d0844553855d9cc38cc2497756754e37975 100644 (file)
@@ -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);
@@ -766,26 +768,35 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
               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[128 + 1], tmp[32];
+      char *nick, tmp[32];
+      int count = 0;
 
-      silc_parse_userfqdn(client_entry->nickname, nick, sizeof(nick), NULL, 0);
-      clients = silc_client_get_clients_local(client, conn, nick, NULL);
+      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_snprintf(tmp, sizeof(tmp), "%d", silc_dlist_count(clients));
-      printformat_module("fe-common/silc", server, NULL,
-                        MSGLEVEL_CRAP, SILCTXT_CHANNEL_MANY_NICKS,
-                        tmp, nick);
-      printformat_module("fe-common/silc", server, NULL,
-                        MSGLEVEL_CRAP, SILCTXT_CHANNEL_USER_APPEARS,
-                        buf, client_entry->nickname);
+      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;
 
@@ -813,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:
@@ -824,21 +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);
 
     silc_server_free_ftp(server, client_entry);
 
-    /* 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[0]) {
-      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 : "");
-    }
+    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 =
@@ -848,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:
@@ -1348,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,
@@ -1500,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;
@@ -1541,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;
@@ -1655,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;
       }
@@ -2316,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;
@@ -2344,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;
   }
 
@@ -2419,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,
@@ -2429,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. */
@@ -2441,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,
@@ -2453,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;
     }
 
@@ -2462,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,
@@ -2474,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,
@@ -2500,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;
     }
 
@@ -2509,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);
   }
 }
 
@@ -2564,7 +2702,7 @@ typedef struct {
   void *context;
 } *GetAuthMethod;
 
-static void silc_get_auth_ask_passphrase(unsigned char *passphrase,
+static void silc_get_auth_ask_passphrase(const unsigned char *passphrase,
                                         SilcUInt32 passphrase_len,
                                         void *context)
 {