Merged c0ffee's MIME signal patch.
authorPekka Riikonen <priikone@silcnet.org>
Sat, 6 Jul 2002 08:46:43 +0000 (08:46 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sat, 6 Jul 2002 08:46:43 +0000 (08:46 +0000)
15 files changed:
CHANGES
apps/irssi/docs/signals.txt
apps/irssi/scripts/mime-test.pl [new file with mode: 0644]
apps/irssi/src/core/Makefile.am
apps/irssi/src/core/blob.c [new file with mode: 0644]
apps/irssi/src/core/blob.h [new file with mode: 0644]
apps/irssi/src/perl/common/Irssi.xs
apps/irssi/src/perl/common/module.h
apps/irssi/src/perl/common/typemap
apps/irssi/src/perl/get-signals.pl
apps/irssi/src/perl/perl-common.c
apps/irssi/src/perl/perl-signals-list.h
apps/irssi/src/silc/core/client_ops.c
apps/irssi/src/silc/core/silc-channels.c
apps/irssi/src/silc/core/silc-servers.c

diff --git a/CHANGES b/CHANGES
index 3e5841656aa103c4e49300b0810bb425d9f9cfb9..67bb578af45aa3852d39cb0752834dde2dcb283f 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,10 @@
+Sat Jul  6 11:45:11 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
+
+       * Merged c0ffee's MIME signal patch which adds support for
+         sending also MIME messages in Irssi SILC Client, and handling
+         received MIME messages in a signal (and perhaps doing something
+         to non-textual MIME messages).
+
 Sun Jun 30 01:30:22 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
 
        * Fixed pending command deletion in server and client library
index 2bf0d9213105238597826963ed856b6ada2b618d..9b526aef086ed20e1c2aeb0c7ab93bc0cae554e2 100644 (file)
@@ -324,3 +324,10 @@ gui-printtext.c:
 
 statusbar-items.c:
  "mail counter"
+
+SILC
+----
+
+client_ops.c:
+ "mime", SERVER_REC, CHANNEL_REC, BLOB_REC, char *mime, char *enc, char *nick
+ "mime-send", SERVER_REC, WI_ITEM_REC, char *data, int data_len, char *enc, char *type
diff --git a/apps/irssi/scripts/mime-test.pl b/apps/irssi/scripts/mime-test.pl
new file mode 100644 (file)
index 0000000..23e3840
--- /dev/null
@@ -0,0 +1,43 @@
+use Irssi;\r
+use MIME::Base64;\r
+\r
+sub sig_mime {\r
+\r
+  my ($server, $channel, $blob, $enc, $type, $nick) = @_;\r
+\r
+  Irssi::print("$enc - $type - $blob->{octets}");\r
+\r
+  if (($enc eq "base64") && ($type eq "image/png")) {\r
+    # just stores the image in /tmp/$nick.png\r
+    open OFILE, '>', "/tmp/" . $nick . ".png";\r
+    print OFILE decode_base64($blob->{data});\r
+    close OFILE;\r
+    Irssi::signal_stop();\r
+  }\r
+\r
+}\r
+\r
+sub cmd_scribble {\r
+\r
+  my ($data, $server, $channel) = @_;\r
+\r
+  return if $server->{chat_type} !~ /^silc$/i;\r
+\r
+  # let's hope, $data is a png image...\r
+  open IFILE, $data;\r
+\r
+  read IFILE, $image, 0xffff;\r
+\r
+  close IFILE;\r
+\r
+  $data = encode_base64($image);\r
+  $octets = length($data);\r
+  Irssi::print($octets);\r
+\r
+  Irssi::signal_emit("mime-send", $server, $channel, $data, \$octets,\r
+       "base64", "image/png");\r
+}\r
+\r
+Irssi::signal_add("mime", "sig_mime");\r
+# /scribble path/to/image.png\r
+Irssi::command_bind("scribble", "cmd_scribble");\r
index 655d291a7da6fcbd6a757a64e901bc07236490e8..0f91a4b04c1f7341eaa221566d7b6d3f2ffca766 100644 (file)
@@ -44,7 +44,8 @@ libcore_a_SOURCES = \
        settings.c \
        signals.c \
        special-vars.c \
-       write-buffer.c
+       write-buffer.c \
+       blob.c
 
 structure_headers = \
        channel-rec.h \
@@ -54,7 +55,8 @@ structure_headers = \
        server-rec.h \
        server-setup-rec.h \
        server-connect-rec.h \
-       window-item-rec.h
+       window-item-rec.h \
+       blob.h
 
 noinst_HEADERS = \
        args.h \
diff --git a/apps/irssi/src/core/blob.c b/apps/irssi/src/core/blob.c
new file mode 100644 (file)
index 0000000..51fe5e5
--- /dev/null
@@ -0,0 +1,8 @@
+#include "common.h"
+#include "blob.h"
+#include "modules.h"
+
+void blob_fill(BLOB_REC *blob)
+{
+       blob->type = module_get_uniq_id("BLOB", 0);
+}
diff --git a/apps/irssi/src/core/blob.h b/apps/irssi/src/core/blob.h
new file mode 100644 (file)
index 0000000..ec9e553
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __BLOB_H__
+#define __BLOB_H__
+
+#include "modules.h"
+
+struct _BLOB_REC {
+       int type;
+       void *data;
+       guint32 octets;
+};
+
+typedef struct _BLOB_REC BLOB_REC;
+
+void blob_fill(BLOB_REC *blob);
+
+#endif
index 67d5e96cda6911a2985635918cedb75b10ebc7f7..c84918e82e6a94efaff8c1f80863cc9bbfc2f93e 100644 (file)
@@ -31,3 +31,4 @@ BOOT:
        irssi_boot(Rawlog);
        irssi_boot(Server);
        irssi_boot(Settings);
+       irssi_boot(Blob);
index 5456f6300414a57f9932ed1237c98a647244e37f..aa1cce47896b7445cf47b7ce33e97427935fbe2a 100644 (file)
@@ -22,6 +22,7 @@
 #include "channels.h"
 #include "queries.h"
 #include "nicklist.h"
+#include "blob.h"
 
 #include "perl/perl-core.h"
 #include "perl/perl-common.h"
@@ -42,3 +43,4 @@ typedef RECONNECT_REC *Irssi__Reconnect;
 typedef CHANNEL_REC *Irssi__Channel;
 typedef QUERY_REC *Irssi__Query;
 typedef NICK_REC *Irssi__Nick;
+typedef BLOB_REC *Irssi__Blob;
index 5b7e0c32836c268e2529778964bb955eeef2c347..41bcd4c581499ffcdab43543c5e59f40d490758f 100644 (file)
@@ -13,6 +13,7 @@ Irssi::Logitem        T_PlainObj
 Irssi::Rawlog          T_PlainObj
 Irssi::Module          T_PlainObj
 Irssi::Windowitem      T_IrssiObj
+Irssi::Blob            T_PlainObj
 
 INPUT
 
index df4667cef659928322144880390ae42e363ee74f..7cd97614ffa26d62b4f47127c42359574a128343 100755 (executable)
@@ -51,6 +51,9 @@ while (<STDIN>) {
        s/WINDOW_REC[^,]*/Irssi::UI::Window/g;
        s/WI_ITEM_REC[^,]*/iobject/g;
 
+       # silc
+       s/BLOB_REC[^,]*/siobject/g;
+
        s/([\w\*:]+)(,|$)/"\1"\2/g;
        print "    { \"$signal\", { $_, NULL } },\n";
 }
index 72fc557c98f0d1f077cfac93c9e269c1e64b6258..0113bdf3155069948788482d18165b10d6876cd9 100644 (file)
@@ -39,6 +39,7 @@
 #include "channels.h"
 #include "queries.h"
 #include "nicklist.h"
+#include "blob.h"
 
 #include "perl-common.h"
 
@@ -229,6 +230,12 @@ void irssi_callXS(void (*subaddr)(CV* cv), CV *cv, SV **mark)
        PUTBACK;
 }
 
