From 0b55012d620ee13dce587df51b11139dca26ec09 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Thu, 18 Apr 2002 12:09:47 +0000 Subject: [PATCH] updates --- CHANGES | 5 ++ apps/irssi/src/silc/core/client_ops.c | 47 ++++++++++++++++++ lib/silcutil/silcstrutil.c | 70 +++++++++++++++++++++++++++ lib/silcutil/silcstrutil.h | 38 +++++++++++++++ 4 files changed, 160 insertions(+) diff --git a/CHANGES b/CHANGES index 316fbf2e..6abf3322 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +Thu Apr 18 14:09:51 CEST 2002 Pekka Riikonen + + * Added silc_mime_parse function to parse MIME headers. + Affected files are lib/silcutil/silcstruti.[ch]. + Wed Apr 17 22:07:59 CEST 2002 Johnny Mnemonic * Fixed a bug in the pid writing function, which couldn't be diff --git a/apps/irssi/src/silc/core/client_ops.c b/apps/irssi/src/silc/core/client_ops.c index ce62c19a..ba4d6cf2 100644 --- a/apps/irssi/src/silc/core/client_ops.c +++ b/apps/irssi/src/silc/core/client_ops.c @@ -106,6 +106,29 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn, nick = silc_nicklist_insert(chanrec, chu, FALSE); } + if (flags & SILC_MESSAGE_FLAG_DATA) { + /* MIME object received, try to display it as well as we can */ + char type[128]; + unsigned char *data; + + memset(type, 0, sizeof(type)); + if (!silc_mime_parse(message, message_len, NULL, 0, type, sizeof(type) - 1, + NULL, 0, &data, NULL)) + 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 { + message = NULL; + } + } + + if (!message) + return; + if (flags & SILC_MESSAGE_FLAG_ACTION) printformat_module("fe-common/silc", server, channel->channel_name, MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_ACTION, @@ -139,6 +162,30 @@ void silc_private_message(SilcClient client, SilcClientConnection conn, if (sender->username) snprintf(userhost, sizeof(userhost) - 1, "%s@%s", sender->username, sender->hostname); + + if (flags & SILC_MESSAGE_FLAG_DATA) { + /* MIME object received, try to display it as well as we can */ + char type[128]; + unsigned char *data; + + memset(type, 0, sizeof(type)); + if (!silc_mime_parse(message, message_len, NULL, 0, type, sizeof(type) - 1, + NULL, 0, &data, NULL)) + 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 { + message = NULL; + } + } + + if (!message) + return; + signal_emit("message private", 4, server, message, sender->nickname ? sender->nickname : "[]", sender->username ? userhost : NULL); diff --git a/lib/silcutil/silcstrutil.c b/lib/silcutil/silcstrutil.c index d1f04883..f15d0786 100644 --- a/lib/silcutil/silcstrutil.c +++ b/lib/silcutil/silcstrutil.c @@ -408,3 +408,73 @@ bool silc_utf8_valid(const unsigned char *utf8, SilcUInt32 utf8_len) { return silc_utf8_decode(utf8, utf8_len, 0, NULL, 0) != 0; } + +/* Mime constants and macros */ +#define MIME_VERSION "MIME-Version: " +#define MIME_VERSION_LEN 14 +#define MIME_CONTENT_TYPE "Content-Type: " +#define MIME_CONTENT_TYPE_LEN 14 +#define MIME_TRANSFER_ENCODING "Content-Transfer-Encoding: " +#define MIME_TRANSFER_ENCODING_LEN 27 + +#define MIME_GET_FIELD(header, mime, mime_len, field, field_len, \ + dest, dest_size) \ +do { \ + char *f = strstr(header, field); \ + if (f && dest) { \ + f = (char *)mime + (f - header) + field_len; \ + for (i = 0; i < (mime_len - (f - (char *)mime)); i++) { \ + if (f[i] == '\r' || f[i] == '\n' || i == dest_size) \ + break; \ + dest[i] = f[i]; \ + } \ + } \ +} while(0) + +/* Parses MIME object and MIME header in it. */ + +bool +silc_mime_parse(const unsigned char *mime, SilcUInt32 mime_len, + char *version, SilcUInt32 version_size, + char *content_type, SilcUInt32 content_type_size, + char *transfer_encoding, SilcUInt32 transfer_encoding_size, + unsigned char **mime_data_ptr, SilcUInt32 *mime_data_len) +{ + int i; + char header[512]; + + memcpy(header, mime, 512 > mime_len ? mime_len : 512); + header[sizeof(header) - 1] = '\0'; + + /* Check for mandatory Content-Type field */ + if (!strstr(header, MIME_CONTENT_TYPE)) + return FALSE; + + /* Get the pointer to the data area in the object */ + for (i = 0; i < mime_len; i++) { + if (mime_len >= i + 4 && + mime[i ] == '\r' && mime[i + 1] == '\n' && + mime[i + 2] == '\r' && mime[i + 3] == '\n') + break; + } + if (i >= mime_len) + return FALSE; + + if (mime_data_ptr) + *mime_data_ptr = (unsigned char *)mime + i + 4; + if (mime_data_len) + *mime_data_len = mime_len - ((mime + i + 4) - mime); + + /* Get MIME version, Content-Type and Transfer Encoding fields */ + MIME_GET_FIELD(header, mime, mime_len, + MIME_VERSION, MIME_VERSION_LEN, + version, version_size); + MIME_GET_FIELD(header, mime, mime_len, + MIME_CONTENT_TYPE, MIME_CONTENT_TYPE_LEN, + content_type, content_type_size); + MIME_GET_FIELD(header, mime, mime_len, + MIME_TRANSFER_ENCODING, MIME_TRANSFER_ENCODING_LEN, + transfer_encoding, transfer_encoding_size); + + return TRUE; +} diff --git a/lib/silcutil/silcstrutil.h b/lib/silcutil/silcstrutil.h index 868fdc8c..e72b4d44 100644 --- a/lib/silcutil/silcstrutil.h +++ b/lib/silcutil/silcstrutil.h @@ -172,5 +172,43 @@ SilcUInt32 silc_utf8_encoded_len(const unsigned char *bin, SilcUInt32 bin_len, ***/ bool silc_utf8_valid(const unsigned char *utf8, SilcUInt32 utf8_len); +/****f* silcutil/SilcStrUtilAPI/silc_mime_parse + * + * SYNOPSIS + * + * bool + * silc_mime_parse(const unsigned char *mime, SilcUInt32 mime_len, + * char *version, SilcUInt32 version_size, + * char *content_type, SilcUInt32 content_type_size, + * char *transfer_encoding, + * SilcUInt32 transfer_encoding_size, + * unsigned char **mime_data_ptr, + * SilcUInt32 *mime_data_len); + * + * DESCRIPTION + * + * Parses MIME header indicated by `mime' data block of length of + * `mime_len'. Returns TRUE if the `mime' is valid MIME object. + * Parses from the MIME header the MIME Version (if present) and + * copies it to the `version' pointer if provided, content type + * indicating the data in the MIME object and copies it to the + * `content_type' if provided, and the tranfer encoding (if present) + * indicating the encoding of the data and copies it to the + * `content_transfer_encoding' if provided. + * + * The pointer to the actual data in the MIME object is saved into + * `mime_data_ptr'. The pointer is a location in the `mime' and it + * does not allocate or copy anything, ie. the `mime_data_ptr' is a + * pointer to the `mime'. The `mime_data_len' indicates the length of + * the data without the MIME header. The caller is responsible of + * NULL terminating the buffers it provides. + * + ***/ +bool +silc_mime_parse(const unsigned char *mime, SilcUInt32 mime_len, + char *version, SilcUInt32 version_size, + char *content_type, SilcUInt32 content_type_size, + char *transfer_encoding, SilcUInt32 transfer_encoding_size, + unsigned char **mime_data_ptr, SilcUInt32 *mime_data_len); #endif /* SILCSTRUTIL_H */ -- 2.43.0