Merge commit 'origin/silc.1.1.branch'
[silc.git] / apps / irssi / src / silc / core / client_ops.c
index 5dc0fb5c2390582116ebc243576558ea774166e0..5da2cea29017314d1cdee99b6bd993928fe992be 100644 (file)
@@ -185,13 +185,13 @@ static void silc_parse_channel_public_keys(SILC_SERVER_REC *server,
     if (silc_pkcs_get_type(pubkey) != SILC_PKCS_SILC)
       continue;
 
-    pk = silc_pkcs_public_key_encode(pubkey, &pk_len);
+    pk = silc_pkcs_public_key_encode(NULL, pubkey, &pk_len);
     if (!pk)
       continue;
 
     fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
     babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
-    silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, pubkey);
+    silc_pubkey = silc_pkcs_public_key_get_pkcs(SILC_PKCS_SILC, pubkey);
 
     printformat_module("fe-common/silc", server, NULL,
                       MSGLEVEL_CRAP, SILCTXT_CHANNEL_PK_LIST_ENTRY,
@@ -236,6 +236,12 @@ void silc_say_error(char *msg, ...)
   va_end(va);
 }
 
+void static verify_message_signature_verified(SilcBool success,
+                                             void *context)
+{
+  *(SilcBool *)context = success;
+}
+
 /* Try to verify a message using locally stored public key data */
 
 int verify_message_signature(SilcClientEntry sender,
@@ -248,6 +254,7 @@ int verify_message_signature(SilcClientEntry sender,
   SilcUInt32 pk_datalen;
   struct stat st;
   int ret = SILC_MSG_SIGNED_VERIFIED, i;
+  SilcBool verified = FALSE;
 
   /* get public key from the signature payload and compare it with the
      one stored in the client entry */
@@ -292,7 +299,7 @@ int verify_message_signature(SilcClientEntry sender,
     SilcPublicKey cached_pk=NULL;
 
     /* try to load the file */
-    if (!silc_pkcs_load_public_key(filename, &cached_pk)) {
+    if (!silc_pkcs_load_public_key(filename, SILC_PKCS_ANY, &cached_pk)) {
       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
                         SILCTXT_PUBKEY_COULD_NOT_LOAD, "client");
       if (pk == NULL)
@@ -309,9 +316,12 @@ int verify_message_signature(SilcClientEntry sender,
   }
 
   /* the public key is now in pk, our "level of trust" in ret */
-  if ((pk) && silc_message_signed_verify(message, pk,
-                                        sha1hash) != SILC_AUTH_OK)
-    ret = SILC_MSG_SIGNED_FAILED;
+  if (pk) {
+    silc_message_signed_verify(message, pk, sha1hash,
+                              verify_message_signature_verified, &verified);
+    if (!verified)
+      ret = SILC_MSG_SIGNED_FAILED;
+  }
 
   if (pk)
     silc_pkcs_public_key_free(pk);
@@ -729,11 +739,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:
@@ -825,6 +834,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:
@@ -836,21 +874,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 =
@@ -860,6 +893,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:
@@ -1365,7 +1427,7 @@ void silc_getkey_cb(bool success, void *context)
                              ((SilcServerEntry)getkey->entry)->public_key);
   SilcSILCPublicKey silc_pubkey;
 
-  silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key);
+  silc_pubkey = silc_pkcs_public_key_get_pkcs(SILC_PKCS_SILC, public_key);
 
   if (success) {
     if (getkey->id_type == SILC_ID_CLIENT)
@@ -1684,6 +1746,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;
       }
@@ -2217,24 +2293,35 @@ void silc_command_reply(SilcClient client, SilcClientConnection conn,
     {
       SilcChannelEntry channel_entry;
       SilcDList chpks;
+      SilcPublicKey founder_key;
 
       channel_entry = va_arg(vp, SilcChannelEntry);
       (void)va_arg(vp, SilcUInt32);
-      (void)va_arg(vp, SilcPublicKey);
+      founder_key = va_arg(vp, SilcPublicKey);
       chpks = va_arg(vp, SilcDList);
 
-      if (SILC_STATUS_IS_ERROR(status) || !cmode_list_chpks ||
-         !channel_entry || !channel_entry->channel_name)
+      if (SILC_STATUS_IS_ERROR(status) || !channel_entry ||
+         !channel_entry->channel_name)
        return;
 
-      /* Print the channel public key list */
-      if (chpks)
-        silc_parse_channel_public_keys(server, channel_entry, chpks);
-      else
+      /* If founder was changed successfully, tell it to user */
+      if (founder_key && channel_entry->founder_key &&
+         !silc_pkcs_public_key_compare(founder_key,
+                                       channel_entry->founder_key)) {
         printformat_module("fe-common/silc", server, NULL,
-                         MSGLEVEL_CRAP, SILCTXT_CHANNEL_PK_NO_LIST,
-                         channel_entry->channel_name);
+                          MSGLEVEL_CRAP, SILCTXT_CHANNEL_FOUNDER_CHANGED,
+                          channel_entry->channel_name);
+      }
 
+      /* Print the channel public key list */
+      if (cmode_list_chpks) {
+       if (chpks)
+         silc_parse_channel_public_keys(server, channel_entry, chpks);
+       else
+         printformat_module("fe-common/silc", server, NULL,
+                            MSGLEVEL_CRAP, SILCTXT_CHANNEL_PK_NO_LIST,
+                            channel_entry->channel_name);
+      }
     }
     break;
 
@@ -2367,14 +2454,14 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
   }
 
   /* Encode public key */
-  pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+  pk = silc_pkcs_public_key_encode(NULL, public_key, &pk_len);
   if (!pk) {
     if (completion)
       completion(FALSE, context);
     return;
   }
 
-  silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key);
+  silc_pubkey = silc_pkcs_public_key_get_pkcs(SILC_PKCS_SILC, public_key);
 
   pw = getpwuid(getuid());
   if (!pw) {
@@ -2478,8 +2565,9 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
     SilcUInt32 encpk_len;
 
     /* Load the key file, try for both IP filename and hostname filename */
-    if (!silc_pkcs_load_public_key(ipf, &local_pubkey) &&
-       (!hostf || (!silc_pkcs_load_public_key(hostf, &local_pubkey)))) {
+    if (!silc_pkcs_load_public_key(ipf, SILC_PKCS_ANY, &local_pubkey) &&
+       (!hostf || (!silc_pkcs_load_public_key(hostf, SILC_PKCS_ANY,
+                                              &local_pubkey)))) {
       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
                         SILCTXT_PUBKEY_RECEIVED,verify->entity_name ?
                         verify->entity_name : entity);
@@ -2508,7 +2596,7 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
     }
 
     /* Encode the key data */
-    encpk = silc_pkcs_public_key_encode(local_pubkey, &encpk_len);
+    encpk = silc_pkcs_public_key_encode(NULL, local_pubkey, &encpk_len);
     if (!encpk) {
       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
                         SILCTXT_PUBKEY_RECEIVED,verify->entity_name ?
@@ -2636,7 +2724,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)
 {