aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-formatter.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/camel-formatter.c')
-rw-r--r--camel/camel-formatter.c1091
1 files changed, 0 insertions, 1091 deletions
diff --git a/camel/camel-formatter.c b/camel/camel-formatter.c
deleted file mode 100644
index 5b68cc858d..0000000000
--- a/camel/camel-formatter.c
+++ /dev/null
@@ -1,1091 +0,0 @@
- /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/*--------------------------------*-C-*---------------------------------*
- *
- * Author :
- * Matt Loper <matt@helixcode.com>
- *
- * Copyright 2000, Helix Code, Inc. (http://www.helixcode.com) .
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- *
- *----------------------------------------------------------------------*/
-
-#include <config.h>
-#include "camel-formatter.h"
-#include "camel-data-wrapper.h"
-#include "camel-mime-message.h"
-#include "camel-multipart.h"
-#include "camel-recipient.h"
-
-#include "camel-log.h"
-#include <libgnome/libgnome.h>
-#include <ctype.h> /* for isprint */
-#include <string.h> /* for strstr */
-
-/*
- * The CamelFormatter takes a mime message, and produces html from it,
- * through the single function camel_formatter_mime_message_to_html().
- * The flow of execution goes something like this:
- *
- * camel_formatter_mime_message_to_html()
- * |
- * V
- * call_handler_function()
- *
- * Then, 'call_handler_function' acts as a dispatcher, using a
- * hashtable to match a mime type to one of the following functions;
- * note that the below functions sometimes then use
- * 'call_handler_function()' to continue the process recursively.
- */
-
-static void handle_text_plain (CamelFormatter *formatter,
- CamelDataWrapper *wrapper);
-static void handle_text_html (CamelFormatter *formatter,
- CamelDataWrapper *wrapper);
-static void handle_image (CamelFormatter *formatter,
- CamelDataWrapper *wrapper);
-static void handle_vcard (CamelFormatter *formatter,
- CamelDataWrapper *wrapper);
-static void handle_mime_part (CamelFormatter *formatter,
- CamelDataWrapper *wrapper);
-static void handle_multipart_mixed (CamelFormatter *formatter,
- CamelDataWrapper *wrapper);
-static void handle_multipart_related (CamelFormatter *formatter,
- CamelDataWrapper *wrapper);
-static void handle_multipart_alternative(CamelFormatter *formatter,
- CamelDataWrapper *wrapper);
-static void handle_unknown_type (CamelFormatter *formatter,
- CamelDataWrapper *wrapper);
-
-/* encodes some characters into their 'escaped' version;
- * so '<' turns into '&lt;', and '"' turns into '&quot;' */
-static gchar* text_to_html (const guchar *input,
- guint len,
- guint *encoded_len_return,
- gboolean convert_newlines_to_br);
-
-/* compares strings case-insensitively */
-static gint strcase_equal (gconstpointer v, gconstpointer v2);
-static gchar* str_tolower (gchar* str);
-
-/* writes the header info for a mime message into a stream */
-static void write_header_info_to_stream (CamelMimeMessage* mime_message,
- CamelStream* stream);
-
-/* dispatch html printing via mimetype */
-static void call_handler_function (CamelFormatter* formatter,
- CamelDataWrapper* wrapper,
- gchar* mimetype_whole,
- gchar* mimetype_main);
-
-static GtkObjectClass *parent_class = NULL;
-
-struct _CamelFormatterPrivate {
- CamelDataWrapper *current_root;
- CamelStream *stream;
- GHashTable *attachments;
-};
-
-
-static void
-debug (const gchar *format, ...)
-{
-#if 0
- va_list args;
- gchar *string;
-
- g_return_if_fail (format != NULL);
-
- va_start (args, format);
- string = g_strdup_vprintf (format, args);
- va_end (args);
-
- fputs (string, stdout);
- fflush (stdout);
-
- g_free (string);
-#endif
-}
-
-static void
-initialize_camel_formatter (CamelFormatter* formatter,
- CamelDataWrapper* data_wrapper,
- CamelStream* stream)
-{
- CamelFormatterPrivate* fmt = formatter->priv;
-
- /* initialize members of our formatter */
- fmt->current_root = data_wrapper;
- fmt->stream = stream;
- if (fmt->attachments)
- g_hash_table_destroy (fmt->attachments);
- fmt->attachments = g_hash_table_new (g_str_hash, strcase_equal);
-}
-
-
-/**
- * camel_formatter_wrapper_to_html:
- * @formatter: the camel formatter object
- * @data_wrapper: the data wrapper
- * @stream: byte stream where data will be written
- *
- * Writes a CamelDataWrapper out, as html, into a stream passed in as
- * a parameter.
- **/
-void camel_formatter_wrapper_to_html (CamelFormatter* formatter,
- CamelDataWrapper* data_wrapper,
- CamelStream* stream_out)
-{
- CamelFormatterPrivate* fmt = formatter->priv;
- gchar *mimetype_whole =
- g_strdup_printf ("%s/%s",
- data_wrapper->mime_type->type,
- data_wrapper->mime_type->subtype);
-
- debug ("camel_formatter_wrapper_to_html: entered\n");
- g_assert (formatter && data_wrapper && stream_out);
-
- /* give the root CamelDataWrapper and the stream to the formatter */
- initialize_camel_formatter (formatter, data_wrapper, stream_out);
-
- if (stream_out) {
-
- /* write everything to the stream */
- camel_stream_write_string (
- fmt->stream, "<html><body bgcolor=\"white\">\n");
- call_handler_function (
- formatter,
- data_wrapper,
- mimetype_whole,
- data_wrapper->mime_type->type);
-
- camel_stream_write_string (fmt->stream, "\n</body></html>\n");
- }
-
-
- g_free (mimetype_whole);
-}
-
-
-/**
- * camel_formatter_mime_message_to_html:
- * @formatter: the camel formatter object
- * @mime_message: the input mime message
- * @header_stream: byte stream where data will be written (can be
- * NULL)
- * @body_stream: byte stream where data will be written (required)
- *
- * Writes a CamelMimeMessage out, as html, into a stream passed in as
- * a parameter.
- **/
-void
-camel_formatter_mime_message_to_html (CamelFormatter* formatter,
- CamelMimeMessage* mime_message,
- CamelStream* header_stream,
- CamelStream* body_stream)
-{
- debug ("camel_formatter_mime_message_to_html: entered\n");
-
- g_assert (formatter != NULL);
- g_assert (CAMEL_IS_FORMATTER (formatter));
- g_assert (mime_message != NULL);
- g_assert (CAMEL_IS_MIME_MESSAGE (mime_message));
-
- g_assert (header_stream || body_stream);
-
- /* give the root CamelDataWrapper and the stream to the
- formatter */
- initialize_camel_formatter (formatter,
- CAMEL_DATA_WRAPPER (mime_message),
- body_stream);
-
- if (body_stream) {
- /* Write the contents of the mime message to the stream */
- camel_stream_write_string (body_stream, "<html><body>\n");
- call_handler_function (
- formatter,
- CAMEL_DATA_WRAPPER (mime_message),
- "message/rfc822",
- "message");
- camel_stream_write_string (body_stream, "\n</body></html>\n");
- }
-
- /* write the subj:, to:, from: etc. fields out as html to the
- header stream */
- if (header_stream)
- write_header_info_to_stream (mime_message,
- header_stream);
-}
-
-/* we're maintaining a hashtable of mimetypes -> functions;
- * those functions have the following signature...*/
-typedef void (*mime_handler_fn) (CamelFormatter *formatter,
- CamelDataWrapper *data_wrapper);
-
-static gchar*
-lookup_unique_id (CamelDataWrapper* root, CamelDataWrapper* child)
-{
- /* ** FIXME : replace this with a string representing
- the location of the objetc in the tree */
- /* TODO: assert our return value != NULL */
-
- gchar *temp_hack_uid;
-
- temp_hack_uid = g_strdup_printf ("%p", camel_data_wrapper_get_output_stream (child));
-
- return temp_hack_uid;
-}
-
-static GHashTable* mime_function_table;
-
-/* This tries to create a tag, given a mimetype and the child of a
- * mime message. It can return NULL if it can't match the mimetype to
- * a bonobo object. */
-static gchar*
-get_bonobo_tag_for_object (CamelFormatter* formatter,
- CamelDataWrapper* wrapper,
- gchar* mimetype)
-{
-
- CamelDataWrapper* root = formatter->priv->current_root;
- char* uid = lookup_unique_id (root, wrapper);
- const char* goad_id = gnome_mime_get_value (
- mimetype, "bonobo-goad-id");
-
- g_assert (root);
-
- if (goad_id) {
-
- char* tag = g_strdup_printf (
- "<object classid=\"%s\"> <param name=\"uid\" value=\"camel://%s\"> </object>",
- goad_id, uid);
-
- debug ("get_bonobo_tag_for_object: goad id %s found for mime type %s\n", goad_id, mimetype);
- return tag;
- }
- else
- return NULL;
-}
-
-
-/*
- * This takes a mimetype, and tries to map that mimetype to a function
- * or a bonobo object.
- *
- * - If it's mapped to a bonobo object, this function prints a tag
- * into the stream, designating the bonobo object and a place that
- * the bonobo object can find data to hydrate from
- *
- * - otherwise, the mimetype is mapped to another function, which can
- * print into the stream
- */
-static void
-call_handler_function (CamelFormatter* formatter,
- CamelDataWrapper* wrapper,
- gchar* mimetype_whole_in, /* ex. "image/jpeg" */
- gchar* mimetype_main_in) /* ex. "image" */
-{
- mime_handler_fn handler_function = NULL;
- gchar* mimetype_whole = NULL;
- gchar* mimetype_main = NULL;
-
- g_assert (formatter);
- g_assert (mimetype_whole_in || mimetype_main_in);
- g_assert (wrapper);
-
-/*
- * Try to find a handler function in our own lookup table
- */
- if (mimetype_whole_in) {
- mimetype_whole = str_tolower (mimetype_whole_in);
-
- handler_function = g_hash_table_lookup (
- mime_function_table, mimetype_whole);
- }
-
- if (mimetype_main_in)
- mimetype_main = str_tolower (mimetype_main_in);
-
- if (mimetype_main && !handler_function)
- handler_function = g_hash_table_lookup (
- mime_function_table, mimetype_main);
-/*
- * Upon failure, try to find a bonobo object to show the object
- */
- if (!handler_function) {
-
- gchar* bonobo_tag = NULL;
-
- if (mimetype_whole)
- bonobo_tag = get_bonobo_tag_for_object (
- formatter, wrapper, mimetype_whole);
-
- if (mimetype_main && !bonobo_tag)
- bonobo_tag = get_bonobo_tag_for_object (
- formatter, wrapper, mimetype_main);
-
- if (bonobo_tag) {
-
- /* we can print a tag, and return! */
- camel_stream_write_string (
- formatter->priv->stream, bonobo_tag);
- g_free (bonobo_tag);
- if (mimetype_whole) g_free (mimetype_whole);
- if (mimetype_main) g_free (mimetype_main);
-
- return;
- }
- }
-/*
- * Use either a handler function we've found, or a default handler
- */
- if (handler_function)
- (*handler_function)(formatter, wrapper);
- else {
- handle_unknown_type (formatter, wrapper);
- debug ("no function or bonobo object found for mimetype \"%s\"\n",
- mimetype_whole?mimetype_whole:mimetype_main);
- }
- if (mimetype_whole) g_free (mimetype_whole);
- if (mimetype_main) g_free (mimetype_main);
-}
-
-
-/*----------------------------------------------------------------------*
- * Header (ex. "subj:", "from:") helper functions for mime msgs
- *----------------------------------------------------------------------*/
-
-/* This routine was originally written by Daniel Velliard, (C) 1998
- * World Wide Web Consortium.
- * - It will (for example) turn the input 'ab <c>' into 'ab &lt;c&gt;'
- * - It has also been altered to turn '\n' into <br>. */
-static gchar *
-text_to_html (const guchar *input,
- guint len,
- guint *encoded_len_return,
- gboolean convert_newlines_to_br)
-{
- const guchar *cur = input;
- guchar *buffer = NULL;
- guchar *out = NULL;
- gint buffer_size = 0;
- guint count;
-
- /* Allocate a translation buffer. */
- buffer_size = 1000;
- buffer = g_malloc (buffer_size);
-
- out = buffer;
- count = 0;
-
- while (count < len) {
- if (out - buffer > buffer_size - 100) {
- gint index = out - buffer;
-
- buffer_size *= 2;
- buffer = g_realloc (buffer, buffer_size);
- out = &buffer[index];
- }
-
- /* By default one has to encode at least '<', '>', '"'
- and '&'. */
- if (*cur == '<') {
- *out++ = '&';
- *out++ = 'l';
- *out++ = 't';
- *out++ = ';';
- } else if (*cur == '>') {
- *out++ = '&';
- *out++ = 'g';
- *out++ = 't';
- *out++ = ';';
- } else if (*cur == '&') {
- *out++ = '&';
- *out++ = 'a';
- *out++ = 'm';
- *out++ = 'p';
- *out++ = ';';
- } else if (*cur == '"') {
- *out++ = '&';
- *out++ = 'q';
- *out++ = 'u';
- *out++ = 'o';
- *out++ = 't';
- *out++ = ';';
- } else if (((*cur >= 0x20) && (*cur < 0x80))
- || (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
- /* Default case, just copy. */
- *out++ = *cur;
- } else {
- char buf[10], *ptr;
-
- g_snprintf(buf, 9, "&#%d;", *cur);
-
- ptr = buf;
- while (*ptr != 0)
- *out++ = *ptr++;
- }
-
- /* turn newlines into <br> */
- if (*cur == '\n' && convert_newlines_to_br) {
- *out++ = '<';
- *out++ = 'b';
- *out++ = 'r';
- *out++ = '>';
- }
-
-
- cur++;
- count++;
- }
-
- *out = 0;
- *encoded_len_return = out - buffer;
-
- return buffer;
-}
-
-
-static void
-write_field_to_stream (const gchar* description, const gchar* value,
- CamelStream *stream, gboolean as_table_row)
-{
- gchar *s;
- guint ev_length;
- gchar* encoded_value = value?text_to_html (
- value, strlen(value), &ev_length, TRUE):g_strdup ("");
- int i;
-
- if (value)
- for (i = 0; i < strlen (value); i++)
- if (!isprint(encoded_value[i]))
- encoded_value[i] = 'Z';
-
- g_assert (description);
-
- s = g_strdup_printf ("%s<b>%s</b>%s%s%s\n",
- as_table_row?"<tr><td>":"",
- description,
- as_table_row?"</td><td>":" ",
- encoded_value,
- as_table_row?"</td></tr>":"");
-
- camel_stream_write_string (stream, s);
- g_free (encoded_value);
- g_free (s);
-}
-
-
-static void
-write_recipients_to_stream (const gchar* recipient_type,
- const GList* recipients,
- CamelStream* stream,
- gboolean as_table_row)
-{
- /* list of recipients, like "elvis@graceland; bart@springfield" */
- gchar *recipients_string = NULL;
- g_assert (recipient_type && stream);
-
- /* Write out each recipient of 'recipient_type' to the stream */
- while (recipients) {
- gchar *old_string = recipients_string;
- recipients_string = g_strdup_printf (
- "%s%s%s",
- old_string?old_string:"",
- old_string?"; ":"",
- (gchar*)recipients->data);
-
- g_free (old_string);
-
- recipients = recipients->next;
- }
- write_field_to_stream (recipient_type, recipients_string, stream,
- as_table_row);
-
- g_free (recipients_string);
-}
-
-
-
-static void
-write_header_info_to_stream (CamelMimeMessage* mime_message,
- CamelStream* stream)
-{
- gchar *s = NULL;
- const GList *recipients = NULL;
-
- g_assert (mime_message && stream);
-
- camel_stream_write_string (stream, "<table WIDTH=\"100\%\">");
-
- /* A few fields will probably be available from the mime_message;
- for each one that's available, write it to the output stream
- with a helper function, 'write_field_to_stream'. */
-
- /* blame me for the bad code - rhon rhon ! */
- /* first row : "From" and "To" */
- camel_stream_write_string (stream, "<tr>");
- camel_stream_write_string (stream, "<td>");
- s = (gchar*)camel_mime_message_get_from (mime_message);
- write_field_to_stream ("From: ", s, stream, FALSE);
-
- camel_stream_write_string (stream, "</td>");
- camel_stream_write_string (stream, "<td>");
-
- /* Fill out the "To:" recipients line */
- recipients = camel_mime_message_get_recipients (
- mime_message, CAMEL_RECIPIENT_TYPE_TO);
-
- if (recipients)
- write_recipients_to_stream ("To:", recipients, stream, FALSE);
-
- camel_stream_write_string (stream, "</td>");
- camel_stream_write_string (stream, "</tr>");
-
-
-
- /* second row : "Subject" and "CC" */
- camel_stream_write_string (stream, "<tr>");
- camel_stream_write_string (stream, "<td>");
- s = (gchar*)camel_mime_message_get_subject (mime_message);
- write_field_to_stream ("Subject: ", s, stream, FALSE);
-
- camel_stream_write_string (stream, "</td>");
- camel_stream_write_string (stream, "<td>");
-
- /* Fill out the "CC:" recipients line */
- recipients = camel_mime_message_get_recipients (
- mime_message, CAMEL_RECIPIENT_TYPE_CC);
- if (recipients)
- write_recipients_to_stream ("CC:", recipients, stream, FALSE);
-
- camel_stream_write_string (stream, "</td>");
- camel_stream_write_string (stream, "</tr>");
-
-
-#if FOR_LATER_EXTENSION
- if ((s = (gchar*)camel_mime_message_get_received_date (mime_message))) {
- write_field_to_stream ("Received Date: ", s, stream, TRUE);
- }
-
- if ((s = (gchar*)camel_mime_message_get_sent_date (mime_message))) {
- write_field_to_stream ("Sent Date: ", s, stream, TRUE);
- }
-
-
-
- /* Fill out the "BCC:" recipients line */
- recipients = camel_mime_message_get_recipients (
- mime_message, CAMEL_RECIPIENT_TYPE_BCC);
- if (recipients)
- write_recipients_to_stream ("BCC:", recipients, stream, TRUE);
-#endif
-
- camel_stream_write_string (stream, "</table>");
-}
-
-/* case-insensitive string comparison */
-static gint
-strcase_equal (gconstpointer v, gconstpointer v2)
-{
- return g_strcasecmp ((const gchar*) v, (const gchar*)v2) == 0;
-}
-
-static gchar*
-str_tolower (gchar* str)
-{
- int i;
- int len = strlen (str);
- gchar* new_str = g_strdup (str);
-
- for (i = 0; i < len; i++) {
- new_str[i] = tolower (str[i]);
- }
- return new_str;
-}
-
-
-#define MIME_TYPE_WHOLE(a) (gmime_content_field_get_mime_type ( \
- camel_mime_part_get_content_type (CAMEL_MIME_PART (a))))
-#define MIME_TYPE_MAIN(a) ((camel_mime_part_get_content_type (CAMEL_MIME_PART (a)))->type)
-#define MIME_TYPE_SUB(a) ((camel_mime_part_get_content_type (CAMEL_MIME_PART (a)))->subtype)
-
-
-/*----------------------------------------------------------------------*
- * Mime handling functions
- *----------------------------------------------------------------------*/
-
-static void
-handle_text_plain (CamelFormatter *formatter, CamelDataWrapper *wrapper)
-{
- gchar* text;
- CamelStream *wrapper_output_stream;
- gchar tmp_buffer[4096];
- gint nb_bytes_read;
- gboolean empty_text = TRUE;
-
- debug ("handle_text_plain: entered\n");
-
- camel_stream_write_string (formatter->priv->stream,
- "\n<!-- text/plain below -->\n");
- camel_stream_write_string (formatter->priv->stream,
- "<pre>\n");
-
- if (strcmp (wrapper->mime_type->subtype, "richtext") == 0) {
-
- camel_stream_write_string (
- formatter->priv->stream,
- "<center><b><table bgcolor=\"b0b0ff\" cellpadding=3><tr><td>Warning: the following richtext may not");
- camel_stream_write_string (
- formatter->priv->stream,
- " be formatted correctly. </b></td></tr></table></center><br>");
- }
-
- /* get the output stream of the data wrapper */
- wrapper_output_stream = camel_data_wrapper_get_output_stream (wrapper);
-
- camel_stream_reset (wrapper_output_stream);
-
-
- do {
-
- /* read next chunk of text */
- nb_bytes_read = camel_stream_read (wrapper_output_stream,
- tmp_buffer,
- 4096);
-
- /* If there's any text, write it to the stream */
- if (nb_bytes_read > 0) {
-
- int returned_strlen;
-
- empty_text = FALSE;
-
- /* replace '<' with '&lt;', etc. */
- text = text_to_html (tmp_buffer,
- nb_bytes_read,
- &returned_strlen,
- FALSE);
-
- camel_stream_write_string (formatter->priv->stream, text);
- g_free (text);
- }
-
-
- } while (!camel_stream_eos (wrapper_output_stream));
-
-
- if (empty_text) {
- debug ("Warning: handle_text_plain: text part is empty!\n");
- camel_stream_write_string (formatter->priv->stream,
- "<b>(empty)</b>");
- }
- camel_stream_write_string (formatter->priv->stream,
- "</pre>\n");
-
- debug ("handle_text_plain: exiting\n");
-}
-
-static void
-handle_text_html (CamelFormatter *formatter, CamelDataWrapper *wrapper)
-{
- CamelStream *wrapper_output_stream;
- gchar tmp_buffer[4096];
- gint nb_bytes_read;
- gboolean empty_text = TRUE;
-
-
- debug ("handle_text_html: entered\n");
-
- /* get the output stream of the data wrapper */
- wrapper_output_stream = camel_data_wrapper_get_output_stream (wrapper);
-
- camel_stream_reset (wrapper_output_stream);
-
- /* write the header */
- camel_stream_write_string (formatter->priv->stream,
- "\n<!-- text/html below -->\n");
-
- do {
-
- /* read next chunk of text */
- nb_bytes_read = camel_stream_read (wrapper_output_stream,
- tmp_buffer,
- 4096);
-
- /* If there's any text, write it to the stream */
- if (nb_bytes_read > 0) {
-
- empty_text = FALSE;
-
- /* write the buffer to the formater output stream */
- camel_stream_write (formatter->priv->stream, tmp_buffer, nb_bytes_read);
- }
-
-
- } while (!camel_stream_eos (wrapper_output_stream));
-
-
- if (empty_text) {
- debug ("Warning: handle_text_html: html part is empty!\n");
- camel_stream_write_string (formatter->priv->stream,
- "<b>(empty)</b>");
- }
-
- debug ("handle_text_html: exiting\n");
-}
-
-static void
-handle_image (CamelFormatter *formatter, CamelDataWrapper *wrapper)
-{
- gchar* uuid;
- gchar* tag;
-
- debug ("handle_image: entered\n");
-
- uuid = lookup_unique_id (formatter->priv->current_root, wrapper);
-
- tag = g_strdup_printf ("<img src=\"camel://%s\">\n", uuid);
- camel_stream_write_string (formatter->priv->stream, tag);
- debug ("handle_image: tag=%s\n", tag);
- g_free (uuid);
- g_free (tag);
-
- debug ("handle_image: exiting\n");
-}
-
-static void
-handle_vcard (CamelFormatter *formatter, CamelDataWrapper *wrapper)
-{
-// gchar* vcard = NULL;
- debug ("handle_vcard: entered\n");
-
- camel_stream_write_string (formatter->priv->stream,
- "\n<!-- image below -->\n");
-// camel_stream_write_string (formatter->priv->stream, vcard);
-// g_free (vcard);
-
- debug ("handle_vcard: exiting\n");
-}
-
-static void
-handle_mime_part (CamelFormatter *formatter,
- CamelDataWrapper *wrapper)
-{
- CamelMimePart* mime_part;
- CamelDataWrapper* message_contents;
- gchar *whole_mime_type;
-
- g_assert (formatter);
- g_assert (wrapper);
- g_assert (CAMEL_IS_MIME_PART (wrapper));
-
-
- mime_part = CAMEL_MIME_PART (wrapper);
- message_contents =
- camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
-
- g_assert (message_contents);
-
- debug ("handle_mime_part: entered\n");
- camel_stream_write_string (formatter->priv->stream,
- "\n<!-- mime message below -->\n");
-
-// camel_stream_write_string (formatter->priv->stream,
-// "<table width=95% border=1><tr><td>\n\n");
-
- /* dispatch the correct handler function for the mime type */
- whole_mime_type = MIME_TYPE_WHOLE (mime_part);
- call_handler_function (formatter, message_contents,
- whole_mime_type,
- MIME_TYPE_MAIN (mime_part));
- g_free (whole_mime_type);
-
- /* close up the table we opened */
-// camel_stream_write_string (formatter->priv->stream,
-// "\n\n</td></tr></table>\n\n");
-
- debug ("handle_mime_part: exiting\n");
-}
-
-
-/*
- * multipart-alternative helper function --
- * returns NULL if no text/html or text/plan msg is found
- */
-static CamelMimePart*
-find_preferred_displayable_body_part_in_multipart_alternative (
- CamelMultipart* multipart)
-{
- int i, max_multiparts;
- CamelMimePart* html_part = NULL;
- CamelMimePart* plain_part = NULL;
-
- /* find out out many parts are in it...*/
- max_multiparts = camel_multipart_get_number (multipart);
-
- /* TODO: DO LEAF-LOOKUP HERE FOR OTHER MIME-TYPES!!! */
-
- for (i = 0; i < max_multiparts; i++) {
- CamelMimeBodyPart* body_part =
- camel_multipart_get_part (multipart, i);
-
- if (!strcase_equal (MIME_TYPE_MAIN (body_part), "text"))
- continue;
-
- if (strcase_equal (MIME_TYPE_SUB (body_part), "plain")) {
- plain_part = CAMEL_MIME_PART (body_part);
- }
- else if (strcase_equal (MIME_TYPE_SUB (body_part), "html")) {
- html_part = CAMEL_MIME_PART (body_part);
- }
- }
-
- if (html_part)
- return html_part;
- if (plain_part)
- return plain_part;
- return NULL;
-}
-
-
-/* called for each body part in a multipart/mixed */
-static void
-print_camel_body_part (CamelMimeBodyPart* body_part,
- CamelFormatter* formatter,
- gboolean* text_printed_yet)
-{
- gchar *whole_mime_type;
-
- CamelDataWrapper* contents =
- camel_medium_get_content_object (CAMEL_MEDIUM (body_part));
- gboolean is_text =
- strcase_equal (MIME_TYPE_MAIN (body_part), "text");
-
- if (is_text && *text_printed_yet)
- return;
- whole_mime_type = MIME_TYPE_WHOLE (body_part);
- call_handler_function (formatter, contents, whole_mime_type,
- MIME_TYPE_MAIN (body_part));
- g_free (whole_mime_type);
-
- camel_stream_write_string (formatter->priv->stream, "\n\n");
- /* use this when gtktmhl is fixed */
- /* camel_stream_write_string (formatter->priv->stream, "\n<hr>\n"); */
-}
-
-
-
-/* Our policy here is this:
- (1) print text/(plain|html) parts found
- (2) print vcards and images inline
- (3) treat all other parts as attachments */
-static void
-handle_multipart_mixed (CamelFormatter *formatter,
- CamelDataWrapper *wrapper)
-{
- CamelMultipart* mp;
- gboolean text_printed_yet = FALSE;
-
- g_assert (formatter);
- g_assert (wrapper);
- g_assert (CAMEL_IS_MULTIPART (wrapper));
-
- mp = CAMEL_MULTIPART (wrapper);
- g_assert (mp);
-
-// debug ("handle_multipart_mixed: entered\n");
-
-
- {
- int i, max_multiparts;
-
- max_multiparts = camel_multipart_get_number (mp);
- for (i = 0; i < max_multiparts; i++) {
- CamelMimeBodyPart* body_part =
- camel_multipart_get_part (mp, i);
-
- print_camel_body_part (body_part, formatter, &text_printed_yet);
- }
- }
-
-
-// debug ("handle_multipart_mixed: exiting\n");
-}
-
-static void
-handle_multipart_related (CamelFormatter *formatter,
- CamelDataWrapper *wrapper)
-{
-// CamelMultipart* mp = CAMEL_MULTIPART (wrapper);
- debug ("handle_multipart_related: entered\n");
-
- debug ("handle_multipart_related: NYI!!\n");
-
- /* TODO: read RFC, in terms of how a one message
- may refer to another object */
-
- debug ("handle_multipart_related: exiting\n");
-}
-
-/*
- The current policy for multipart/alternative is this:
-
- if (we find a text/html body part)
- we print it
- else if (we find a text/plain body part)
- we print it
- else
- we print nothing
-*/
-static void
-handle_multipart_alternative (CamelFormatter *formatter,
- CamelDataWrapper *wrapper)
-{
- CamelMultipart* multipart = CAMEL_MULTIPART (wrapper);
- CamelMimePart* mime_part;
- gchar *whole_mime_type;
-
- debug ("handle_multipart_alternative: entered\n");
-
- mime_part =
- find_preferred_displayable_body_part_in_multipart_alternative(
- multipart);
- if (mime_part) {
-
- CamelDataWrapper* contents =
- camel_medium_get_content_object (
- CAMEL_MEDIUM (mime_part));
-
- whole_mime_type = MIME_TYPE_WHOLE (mime_part);
- call_handler_function (formatter, contents,
- whole_mime_type,
- MIME_TYPE_MAIN (mime_part));
- g_free (whole_mime_type);
- }
-
- debug ("handle_multipart_alternative: exiting\n");
-}
-
-static void
-handle_unknown_type (CamelFormatter *formatter,
- CamelDataWrapper *wrapper)
-{
- gchar* tag;
- CamelDataWrapper* root = formatter->priv->current_root;
- char* uid = lookup_unique_id (root, wrapper);
-
- debug ("handle_unknown_type: entered\n");
-
- tag = g_strdup_printf ("<a href=\"camel://%s\">click-me-to-save</a>\n",
- uid);
-
- camel_stream_write_string (formatter->priv->stream, tag);
-
- debug ("handle_unknown_type: exiting\n");
-}
-
-/*----------------------------------------------------------------------*
- * Standard Gtk+ class functions
- *----------------------------------------------------------------------*/
-
-CamelFormatter*
-camel_formatter_new ()
-{
- return (gtk_type_new (CAMEL_FORMATTER_TYPE));
-}
-
-
-static void
-_finalize (GtkObject* object)
-{
- CamelFormatter *formatter = CAMEL_FORMATTER (object);
-
- if (formatter->priv->attachments)
- g_hash_table_destroy (formatter->priv->attachments);
-
- g_free (formatter->priv);
-
- GTK_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-camel_formatter_class_init (CamelFormatterClass *camel_formatter_class)
-{
- GtkObjectClass *gtk_object_class =
- GTK_OBJECT_CLASS (camel_formatter_class);
-
- parent_class = gtk_type_class (gtk_object_get_type ());
-
- mime_function_table =
- g_hash_table_new (g_str_hash, strcase_equal);
-
-#define ADD_HANDLER(a,b) g_hash_table_insert (mime_function_table, a, b)
-
- /* hook up mime types to functions that handle them */
- ADD_HANDLER ("text/plain", handle_text_plain);
- ADD_HANDLER ("text/richtext", handle_text_plain);
- ADD_HANDLER ("text/html", handle_text_html);
- ADD_HANDLER ("multipart/alternative", handle_multipart_alternative);
- ADD_HANDLER ("multipart/related", handle_multipart_related);
- ADD_HANDLER ("multipart/mixed", handle_multipart_mixed);
- ADD_HANDLER ("message/rfc822", handle_mime_part);
- ADD_HANDLER ("image", handle_image);
- ADD_HANDLER ("vcard", handle_vcard);
-
- /* body parts don't have mime parts per se, so camel
- sticks on the following one */
- ADD_HANDLER ("mime/body-part", handle_mime_part);
-
- /* virtual method overload */
- gtk_object_class->finalize = _finalize;
-}
-
-
-static void
-camel_formatter_init (gpointer object, gpointer klass)
-{
- CamelFormatter* cmf = CAMEL_FORMATTER (object);
- cmf->priv = g_new (CamelFormatterPrivate, 1);
- cmf->priv->attachments = NULL;
-}
-
-
-GtkType
-camel_formatter_get_type (void)
-{
- static GtkType camel_formatter_type = 0;
-
- if (!camel_formatter_type) {
- GtkTypeInfo camel_formatter_info =
- {
- "CamelFormatter",
- sizeof (CamelFormatter),
- sizeof (CamelFormatterClass),
- (GtkClassInitFunc) camel_formatter_class_init,
- (GtkObjectInitFunc) camel_formatter_init,
- /* reserved_1 */ NULL,
- /* reserved_2 */ NULL,
- (GtkClassInitFunc) NULL,
- };
-
- camel_formatter_type = gtk_type_unique (
- gtk_object_get_type (),
- &camel_formatter_info);
- }
-
- return camel_formatter_type;
-}