Mon Jan 12 13:01:10 CET 2004 Jochen Eisinger <jochen@penguin-breeder.org>
[silc.git] / apps / irssi / src / silc / core / client_ops.c
index 476fbeda80d86fcaf14452563f78aa176807ef19..3b5ca0ccb1a4726993b75b70149d68c5c3bd94f8 100644 (file)
@@ -34,6 +34,7 @@
 #include "levels.h"
 #include "settings.h"
 #include "ignore.h"
+#include "special-vars.h"
 #include "fe-common/core/printtext.h"
 #include "fe-common/core/fe-channels.h"
 #include "fe-common/core/keyboard.h"
@@ -49,6 +50,20 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
                                SilcSKEPKType pk_type,
                                SilcVerifyPublicKey completion, void *context);
 
+char *silc_get_session_filename(SILC_SERVER_REC *server)
+{
+  char *file, *expanded;
+
+  expanded = parse_special_string(settings_get_str("session_filename"),
+                               SERVER(server), NULL, "", NULL, 0);
+
+  file = silc_calloc(1, strlen(expanded) + 255);
+  snprintf(file, strlen(expanded) + 255, "%s/%s", get_irssi_dir(), expanded);
+  free(expanded);
+
+  return file;
+}
+
 static void silc_get_umode_string(SilcUInt32 mode, char *buf,
                                  SilcUInt32 buf_size)
 {
@@ -290,62 +305,71 @@ int verify_message_signature(SilcClientEntry sender,
 
 char * silc_unescape_data(const char *escaped_data, SilcUInt32 *length)
 {
-  SilcUInt32 ctr, dest=0;
-  char *data;
-
-  data = silc_calloc(strlen(escaped_data), sizeof(char));
-  
-  for (ctr = 0; ctr < strlen(escaped_data); ctr++)
-    if (escaped_data[ctr] == 1)
-      data[dest++] = escaped_data[++ctr] - 1;
-    else
-      data[dest++] = escaped_data[ctr];
+    char *data, *ptr;
+    int i = 0, j = 0, len = strlen(escaped_data);
+
+    data = silc_calloc(len, sizeof(char));
+
+    while (i < len) {
+        ptr = memchr(escaped_data + i, 1, len - i);
+        if (ptr) {
+            int inc = (ptr - escaped_data) - i;
+            memcpy(data + j, escaped_data + i, inc);
+            j += inc;
+            i += inc + 2;
+            data[j++] = *(ptr + 1) - 1;
+        } else {
+            memcpy(data + j, escaped_data + i, len - i);
+            j += (len - i);
+            break;
+        }
+    }
 
-  *length = dest;
-  return data;
+    *length = j;
+    return data;
 }
 
 char * silc_escape_data(const char *data, SilcUInt32 len)
 {
-  char *escaped_data;
-  SilcUInt32 ctr, zeros=0;
-
-  for (ctr = 0; ctr < len; ctr++)
-    if (data[ctr] == 0 || data[ctr] == 1)
-      zeros++;
-
-  escaped_data = silc_calloc(zeros + len, sizeof(char));
-
-  zeros=0;
-  for (ctr = 0; ctr < len; ctr++)
-    switch (data[ctr]) {
-      case 0:
-       escaped_data[zeros++] = 1;
-       escaped_data[zeros++] = 1;
-       break;
-
-      case 1:
-       escaped_data[zeros++] = 1;
-       escaped_data[zeros++] = 2;
-       break;
-
-      default:
-       escaped_data[zeros++] = data[ctr];
-    } 
+    char *escaped_data, *ptr, *ptr0, *ptr1;
+    int i = 0, j = 0;
+
+    escaped_data = silc_calloc(2 * len, sizeof(char));
+
+    while (i < len) {
+        ptr0 = memchr(data + i, 0, len - i);
+        ptr1 = memchr(data + i, 1, len - i);
+
+        ptr = (ptr0 < ptr1 ? (ptr0 ? ptr0 : ptr1) : (ptr1 ? ptr1 : ptr0));
+
+        if (ptr) {
+            int inc = (ptr - data) - i;
+            if (inc)
+                memcpy(escaped_data + j, data + i, inc);
+            j += inc;
+            i += inc;
+            escaped_data[j++] = 1;
+            escaped_data[j++] = *(data + i++) + 1;
+        } else {
+            memcpy(escaped_data + j, data + i, len - i);
+            j += (len - i);
+            break;
+        }
+    }
 
     return escaped_data;
 }
 
-void silc_emit_mime_sig(SILC_SERVER_REC *server, SILC_CHANNEL_REC *channel,
-               const char *data, SilcUInt32 data_len,
-               const char *encoding, const char *type, const char *nick)
+void silc_emit_mime_sig(SILC_SERVER_REC *server, WI_ITEM_REC *item,
+               const char *data, SilcUInt32 data_len, const char *nick,
+              int verified)
 {
    char *escaped_data;
 
    escaped_data = silc_escape_data(data, data_len);
 
-   signal_emit("mime", 6, server, channel, escaped_data, encoding, type, nick);
+   signal_emit("mime", 5, server, item, escaped_data, nick, verified);
+
    silc_free(escaped_data);
 }
 
@@ -393,34 +417,15 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn,
   }
 
   if (flags & SILC_MESSAGE_FLAG_DATA) {
-    /* MIME object received, try to display it as well as we can */
-    char type[128], enc[128];
-    unsigned char *data;
-    SilcUInt32 data_len;
-
-    memset(type, 0, sizeof(type));
-    memset(enc, 0, sizeof(enc));
-    if (!silc_mime_parse(message, message_len, NULL, 0, type, sizeof(type) - 1,
-                        enc, sizeof(enc) - 1, &data, &data_len))
-      return;
-
-    /* Then figure out what we can display */
-    if (strstr(type, "text/") && !strstr(type, "text/t140") &&
-       !strstr(type, "text/vnd")) {
-      /* It is something textual, display it */
-      message = (const unsigned char *)data;
-    } else {
-      silc_emit_mime_sig(server, chanrec, data, data_len,
-               enc, type, nick == NULL ? NULL : nick->nick);
-      message = NULL;
-    }
+    silc_emit_mime_sig(server, (WI_ITEM_REC *)chanrec, message, message_len,
+               nick == NULL ? NULL : nick->nick,
+               flags & SILC_MESSAGE_FLAG_SIGNED ? verified : -1);
+    message = NULL;
   }
 
   if (!message)
     return;
 
-  /* FIXME: replace those printformat calls with signals and add signature
-            information to them (if present) */
   if (flags & SILC_MESSAGE_FLAG_ACTION)
     if(flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
       char tmp[256], *cp, *dm = NULL;
@@ -432,15 +437,20 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn,
       }
       silc_utf8_decode(message, message_len, SILC_STRING_LANGUAGE,
                        cp, message_len);
-      printformat_module("fe-common/silc", server, channel->channel_name,
-                         MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_ACTION,
-                         nick == NULL ? "[<unknown>]" : nick->nick, cp);
+      if (flags & SILC_MESSAGE_FLAG_SIGNED)
+        signal_emit("message silc signed_action", 6, server, cp, nick->nick,
+                   nick->host, channel->channel_name, verified);
+      else
+        signal_emit("message silc action", 5, server, cp, nick->nick,
+                   nick->host, channel->channel_name);
       silc_free(dm);
     } else {
-      printformat_module("fe-common/silc", server, channel->channel_name,
-                         MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_ACTION,
-                         nick == NULL ? "[<unknown>]" : nick->nick,
-                         message);
+      if (flags & SILC_MESSAGE_FLAG_SIGNED)
+        signal_emit("message silc signed_action", 6, server, message,
+                   nick->nick, nick->host, channel->channel_name, verified);
+      else
+        signal_emit("message silc action", 5, server, message,
+                   nick->nick, nick->host, channel->channel_name);
     }
   else if (flags & SILC_MESSAGE_FLAG_NOTICE)
     if(flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
@@ -453,15 +463,20 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn,
       }
       silc_utf8_decode(message, message_len, SILC_STRING_LANGUAGE,
                        cp, message_len);