+static void perl_blob_fill_hash(HV *hv, BLOB_REC *blob)
+{
+       hv_store(hv, "octets", 6, newSViv(blob->octets), 0);
+       hv_store(hv, "data", 4, newSVpv(blob->data, blob->octets), 0);
+}
+
 void perl_chatnet_fill_hash(HV *hv, CHATNET_REC *chatnet)
 {
        char *type, *chat_type;
@@ -624,6 +631,10 @@ void perl_common_start(void)
        plain_stashes = g_hash_table_new((GHashFunc) g_str_hash,
                                         (GCompareFunc) g_str_equal);
         irssi_add_plains(core_plains);
+       irssi_add_object(module_get_uniq_id("BLOB", 0), 0,
+                       "Irssi::Blob",
+                       (PERL_OBJECT_FUNC) perl_blob_fill_hash);
+
 
         use_protocols = NULL;
        g_slist_foreach(chat_protocols, (GFunc) perl_register_protocol, NULL);
index 05003c0fb2885e25e606e8f0d196d50c60e1efe1..f541511c29135825380523a0a2ec8516c1e190e9 100644 (file)
@@ -175,6 +175,8 @@ static PERL_SIGNAL_ARGS_REC perl_signal_args[] =
     { "message dcc", { "siobject", "string", NULL } },
     { "message dcc action", { "siobject", "string", NULL } },
     { "message dcc ctcp", { "siobject", "string", "string", NULL } },
+    { "mime", { "iobject", "iobject", "siobject", "string", "string", "string", NULL } },
+    { "mime-send", { "iobject", "iobject", "string", "int", "string", "string", NULL } },
 
     { NULL }
 };
