From: Pekka Riikonen Date: Sat, 6 Jul 2002 08:46:43 +0000 (+0000) Subject: Merged c0ffee's MIME signal patch. X-Git-Tag: silc.client.0.9.5~39 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=fa0904121c6cdc56d0bbc01437a09cf798e2e322 Merged c0ffee's MIME signal patch. --- diff --git a/CHANGES b/CHANGES index 3e584165..67bb578a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,10 @@ +Sat Jul 6 11:45:11 EEST 2002 Pekka Riikonen + + * 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 * Fixed pending command deletion in server and client library diff --git a/apps/irssi/docs/signals.txt b/apps/irssi/docs/signals.txt index 2bf0d921..9b526aef 100644 --- a/apps/irssi/docs/signals.txt +++ b/apps/irssi/docs/signals.txt @@ -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 index 00000000..23e38403 --- /dev/null +++ b/apps/irssi/scripts/mime-test.pl @@ -0,0 +1,43 @@ +use Irssi; +use MIME::Base64; + +sub sig_mime { + + my ($server, $channel, $blob, $enc, $type, $nick) = @_; + + Irssi::print("$enc - $type - $blob->{octets}"); + + if (($enc eq "base64") && ($type eq "image/png")) { + # just stores the image in /tmp/$nick.png + open OFILE, '>', "/tmp/" . $nick . ".png"; + print OFILE decode_base64($blob->{data}); + close OFILE; + Irssi::signal_stop(); + } + +} + +sub cmd_scribble { + + my ($data, $server, $channel) = @_; + + return if $server->{chat_type} !~ /^silc$/i; + + # let's hope, $data is a png image... + open IFILE, $data; + + read IFILE, $image, 0xffff; + + close IFILE; + + $data = encode_base64($image); + $octets = length($data); + Irssi::print($octets); + + Irssi::signal_emit("mime-send", $server, $channel, $data, \$octets, + "base64", "image/png"); +} + +Irssi::signal_add("mime", "sig_mime"); +# /scribble path/to/image.png +Irssi::command_bind("scribble", "cmd_scribble"); diff --git a/apps/irssi/src/core/Makefile.am b/apps/irssi/src/core/Makefile.am index 655d291a..0f91a4b0 100644 --- a/apps/irssi/src/core/Makefile.am +++ b/apps/irssi/src/core/Makefile.am @@ -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 index 00000000..51fe5e5e --- /dev/null +++ b/apps/irssi/src/core/blob.c @@ -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 index 00000000..ec9e553e --- /dev/null +++ b/apps/irssi/src/core/blob.h @@ -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 diff --git a/apps/irssi/src/perl/common/Irssi.xs b/apps/irssi/src/perl/common/Irssi.xs index 67d5e96c..c84918e8 100644 --- a/apps/irssi/src/perl/common/Irssi.xs +++ b/apps/irssi/src/perl/common/Irssi.xs @@ -31,3 +31,4 @@ BOOT: irssi_boot(Rawlog); irssi_boot(Server); irssi_boot(Settings); + irssi_boot(Blob); diff --git a/apps/irssi/src/perl/common/module.h b/apps/irssi/src/perl/common/module.h index 5456f630..aa1cce47 100644 --- a/apps/irssi/src/perl/common/module.h +++ b/apps/irssi/src/perl/common/module.h @@ -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; diff --git a/apps/irssi/src/perl/common/typemap b/apps/irssi/src/perl/common/typemap index 5b7e0c32..41bcd4c5 100644 --- a/apps/irssi/src/perl/common/typemap +++ b/apps/irssi/src/perl/common/typemap @@ -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 diff --git a/apps/irssi/src/perl/get-signals.pl b/apps/irssi/src/perl/get-signals.pl index df4667ce..7cd97614 100755 --- a/apps/irssi/src/perl/get-signals.pl +++ b/apps/irssi/src/perl/get-signals.pl @@ -51,6 +51,9 @@ while () { 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"; } diff --git a/apps/irssi/src/perl/perl-common.c b/apps/irssi/src/perl/perl-common.c index 72fc557c..0113bdf3 100644 --- a/apps/irssi/src/perl/perl-common.c +++ b/apps/irssi/src/perl/perl-common.c @@ -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); diff --git a/apps/irssi/src/perl/perl-signals-list.h b/apps/irssi/src/perl/perl-signals-list.h index 05003c0f..f541511c 100644 --- a/apps/irssi/src/perl/perl-signals-list.h +++ b/apps/irssi/src/perl/perl-signals-list.h @@ -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 } }; diff --git a/apps/irssi/src/silc/core/client_ops.c b/apps/irssi/src/silc/core/client_ops.c index d92b4eb0..c138a51a 100644 --- a/apps/irssi/src/silc/core/client_ops.c +++ b/apps/irssi/src/silc/core/client_ops.c @@ -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 ? "[]" : 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 : "[]", - type); + silc_emit_mime_sig(server, NULL, data, data_len, + enc, type, sender->nickname); message = NULL; } } diff --git a/apps/irssi/src/silc/core/silc-channels.c b/apps/irssi/src/silc/core/silc-channels.c index f5b3bbaf..a9b8c953 100644 --- a/apps/irssi/src/silc/core/silc-channels.c +++ b/apps/irssi/src/silc/core/silc-channels.c @@ -31,6 +31,7 @@ #include "rawlog.h" #include "misc.h" #include "settings.h" +#include "blob.h" #include "channels-setup.h" @@ -45,6 +46,19 @@ #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 ? "[]" : 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); diff --git a/apps/irssi/src/silc/core/silc-servers.c b/apps/irssi/src/silc/core/silc-servers.c index 5b5eb384..a67fc0b8 100644 --- a/apps/irssi/src/silc/core/silc-servers.c +++ b/apps/irssi/src/silc/core/silc-servers.c @@ -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);