updates
authorPekka Riikonen <priikone@silcnet.org>
Thu, 18 Apr 2002 12:09:47 +0000 (12:09 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Thu, 18 Apr 2002 12:09:47 +0000 (12:09 +0000)
CHANGES
apps/irssi/src/silc/core/client_ops.c
lib/silcutil/silcstrutil.c
lib/silcutil/silcstrutil.h

diff --git a/CHANGES b/CHANGES
index 316fbf2ed5c4b3c8d53794bd99e6877974ce9e9a..6abf33222ca1a93303a6eb19cb8feb40304d71da 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,8 @@
+Thu Apr 18 14:09:51 CEST 2002  Pekka Riikonen <priikone@silcnet.org>
+
+       * 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 <johnny@themnemonic.org>
 
        * Fixed a bug in the pid writing function, which couldn't be
index ce62c19a61ca4bc56891d164d1d32072ff160d8c..ba4d6cf27eebeaf7567d1dbb59bd06f98ed38a4a 100644 (file)
@@ -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 : "[<unknown>]",
              sender->username ? userhost : NULL);
index d1f04883d69d99818031a839b35feda68cc30f8c..f15d07863d4fdc641a151520e6b2d59c85372d09 100644 (file)
@@ -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;
+}
index 868fdc8c9ad8866feb92970e6b8f1cb75101daec..e72b4d446c5168f0be7a19c3efdfcbbde8be6c5d 100644 (file)
@@ -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 */