index d92b4eb06362cfa926a59b9e857d9e38840e8117..c138a51a3eae123ba9b6739352215b32dd25621e 100644 (file)
@@ -39,6 +39,7 @@
 #include "fe-common/silc/module-formats.h"
 
 #include "core.h"
+#include "blob.h"
 
 static void 
 silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
@@ -110,6 +111,20 @@ void silc_say_error(char *msg, ...)
   va_end(va);
 }
 
+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)
+{
+  BLOB_REC blob;
+
+  blob_fill(&blob);
+  blob.octets = data_len;
+  blob.data = (char *)data;
+
+  signal_emit("mime", 6, server, channel, &blob, encoding, type, nick);
+}
+
 /* 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. */
 
@@ -142,12 +157,14 @@ 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];
+    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,
-                        NULL, 0, &data, NULL))
+                        enc, sizeof(enc) - 1, &data, &data_len))
       return;
 
     /* Then figure out what we can display */
@@ -156,9 +173,8 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn,
       /* It is something textual, display it */
       message = (const unsigned char *)data;
     } else {
-      printformat_module("fe-common/silc", server, channel->channel_name,
-                        MSGLEVEL_CRAP, SILCTXT_MESSAGE_DATA,
-                        nick == NULL ? "[<unknown>]" : nick->nick, type);
+      silc_emit_mime_sig(server, chanrec, data, data_len, 
+                        enc, type, nick->nick);
       message = NULL;
     }
   }
@@ -223,12 +239,14 @@ 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];
+    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,
-                        NULL, 0, &data, NULL))
+                        enc, sizeof(enc) - 1, &data, &data_len))
       return;
 
     /* Then figure out what we can display */
@@ -237,10 +255,8 @@ void silc_private_message(SilcClient client, SilcClientConnection conn,
       /* It is something textual, display it */
       message = (const unsigned char *)data;
     } else {
-      printformat_module("fe-common/silc", server, NULL,
-                        MSGLEVEL_CRAP, SILCTXT_MESSAGE_DATA,
-                        sender->nickname ? sender->nickname : "[<unknown>]",
-                        type);
+      silc_emit_mime_sig(server, NULL, data, data_len, 
+                        enc, type, sender->nickname);
       message = NULL;
     }
   }