-      printformat_module("fe-common/silc", server, channel->channel_name,
-                         MSGLEVEL_NOTICES, SILCTXT_CHANNEL_NOTICE,
-                         nick == NULL ? "[<unknown>]" : nick->nick, cp);
+      if (flags & SILC_MESSAGE_FLAG_SIGNED)
+       signal_emit("message silc signed_notice", 6, server, cp, nick->nick,
+               nick->host, channel->channel_name, verified);
+      else
+       signal_emit("message silc notice", 5, server, cp, nick->nick,
+               nick->host, channel->channel_name);
       silc_free(dm);
     } else {
-      printformat_module("fe-common/silc", server, channel->channel_name,
-                         MSGLEVEL_NOTICES, SILCTXT_CHANNEL_NOTICE,
-                         nick == NULL ? "[<unknown>]" : nick->nick,
-                         message);
+      if (flags & SILC_MESSAGE_FLAG_SIGNED)
+       signal_emit("message silc signed_notice", 6, server, message,
+               nick->nick, nick->host, channel->channel_name, verified);
+      else
+       signal_emit("message silc notice", 5, server, message,
+               nick->nick, nick->host, channel->channel_name);
     }
   else {
     if (flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
@@ -535,65 +550,117 @@ void silc_private_message(SilcClient client, SilcClientConnection conn,
   }
 
   if (flags & SILC_MESSAGE_FLAG_DATA) {
-    /* MIME object received, try to display it as well as we can */
-    char type[128], enc[128];
-    unsigned char *data;
-    SilcUInt32 data_len;
-
-    memset(type, 0, sizeof(type));
-    memset(enc, 0, sizeof(enc));
-    if (!silc_mime_parse(message, message_len, NULL, 0, type, sizeof(type) - 1,
-                        enc, sizeof(enc) - 1, &data, &data_len))
-      return;
-
-    /* Then figure out what we can display */
-    if (strstr(type, "text/") && !strstr(type, "text/t140") &&
-       !strstr(type, "text/vnd")) {
-      /* It is something textual, display it */
-      message = (const unsigned char *)data;
-    } else {
-      silc_emit_mime_sig(server, NULL, data, data_len,
-                       enc, type, sender->nickname ? sender->nickname :
-                                  "[<unknown>]");
-      message = NULL;
-    }
+    silc_emit_mime_sig(server,
+               sender->nickname ?
+               (WI_ITEM_REC *)query_find(SERVER(server), sender->nickname) :
+               NULL,
+               message, message_len,
+               sender->nickname ? sender->nickname : "[<unknown>]",
+               flags & SILC_MESSAGE_FLAG_SIGNED ? verified : -1);
+    message = NULL;
   }
 
   if (!message)
     return;
 
-  if (flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
-    char tmp[256], *cp, *dm = NULL;
-
-    memset(tmp, 0, sizeof(tmp));
-    cp = tmp;
-    if (message_len > sizeof(tmp) - 1) {
-      dm = silc_calloc(message_len + 1, sizeof(*dm));
-      cp = dm;
+  if (flags & SILC_MESSAGE_FLAG_ACTION)
+    if(flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
+      char tmp[256], *cp, *dm = NULL;
+      memset(tmp, 0, sizeof(tmp));
+      cp = tmp;
+      if(message_len > sizeof(tmp) - 1) {
+        dm = silc_calloc(message_len + 1, sizeof(*dm));
+        cp = dm;
+      }
+      silc_utf8_decode(message, message_len, SILC_STRING_LANGUAGE,
+                       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, 
+                   NULL, verified);
+      else
+        signal_emit("message silc private_action", 5, server, cp, 
+                   sender->nickname ? sender->nickname : "[<unknown>]",
+                   sender->username ? 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, 
+                   NULL, verified);
+      else
+        signal_emit("message silc private_action", 5, server, message, 
+                   sender->nickname ? sender->nickname : "[<unknown>]",
+                   sender->username ? userhost : NULL, NULL);
     }
+  else if (flags & SILC_MESSAGE_FLAG_NOTICE)
+    if(flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
+      char tmp[256], *cp, *dm = NULL;
+      memset(tmp, 0, sizeof(tmp));
+      cp = tmp;
+      if(message_len > sizeof(tmp) - 1) {
+        dm = silc_calloc(message_len + 1, sizeof(*dm));
+        cp = dm;
+      }
+      silc_utf8_decode(message, message_len, SILC_STRING_LANGUAGE,
+                       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, 
+                   NULL, verified);
+      else
+        signal_emit("message silc private_notice", 5, server, cp, 
+                   sender->nickname ? sender->nickname : "[<unknown>]",
+                   sender->username ? 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, 
+                   NULL, verified);
+      else
+        signal_emit("message silc private_notice", 5, server, message, 
+                   sender->nickname ? sender->nickname : "[<unknown>]",
+                   sender->username ? userhost : NULL, NULL);
+    }
+  else {
+    if (flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
+      char tmp[256], *cp, *dm = NULL;
+
+      memset(tmp, 0, sizeof(tmp));
+      cp = tmp;
+      if (message_len > sizeof(tmp) - 1) {
+        dm = silc_calloc(message_len + 1, sizeof(*dm));
+        cp = dm;
+      }
+
+      silc_utf8_decode(message, message_len, SILC_STRING_LANGUAGE,
+                    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);
+      else
+        signal_emit("message private", 4, server, cp,
+                 sender->nickname ? sender->nickname : "[<unknown>]",
+                 sender->username ? userhost : NULL);
+      silc_free(dm);
+      return;
+    } 
 
-    silc_utf8_decode(message, message_len, SILC_STRING_LANGUAGE,
-                    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);
+      signal_emit("message signed_private", 5, server, message,
+              sender->nickname ? sender->nickname : "[<unknown>]",
+              sender->username ? userhost : NULL, verified);
     else
-      signal_emit("message private", 4, server, cp,
-                 sender->nickname ? sender->nickname : "[<unknown>]",
-                 sender->username ? 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);
-  else
-    signal_emit("message private", 4, server, message,
-               sender->nickname ? sender->nickname : "[<unknown>]",
-               sender->username ? userhost : NULL);
+      signal_emit("message private", 4, server, message,
+              sender->nickname ? sender->nickname : "[<unknown>]",
+              sender->username ? userhost : NULL);
+  } 
 }
 
 /* Notify message to the client. The notify arguments are sent in the
@@ -1222,14 +1289,37 @@ void silc_connect(SilcClient client, SilcClientConnection conn,
       signal_emit("message own_nick", 4, server, server->nick, old, "");
       g_free(old);
     }
+
+    /* remove the detach data now */
+    {
+      char *file;
+
+      file = silc_get_session_filename(server);
+
+      unlink(file);
+      silc_free(file);
+    }
     break;
 
   default:
-    server->connection_lost = TRUE;
-    if (server->conn)
-      server->conn->context = NULL;
-    server_disconnect(SERVER(server));
-    break;
+    {
+      char * file;
+
+      file = silc_get_session_filename(server);
+
+      if (silc_file_size(file) > 0)
+        printformat_module("fe-common/silc", server, NULL,
+                          MSGLEVEL_CRAP, SILCTXT_REATTACH_FAILED, file);
+
+      silc_free(file);
+
+      server->connection_lost = TRUE;
+      if (server->conn)
+        server->conn->context = NULL;
+      server_disconnect(SERVER(server));
+
+      break;
+    }
   }
 }
 
@@ -1578,7 +1668,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
        /* Print the unknown nick for user */
        unsigned char *tmp =
          silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
-                                    3, NULL);
+                                    2, NULL);
        if (tmp)
          silc_say_error("%s: %s", tmp,
                         silc_get_status_message(status));