index f5b3bbaf48676d0ccac04aeb7e5d9303fdedbe5e..a9b8c9539affadfc679b0158a787348144e3b549 100644 (file)
@@ -31,6 +31,7 @@
 #include "rawlog.h"
 #include "misc.h"
 #include "settings.h"
+#include "blob.h"
 
 #include "channels-setup.h"
 
 
 #include "silc-commands.h"
 
+void sig_mime(SILC_SERVER_REC *server, SILC_CHANNEL_REC *channel,
+             BLOB_REC *blob, const char *enc, const char *type,
+             const char *nick)
+{
+  if (!(IS_SILC_SERVER(server)))
+    return;
+  
+  printformat_module("fe-common/silc", server, 
+                    channel == NULL ? NULL : channel->name,
+                    MSGLEVEL_CRAP, SILCTXT_MESSAGE_DATA,
+                    nick == NULL ? "[<unknown>]" : nick, type);
+}
+
 SILC_CHANNEL_REC *silc_channel_create(SILC_SERVER_REC *server,
                                      const char *name, int automatic)
 {
@@ -973,6 +987,7 @@ void silc_channels_init(void)
   signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
   signal_add("server connected", (SIGNAL_FUNC) sig_connected);
   signal_add("server quit", (SIGNAL_FUNC) sig_server_quit);
+  signal_add("mime", (SIGNAL_FUNC) sig_mime);
 
   command_bind_silc("part", MODULE_NAME, (SIGNAL_FUNC) command_part);
   command_bind_silc("me", MODULE_NAME, (SIGNAL_FUNC) command_me);
@@ -990,6 +1005,7 @@ void silc_channels_deinit(void)
   signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
   signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
   signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit);
+  signal_remove("mime", (SIGNAL_FUNC) sig_mime);
 
   command_unbind("part", (SIGNAL_FUNC) command_part);
   command_unbind("me", (SIGNAL_FUNC) command_me);