@@ -1696,7 +1786,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
        /* Print the unknown nick for user */
        unsigned char *tmp =
          silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
-                                    3, NULL);
+                                    2, NULL);
        if (tmp)
          silc_say_error("%s: %s", tmp,
                         silc_get_status_message(status));
@@ -1730,11 +1820,10 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
     {
       char *nickname, *username, *realname;
 
-      if (status == SILC_STATUS_ERR_NO_SUCH_NICK ||
-         status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
-       char *tmp;
-       tmp = silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
-                                        3, NULL);
+      if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
+       char *tmp =
+         silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
+                                    2, NULL);
        if (tmp)
          silc_say_error("%s: %s", tmp,
                         silc_get_status_message(status));
@@ -1872,17 +1961,22 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
        collider = silc_client_get_client_by_id(client, conn,
                                                old->id);
 
-        memset(buf, 0, sizeof(buf));
-        snprintf(buf, sizeof(buf) - 1, "%s@%s",
-                collider->username, collider->hostname);
-       nicklist_rename_unique(SERVER(server),
-                              old, old->nickname,
-                              collider, collider->nickname);
-       silc_print_nick_change(server, collider->nickname,
-                              client_entry->nickname, buf);
-       g_slist_free(nicks);
+       if (collider != client_entry) {
+
+          memset(buf, 0, sizeof(buf));
+          snprintf(buf, sizeof(buf) - 1, "%s@%s",
+                  collider->username, collider->hostname);
+         nicklist_rename_unique(SERVER(server),
+                                old, old->nickname,
+                                collider, collider->nickname);
+         silc_print_nick_change(server, collider->nickname,
+                                client_entry->nickname, buf);
+       }
       }
 
+      if (nicks != NULL)
+       g_slist_free(nicks);
+
       old = g_strdup(server->nick);
       server_change_nick(SERVER(server), client_entry->nickname);
       nicklist_rename_unique(SERVER(server),
@@ -2884,13 +2978,14 @@ void
 silc_detach(SilcClient client, SilcClientConnection conn,
             const unsigned char *detach_data, SilcUInt32 detach_data_len)
 {
-  char file[256];
+  SILC_SERVER_REC *server = conn->context;
+  char *file;
 
   /* Save the detachment data to file. */
 
-  memset(file, 0, sizeof(file));
-  snprintf(file, sizeof(file) - 1, "%s/session", get_irssi_dir());
+  file = silc_get_session_filename(server);
   silc_file_writefile(file, detach_data, detach_data_len);
+  silc_free(file);
 }