index 5b5eb384ac6af9cb8a8c5b7dce88b0fb8a31030c..a67fc0b81505b3f58c83248f720ce5bb0c58045a 100644 (file)
@@ -69,6 +69,8 @@ static void silc_send_channel(SILC_SERVER_REC *server,
 typedef struct {
   char *nick;
   char *msg;
+  int len;
+  SilcMessageFlags flags;
   SILC_SERVER_REC *server;
 } PRIVMSG_REC;
 
@@ -121,8 +123,8 @@ static void silc_send_msg_clients(SilcClient client,
 
     /* Send the private message */
     silc_client_send_private_message(client, conn, target, 
-                                    SILC_MESSAGE_FLAG_UTF8,
-                                    rec->msg, strlen(rec->msg),
+                                    rec->flags,
+                                    rec->msg, rec->len,
                                     TRUE);
   }
   
@@ -132,7 +134,8 @@ static void silc_send_msg_clients(SilcClient client,
   g_free(rec);
 }
 
-static void silc_send_msg(SILC_SERVER_REC *server, char *nick, char *msg)
+static void silc_send_msg(SILC_SERVER_REC *server, char *nick, char *msg,
+                       int msg_len, SilcMessageFlags flags)
 {
   PRIVMSG_REC *rec;
   SilcClientEntry *clients;
@@ -153,6 +156,8 @@ static void silc_send_msg(SILC_SERVER_REC *server, char *nick, char *msg)
     rec->nick = g_strdup(nick);
     rec->msg = g_strdup(msg);
     rec->server = server;
+    rec->flags = flags;
+    rec->len = msg_len;
 
     /* Could not find client with that nick, resolve it from server. */
     silc_client_get_clients(silc_client, server->conn,
@@ -164,8 +169,51 @@ static void silc_send_msg(SILC_SERVER_REC *server, char *nick, char *msg)
   /* Send the private message directly */
   silc_free(nickname);
   silc_client_send_private_message(silc_client, server->conn, 
-                                  clients[0], SILC_MESSAGE_FLAG_UTF8,
-                                  msg, strlen(msg), TRUE);
+                                  clients[0], flags,
+                                  msg, msg_len, TRUE);
+}
+
+void silc_send_mime(SILC_SERVER_REC *server, WI_ITEM_REC *to,
+                   const char *data, int data_len,
+                   const char *enc, const char *type)
+{
+  SILC_CHANNEL_REC *channel;
+  QUERY_REC *query;
+  char *mime_data;
+  int mime_data_len;
+  
+  if (!(IS_SILC_SERVER(server)) || (data == NULL) || (to == NULL) || 
+      (enc == NULL) || (type == NULL))
+    return;
+           
+#define SILC_MIME_HEADER "MIME-Version: 1.0\r\nContent-Type: %s\r\nContent-Transfer-Encoding: %s\r\n\r\n"
+
+  mime_data_len = data_len + strlen(SILC_MIME_HEADER) - 4
+    + strlen(enc) + strlen(type);
+  if (mime_data_len >= SILC_PACKET_MAX_LEN)
+    return;
+
+  /* we risk to large packets here... */
+  mime_data = silc_calloc(mime_data_len, sizeof(*mime_data));
+  snprintf(mime_data, mime_data_len, SILC_MIME_HEADER, type, enc);
+  memmove(mime_data + strlen(SILC_MIME_HEADER) - 4 + strlen(enc) + strlen(type),
+         data, data_len);
+
+#undef SILC_MIME_HEADER
+
+  if (IS_SILC_CHANNEL(to)) {
+    channel = SILC_CHANNEL(to);
+    silc_client_send_channel_message(silc_client, server->conn, channel->entry, 
+                                    NULL, SILC_MESSAGE_FLAG_DATA,
+                                    mime_data, mime_data_len, TRUE);
+  } else if (IS_SILC_QUERY(to)) {
+    query = SILC_QUERY(to);
+    silc_send_msg(server, query->name, mime_data, mime_data_len,
+                 SILC_MESSAGE_FLAG_DATA);
+    
+  }
+
+  silc_free(mime_data);
 }
 
 static int isnickflag_func(char flag)
@@ -203,7 +251,9 @@ static void send_message(SILC_SERVER_REC *server, char *target,
   if (target_type == SEND_TARGET_CHANNEL)
     silc_send_channel(server, target, message ? message : msg);
   else
-    silc_send_msg(server, target, message ? message : msg);
+    silc_send_msg(server, target, message ? message : msg,
+                 message ? strlen(message) : strlen(msg),
+                 SILC_MESSAGE_FLAG_UTF8);
 
   silc_free(message);
 }
@@ -890,6 +940,7 @@ void silc_server_init(void)
 
   signal_add_first("server connected", (SIGNAL_FUNC) sig_connected);
   signal_add("server disconnected", (SIGNAL_FUNC) sig_disconnected);
+  signal_add("mime-send", (SIGNAL_FUNC)silc_send_mime);
   command_bind_silc("whois", MODULE_NAME, (SIGNAL_FUNC) command_self);
   command_bind_silc("whowas", MODULE_NAME, (SIGNAL_FUNC) command_self);
   command_bind_silc("nick", MODULE_NAME, (SIGNAL_FUNC) command_self);
@@ -925,6 +976,7 @@ void silc_server_deinit(void)
 
   signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
   signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected);
+  signal_remove("mime-send", (SIGNAL_FUNC)silc_send_mime);
   command_unbind("whois", (SIGNAL_FUNC) command_self);
   command_unbind("whowas", (SIGNAL_FUNC) command_self);
   command_unbind("nick", (SIGNAL_FUNC) command_self);