From 3d7a8fdeac2dfa5068844a42f6c564d186bd21db Mon Sep 17 00:00:00 2001 From: Bertrand Guiheneuf Date: Sun, 1 Aug 1999 13:42:43 +0000 Subject: Adding missing files svn path=/trunk/; revision=1053 --- camel/camel-mime-body-part.c | 123 +++++++ camel/camel-mime-body-part.h | 82 +++++ camel/camel-multipart.c | 467 ++++++++++++++++++++++++++ camel/camel-multipart.h | 105 ++++++ camel/camel.c | 30 ++ camel/camel.h | 43 +++ camel/data-wrapper-repository.c | 124 +++++++ camel/data-wrapper-repository.h | 53 +++ camel/string-utils.c | 251 ++++++++++++++ camel/string-utils.h | 67 ++++ devel-docs/camel/tmpl/camel-data-wrapper.sgml | 26 ++ tests/test3.c | 28 ++ 12 files changed, 1399 insertions(+) create mode 100644 camel/camel-mime-body-part.c create mode 100644 camel/camel-mime-body-part.h create mode 100644 camel/camel-multipart.c create mode 100644 camel/camel-multipart.h create mode 100644 camel/camel.c create mode 100644 camel/camel.h create mode 100644 camel/data-wrapper-repository.c create mode 100644 camel/data-wrapper-repository.h create mode 100644 camel/string-utils.c create mode 100644 camel/string-utils.h create mode 100644 devel-docs/camel/tmpl/camel-data-wrapper.sgml create mode 100644 tests/test3.c diff --git a/camel/camel-mime-body-part.c b/camel/camel-mime-body-part.c new file mode 100644 index 0000000000..3b0c547bfa --- /dev/null +++ b/camel/camel-mime-body-part.c @@ -0,0 +1,123 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* camel-mime-body-part.c : Abstract class for a mime body part */ + + +/* + * + * Copyright (C) 1999 Bertrand Guiheneuf . + * + * 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 Place, Suite 330, Boston, MA 02111-1307 + * USA + */ +#include +#include "camel-mime-body-part.h" +#include "camel-log.h" + + +static void _set_parent (CamelMimeBodyPart *mime_body_part, CamelMultipart *multipart); +static const CamelMultipart *_get_parent (CamelMimeBodyPart *mime_body_part); + + +static CamelMimePartClass *parent_class=NULL; + +/* Returns the class for a CamelMimeBodyPart */ +#define CMBP_CLASS(so) CAMEL_MIME_BODY_PART_CLASS (GTK_OBJECT(so)->klass) + + + +static void +camel_mime_body_part_class_init (CamelMimeBodyPartClass *camel_mime_body_part_class) +{ + CamelMimePartClass *camel_mime_part_class = CAMEL_MIME_PART_CLASS (camel_mime_body_part_class); + parent_class = gtk_type_class (camel_mime_part_get_type ()); + + /* virtual method definition */ + camel_mime_body_part_class->set_parent = _set_parent; + camel_mime_body_part_class->get_parent = _get_parent; +} + +static void +camel_mime_body_part_init (gpointer object, gpointer klass) +{ + CamelMimeBodyPart *camel_mime_body_part = CAMEL_MIME_BODY_PART (object); +} + + + + +GtkType +camel_mime_body_part_get_type (void) +{ + static GtkType camel_mime_body_part_type = 0; + + if (!camel_mime_body_part_type) { + GtkTypeInfo camel_mime_body_part_info = + { + "CamelMimeBodyPart", + sizeof (CamelMimeBodyPart), + sizeof (CamelMimeBodyPartClass), + (GtkClassInitFunc) camel_mime_body_part_class_init, + (GtkObjectInitFunc) camel_mime_body_part_init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + camel_mime_body_part_type = gtk_type_unique (camel_mime_part_get_type (), &camel_mime_body_part_info); + } + + return camel_mime_body_part_type; +} + +CamelMimeBodyPart * +camel_mime_body_part_new () +{ + CamelMimeBodyPart *mime_body_part; + CAMEL_LOG_FULL_DEBUG ("CamelMimeBodyPart:: Entering new()\n"); + + mime_body_part = (CamelMimeBodyPart *)gtk_type_new (CAMEL_MIME_BODY_PART_TYPE); + CAMEL_LOG_FULL_DEBUG ("CamelMimeBodyPart:: Leaving new()\n"); + return mime_body_part; +} + + +static void +_set_parent (CamelMimeBodyPart *mime_body_part, CamelMultipart *multipart) +{ + mime_body_part->parent = multipart; +} + + +void +camel_mime_body_part_set_parent (CamelMimeBodyPart *mime_body_part, CamelMultipart *multipart) +{ + CMBP_CLASS (mime_body_part)->set_parent (mime_body_part, multipart); +} + + +static const CamelMultipart * +_get_parent (CamelMimeBodyPart *mime_body_part) +{ + return mime_body_part->parent; +} + + +const CamelMultipart * +camel_mime_body_part_get_parent (CamelMimeBodyPart *mime_body_part) +{ + return CMBP_CLASS (mime_body_part)->get_parent (mime_body_part); +} + + diff --git a/camel/camel-mime-body-part.h b/camel/camel-mime-body-part.h new file mode 100644 index 0000000000..eb721f3b60 --- /dev/null +++ b/camel/camel-mime-body-part.h @@ -0,0 +1,82 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* camel-mime-body-part.h : class for a mime body part */ + +/* + * + * Copyright (C) 1999 Bertrand Guiheneuf . + * + * 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 Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + + +#ifndef CAMEL_MIME_BODY_PART_H +#define CAMEL_MIME_BODY_PART_H 1 + + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus }*/ + +typedef struct _CamelMimeBodyPart CamelMimeBodyPart; + +#include +#include "camel-mime-part.h" +#include "camel-multipart.h" + + + +#define CAMEL_MIME_BODY_PART_TYPE (camel_mime_body_part_get_type ()) +#define CAMEL_MIME_BODY_PART(obj) (GTK_CHECK_CAST((obj), CAMEL_MIME_BODY_PART_TYPE, CamelMimeBodyPart)) +#define CAMEL_MIME_BODY_PART_CLASS(k) (GTK_CHECK_CLASS_CAST ((k), CAMEL_MIME_BODY_PART_TYPE, CamelMimeBodyPartClass)) +#define IS_CAMEL_MIME_BODY_PART(o) (GTK_CHECK_TYPE((o), CAMEL_MIME_BODY_PART_TYPE)) + + +struct _CamelMimeBodyPart +{ + CamelMimePart parent_object; + CamelMultipart *parent; + +}; + + + +typedef struct { + CamelMimePartClass parent_class; + + /* Virtual methods */ + void (*set_parent) (CamelMimeBodyPart *mime_body_part, CamelMultipart *multipart); + const CamelMultipart * (*get_parent) (CamelMimeBodyPart *mime_body_part); + +} CamelMimeBodyPartClass; + + +/* Standard Gtk function */ +GtkType camel_mime_body_part_get_type (void); + + +/* public methods */ +CamelMimeBodyPart *camel_mime_body_part_new (); +void camel_mime_body_part_set_parent (CamelMimeBodyPart *mime_body_part, CamelMultipart *multipart); +const CamelMultipart *camel_mime_body_part_get_parent (CamelMimeBodyPart *mime_body_part); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CAMEL_MIME_BODY_PART_H */ + diff --git a/camel/camel-multipart.c b/camel/camel-multipart.c new file mode 100644 index 0000000000..05203dba13 --- /dev/null +++ b/camel/camel-multipart.c @@ -0,0 +1,467 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* camel-multipart.c : Abstract class for a multipart */ + + +/* + * + * Copyright (C) 1999 Bertrand Guiheneuf . + * + * 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 Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include +#include "camel-multipart.h" +#include "camel-log.h" +#include "gmime-content-field.h" +#include "gmime-utils.h" + + +static void _add_part (CamelMultipart *multipart, CamelMimeBodyPart *part); +static void _add_part_at (CamelMultipart *multipart, CamelMimeBodyPart *part, guint index); +static void _remove_part (CamelMultipart *multipart, CamelMimeBodyPart *part); +static CamelMimeBodyPart *_remove_part_at (CamelMultipart *multipart, guint index); +static CamelMimeBodyPart *_get_part (CamelMultipart *multipart, guint index); +static guint _get_number (CamelMultipart *multipart); +static void _set_parent (CamelMultipart *multipart, CamelMimePart *parent); +static CamelMimePart *_get_parent (CamelMultipart *multipart); +static void _set_boundary (CamelMultipart *multipart, gchar *boundary); +static const gchar *_get_boundary (CamelMultipart *multipart); +static void _write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream); +static void _construct_from_stream (CamelDataWrapper *data_wrapper, CamelStream *stream); + +static CamelDataWrapperClass *parent_class=NULL; + +/* Returns the class for a CamelMultipart */ +#define CMP_CLASS(so) CAMEL_MULTIPART_CLASS (GTK_OBJECT(so)->klass) + +/* Returns the class for a CamelDataWrapper */ +#define CDW_CLASS(so) CAMEL_DATA_WRAPPER_CLASS (GTK_OBJECT(so)->klass) + + +static void +camel_multipart_class_init (CamelMultipartClass *camel_multipart_class) +{ + CamelDataWrapperClass *camel_data_wrapper_class = CAMEL_DATA_WRAPPER_CLASS (camel_multipart_class); + parent_class = gtk_type_class (camel_data_wrapper_get_type ()); + + /* virtual method definition */ + camel_multipart_class->add_part = _add_part; + camel_multipart_class->add_part_at = _add_part_at; + camel_multipart_class->remove_part = _remove_part; + camel_multipart_class->remove_part_at = _remove_part_at; + camel_multipart_class->get_part = _get_part; + camel_multipart_class->get_number = _get_number; + camel_multipart_class->set_parent = _set_parent; + camel_multipart_class->get_parent = _get_parent; + camel_multipart_class->set_boundary = _set_boundary; + camel_multipart_class->get_boundary = _get_boundary; + + /* virtual method overload */ + camel_data_wrapper_class->write_to_stream = _write_to_stream; + camel_data_wrapper_class->construct_from_stream = _construct_from_stream; +} + +static void +camel_multipart_init (gpointer object, gpointer klass) +{ + CamelMultipart *multipart = CAMEL_MULTIPART (object); + camel_data_wrapper_set_mime_type ( CAMEL_DATA_WRAPPER (multipart), "multipart"); + camel_multipart_set_boundary (multipart, "__camel_boundary__"); + +} + + + + +GtkType +camel_multipart_get_type (void) +{ + static GtkType camel_multipart_type = 0; + + if (!camel_multipart_type) { + GtkTypeInfo camel_multipart_info = + { + "CamelMultipart", + sizeof (CamelMultipart), + sizeof (CamelMultipartClass), + (GtkClassInitFunc) camel_multipart_class_init, + (GtkObjectInitFunc) camel_multipart_init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + camel_multipart_type = gtk_type_unique (camel_data_wrapper_get_type (), &camel_multipart_info); + } + + return camel_multipart_type; +} + + +CamelMultipart * +camel_multipart_new () +{ + CamelMultipart *multipart; + CAMEL_LOG_FULL_DEBUG ("CamelMultipart:: Entering new()\n"); + + multipart = (CamelMultipart *)gtk_type_new (CAMEL_MULTIPART_TYPE); + multipart->preface = NULL; + multipart->postface = NULL; + + CAMEL_LOG_FULL_DEBUG ("CamelMultipart:: Leaving new()\n"); + return multipart; +} + + +static void +_add_part (CamelMultipart *multipart, CamelMimeBodyPart *part) +{ + multipart->parts = g_list_append (multipart->parts, part); +} + +void +camel_multipart_add_part (CamelMultipart *multipart, CamelMimeBodyPart *part) +{ + CMP_CLASS (multipart)->add_part (multipart, part); +} + + +static void +_add_part_at (CamelMultipart *multipart, CamelMimeBodyPart *part, guint index) +{ + multipart->parts = g_list_insert (multipart->parts, part, index); +} + +void +camel_multipart_add_part_at (CamelMultipart *multipart, CamelMimeBodyPart *part, guint index) +{ + CMP_CLASS (multipart)->add_part_at (multipart, part, index); +} + +static void +_remove_part (CamelMultipart *multipart, CamelMimeBodyPart *part) +{ + if (!multipart->parts) { + CAMEL_LOG_FULL_DEBUG ("CamelMultipart::remove_part part list id void\n"); + return; + } + multipart->parts = g_list_remove (multipart->parts, part); +} + +void +camel_multipart_remove_part (CamelMultipart *multipart, CamelMimeBodyPart *part) +{ + CMP_CLASS (multipart)->remove_part (multipart, part); +} + + +static CamelMimeBodyPart * +_remove_part_at (CamelMultipart *multipart, guint index) +{ + GList *parts_list; + GList *part_to_remove; + CamelMimeBodyPart *removed_body_part; + + CAMEL_LOG_FULL_DEBUG ("CamelMultipart:: Entering remove_part_at\n"); + CAMEL_LOG_TRACE ("CamelMultipart::remove_part_at : Removing part number %d\n", index); + + if (!(multipart->parts)) { + CAMEL_LOG_FULL_DEBUG ("CamelMultipart::remove_part_at part list is void \n"); + return; + } + + parts_list = multipart->parts; + part_to_remove = g_list_nth (parts_list, index); + if (!part_to_remove) { + CAMEL_LOG_WARNING ("CamelMultipart::remove_part_at : part to remove is NULL\n"); + CAMEL_LOG_FULL_DEBUG ("CamelMultipart::remove_part_at : index = %d, number of parts=%d\n", + index, g_list_length (parts_list)); + return NULL; + } + removed_body_part = CAMEL_MIME_BODY_PART (part_to_remove->data); + + multipart->parts = g_list_remove_link (parts_list, part_to_remove); + g_list_free_1 (part_to_remove); + + CAMEL_LOG_FULL_DEBUG ("CamelMultipart:: Leaving remove_part_at\n"); + return removed_body_part; + +} + +CamelMimeBodyPart * +camel_multipart_remove_part_at (CamelMultipart *multipart, guint index) +{ + return CMP_CLASS (multipart)->remove_part_at (multipart, index); +} + + +static CamelMimeBodyPart * +_get_part (CamelMultipart *multipart, guint index) +{ + GList *part; + if (!(multipart->parts)) { + CAMEL_LOG_FULL_DEBUG ("CamelMultipart::get_part part list is void \n"); + return NULL; + } + + part = g_list_nth (multipart->parts, index); + if (part) return CAMEL_MIME_BODY_PART (part->data); + else { + CAMEL_LOG_FULL_DEBUG ("CamelMultipart::get_part part number %d not found\n", index); + return NULL; + } +} + +CamelMimeBodyPart * +camel_multipart_get_part (CamelMultipart *multipart, guint index) +{ + return CMP_CLASS (multipart)->get_part (multipart, index); +} + + +static guint +_get_number (CamelMultipart *multipart) +{ + return g_list_length (multipart->parts); +} + +guint +camel_multipart_get_number (CamelMultipart *multipart) +{ + return CMP_CLASS (multipart)->get_number (multipart); +} + + +static void +_set_parent (CamelMultipart *multipart, CamelMimePart *parent) +{ + multipart->parent = parent; +} + +void +camel_multipart_set_parent (CamelMultipart *multipart, CamelMimePart *parent) +{ + CMP_CLASS (multipart)->set_parent (multipart, parent); +} + + +static CamelMimePart * +_get_parent (CamelMultipart *multipart) +{ + return multipart->parent; +} + + +CamelMimePart * +camel_multipart_get_parent (CamelMultipart *multipart) +{ + return CMP_CLASS (multipart)->get_parent (multipart); +} + + + + + +static void +_set_boundary (CamelMultipart *multipart, gchar *boundary) +{ + gmime_content_field_set_parameter (CAMEL_DATA_WRAPPER (multipart)->mime_type, "boundary", boundary); +} + +void +camel_multipart_set_boundary (CamelMultipart *multipart, gchar *boundary) +{ + CMP_CLASS (multipart)->set_boundary (multipart, boundary); +} + + +static const gchar * +_get_boundary (CamelMultipart *multipart) +{ + const gchar *boundary; + CAMEL_LOG_FULL_DEBUG ("Entering CamelMultipart::_get_boundary\n"); + if (!CAMEL_DATA_WRAPPER (multipart)->mime_type) { + CAMEL_LOG_WARNING ("CamelMultipart::_get_boundary CAMEL_DATA_WRAPPER (multipart)->mime_type is NULL\n"); + return; + } + boundary = gmime_content_field_get_parameter (CAMEL_DATA_WRAPPER (multipart)->mime_type, "boundary"); + CAMEL_LOG_FULL_DEBUG ("Leaving CamelMultipart::_get_boundary\n"); + return boundary; +} + + +const gchar * +camel_multipart_get_boundary (CamelMultipart *multipart) +{ + return CMP_CLASS (multipart)->get_boundary (multipart); +} + + +struct _print_part_user_data { + CamelStream *stream; + const gchar *boundary; +}; + + + +static void +_print_part (gpointer data, gpointer user_data) +{ + CamelMimeBodyPart *body_part = CAMEL_MIME_BODY_PART (data); + struct _print_part_user_data *ud = (struct _print_part_user_data *)user_data; + + if (ud->boundary) camel_stream_write_strings (ud->stream, "\n--", ud->boundary, "\n", NULL); + else camel_stream_write_strings (ud->stream, "\n--\n", NULL); + camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (body_part), ud->stream); + + +} + + + +static void +_write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) +{ + CamelMultipart *multipart = CAMEL_MULTIPART (data_wrapper); + struct _print_part_user_data ud; + const gchar *boundary; + + CAMEL_LOG_FULL_DEBUG ("Entering CamelMultipart::_write_to_stream entering\n"); + boundary = camel_multipart_get_boundary (multipart); + CAMEL_LOG_FULL_DEBUG ("Entering CamelMultipart::_write_to_stream, boundary = %s\n", boundary); + g_return_if_fail (boundary); + ud.boundary = boundary; + ud.stream = stream; + if (multipart->preface) camel_stream_write_strings (stream, multipart->preface, NULL); + g_list_foreach (multipart->parts, _print_part, (gpointer)&ud); + camel_stream_write_strings (stream, "\n--", boundary, "--\n", NULL); + if (multipart->postface) camel_stream_write_strings (stream, multipart->postface, NULL); + CAMEL_LOG_FULL_DEBUG ("Leaving CamelMultipart::_write_to_stream leaving \n"); +} + + + + +/** + * _read_part: read one part in a multipart environement. + * @part: GString to add the part to + * @stream: the stream to read the lines from. + * @normal_boundary: end of part bundary. + * @end_boundary: end of multipart boundary. + * + * This routine is a bit special: RFC 2046 says that, in a multipart + * environment, the last crlf before a boundary belongs to the boundary. + * Thus, if there is no blank line before the boundary, the last crlf + * of the last line of the part is removed. + * + * Return value: false if the last boundary element has been met true otherwise. + **/ + +static gboolean +_read_part (GString *new_part, CamelStream *stream, gchar *normal_boundary, gchar *end_boundary) +{ + gchar *new_line; + gboolean end_of_part; + gboolean last_part; + gboolean pending_crlf = FALSE; + guint line_length; + + /* RFC 2046 precises that when parsing the content of a multipart + * element, the program should not think it will find the last bounndary, + * and in particular, the message could have been damaged during + * transport, the parsing should be OK */ + CAMEL_LOG_FULL_DEBUG ("CamelMultipart:: Entering _read_part\n"); +#if 0 + do { + new_line = gmime_read_line_from_stream (stream); + printf ("++ new line = \"%s\"\n", new_line); + if (new_line) { + end_of_part = (strcmp (new_line, normal_boundary) == 0); + last_part = (strcmp (new_line, end_boundary) == 0); + if (!end_of_part && !last_part) { + if (pending_crlf) { + new_part = g_string_append_c (new_part, '\n'); + pending_crlf = FALSE; + } + line_length = strlen (new_line); + if (new_line[line_length-1]='\n') { + pending_crlf = TRUE; + new_line[line_length-1]='\0'; + } + new_part = g_string_append (new_part, new_line); + } + } + + } ; +#endif + new_line = gmime_read_line_from_stream (stream); + while (new_line && !end_of_part && !last_part) { + printf ("++ new line = \"%s\"\n", new_line); + end_of_part = (strcmp (new_line, normal_boundary) == 0); + last_part = (strcmp (new_line, end_boundary) == 0); + if (!end_of_part && !last_part) + new_part = g_string_append (new_part, new_line); + new_line = gmime_read_line_from_stream (stream); + } + CAMEL_LOG_FULL_DEBUG ("CamelMultipart:: Leaving _read_part\n"); + return (!last_part && new_line); +} + +static void +_construct_from_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) +{ + CamelMultipart *multipart = CAMEL_MULTIPART (data_wrapper); + const gchar *boundary; + gchar *real_boundary_line; + gchar *end_boundary_line; + GString *new_part; + gboolean end_of_multipart; + CamelMimeBodyPart *body_part; + + CAMEL_LOG_FULL_DEBUG ("Entering CamelMultipart::_construct_from_stream\n"); + boundary = camel_multipart_get_boundary (multipart); + g_return_if_fail (boundary); + + real_boundary_line = g_strdup_printf ("--%s", boundary); + end_boundary_line = g_strdup_printf ("--%s--", boundary); + + new_part = g_string_new (""); + + /* read the prefix if any */ + end_of_multipart = _read_part (new_part, stream, real_boundary_line, end_boundary_line); + if (multipart->preface) g_free (multipart->preface); + if ( (new_part->str)[0] != '\0') multipart->preface = g_strdup (new_part->str); + + /* read all the real parts */ + while (!end_of_multipart) { + CAMEL_LOG_FULL_DEBUG ("CamelMultipart::construct_from_stream, detected a new part\n"); + g_string_assign (new_part, ""); + body_part = camel_mime_body_part_new (); + //camel_data_wrapper_construct_from_stream (); + camel_multipart_add_part (multipart, body_part); + end_of_multipart = _read_part (new_part, stream, real_boundary_line, end_boundary_line); + } + + g_string_assign (new_part, ""); + _read_part (new_part, stream, real_boundary_line, end_boundary_line); + if (multipart->postface) g_free (multipart->postface); + if ( (new_part->str)[0] != '\0') multipart->postface = g_strdup (new_part->str); + + g_string_free (new_part, TRUE); + g_free (real_boundary_line); + g_free (end_boundary_line); + CAMEL_LOG_FULL_DEBUG ("Leaving CamelMultipart::_construct_from_stream\n"); +} diff --git a/camel/camel-multipart.h b/camel/camel-multipart.h new file mode 100644 index 0000000000..64f98d0c65 --- /dev/null +++ b/camel/camel-multipart.h @@ -0,0 +1,105 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* camel-multipart.h : class for a multipart */ + +/* + * + * Copyright (C) 1999 Bertrand Guiheneuf . + * + * 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 Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + + +#ifndef CAMEL_MULTIPART_H +#define CAMEL_MULTIPART_H 1 + + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus }*/ + +typedef struct _CamelMultipart CamelMultipart; + +#include +#include "camel-mime-part.h" +#include "camel-mime-body-part.h" + + +#define CAMEL_MULTIPART_TYPE (camel_multipart_get_type ()) +#define CAMEL_MULTIPART(obj) (GTK_CHECK_CAST((obj), CAMEL_MULTIPART_TYPE, CamelMultipart)) +#define CAMEL_MULTIPART_CLASS(k) (GTK_CHECK_CLASS_CAST ((k), CAMEL_MULTIPART_TYPE, CamelMultipartClass)) +#define IS_CAMEL_MULTIPART(o) (GTK_CHECK_TYPE((o), CAMEL_MULTIPART_TYPE)) + + +struct _CamelMultipart +{ + CamelDataWrapper parent_object; + + CamelMimePart *parent; + GList *parts; + gchar *boundary; + gchar *preface; + gchar *postface; + +}; + + + +typedef struct { + CamelDataWrapperClass parent_class; + + /* Virtual methods */ + void (*add_part) (CamelMultipart *multipart, CamelMimeBodyPart *part); + void (*add_part_at) (CamelMultipart *multipart, CamelMimeBodyPart *part, guint index); + void (*remove_part) (CamelMultipart *multipart, CamelMimeBodyPart *part); + CamelMimeBodyPart * (*remove_part_at) (CamelMultipart *multipart, guint index); + CamelMimeBodyPart * (*get_part) (CamelMultipart *multipart, guint index); + guint (*get_number) (CamelMultipart *multipart); + void (*set_parent) (CamelMultipart *multipart, CamelMimePart *parent); + CamelMimePart * (*get_parent) (CamelMultipart *multipart); + void (*set_boundary) (CamelMultipart *multipart, gchar *boundary); + const gchar * (*get_boundary) (CamelMultipart *multipart); + +} CamelMultipartClass; + + +/* Standard Gtk function */ +GtkType camel_multipart_get_type (void); + + +/* public methods */ +CamelMultipart *camel_multipart_new (); +void camel_multipart_add_part (CamelMultipart *multipart, CamelMimeBodyPart *part); +void camel_multipart_add_part_at (CamelMultipart *multipart, CamelMimeBodyPart *part, guint index); +void camel_multipart_remove_part (CamelMultipart *multipart, CamelMimeBodyPart *part); +CamelMimeBodyPart *camel_multipart_remove_part_at (CamelMultipart *multipart, guint index); +CamelMimeBodyPart *camel_multipart_get_part (CamelMultipart *multipart, guint index); +guint camel_multipart_get_number (CamelMultipart *multipart); +void camel_multipart_set_parent (CamelMultipart *multipart, CamelMimePart *parent); +CamelMimePart *camel_multipart_get_parent (CamelMultipart *multipart); +void camel_multipart_set_boundary (CamelMultipart *multipart, gchar *boundary); +const gchar *camel_multipart_get_boundary (CamelMultipart *multipart); + + + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CAMEL_MULTIPART_H */ + diff --git a/camel/camel.c b/camel/camel.c new file mode 100644 index 0000000000..706041879f --- /dev/null +++ b/camel/camel.c @@ -0,0 +1,30 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * + * Copyright (C) 1999 Bertrand Guiheneuf . + * + * 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 Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include "camel.h" + +gint +camel_init() +{ + return data_wrapper_repository_init (); + +} diff --git a/camel/camel.h b/camel/camel.h new file mode 100644 index 0000000000..c0548f5e10 --- /dev/null +++ b/camel/camel.h @@ -0,0 +1,43 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * + * Copyright (C) 1999 Bertrand Guiheneuf . + * + * 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 Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + + +#ifndef CAMEL_H +#define CAMEL_H 1 + + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus }*/ + +#include +#include +#include + +gint camel_init (); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CAMEL_H */ diff --git a/camel/data-wrapper-repository.c b/camel/data-wrapper-repository.c new file mode 100644 index 0000000000..147a92b831 --- /dev/null +++ b/camel/data-wrapper-repository.c @@ -0,0 +1,124 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * + * Copyright (C) 1999 Bertrand Guiheneuf . + * + * 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 Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + + + + +#include "data-wrapper-repository.h" +#include "camel-multipart.h" + + + +static DataWrapperRepository _repository; +static _initialized = -1; +GMimeContentField *_content_field; + + + +/** + * data_wrapper_repository_init: initialize data wrapper repository + * + * initialize the data wrapper repository. When the repository has + * already been initialized, returns -1. + * + * Return value: 1 if correctly initialized returns -1. + **/ +gint +data_wrapper_repository_init () +{ + if (_initialized != -1) return -1; + _repository.mime_links = g_hash_table_new (g_str_hash, g_str_equal); + data_wrapper_set_data_wrapper_type ("multipart", camel_multipart_get_type()); + _content_field = gmime_content_field_new (NULL, NULL); + _initialized = 1; + return 1; +} + +/** + * data_wrapper_set_data_wrapper_type: associate a data wrapper object type to a mime type + * @mime_type: mime type + * @object_type: object type + * + * Associate an object type to a mime type. + **/ +void +data_wrapper_set_data_wrapper_type (const gchar *mime_type, GtkType object_type) +{ + gboolean already_exists; + gchar *old_mime_type; + GtkType old_gtk_type; + + already_exists = g_hash_table_lookup_extended (_repository.mime_links, (gpointer)mime_type, + (gpointer)&old_mime_type, (gpointer)&old_gtk_type); + if (already_exists) + g_hash_table_insert (_repository.mime_links, (gpointer)old_mime_type, (gpointer)object_type); + else + g_hash_table_insert (_repository.mime_links, (gpointer)g_strdup (mime_type), (gpointer)object_type); +} + + + +/** + * data_wrapper_get_data_wrapper_type: get the gtk type object associated to a mime type + * @mime_type: mime type + * + * returns the GtkType of the data wrapper object associated to + * a particular mime type. The mime type must be a character string + * of the form "type/subtype" or simply "type". When the complete + * mime type ("type/subtype") is not associated to any particular + * data wrapper object, this routine looks for a default data wrapper + * for the main mime type ("type"). When no particular association is + * found for this mime type, the type of the SimpleDataWrapper is + * returned. + * + * + * Return value: the associated data wrapper object type. + **/ +GtkType +data_wrapper_get_data_wrapper_type (const gchar *mime_type) +{ + gboolean exists; + gchar *old_mime_type; + GtkType gtk_type; + + /* find if the complete mime type exists */ + exists = g_hash_table_lookup_extended (_repository.mime_links, (gpointer)mime_type, + (gpointer)&old_mime_type, (gpointer)>k_type); + if (exists) /* the complete mime type exists, return it */ + return gtk_type; + else { + /* the complete mime type association does not exists */ + /* is there an association for the main mime type ? */ + gmime_content_field_construct_from_string (_content_field, mime_type); + exists = g_hash_table_lookup_extended (_repository.mime_links, (gpointer)(_content_field->type), + (gpointer)&old_mime_type, (gpointer)>k_type); + + if (exists) /* the main mime type association exists */ + return gtk_type; + else return camel_simple_data_wrapper_get_type(); + } + + + + +} + diff --git a/camel/data-wrapper-repository.h b/camel/data-wrapper-repository.h new file mode 100644 index 0000000000..06738db585 --- /dev/null +++ b/camel/data-wrapper-repository.h @@ -0,0 +1,53 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * + * Copyright (C) 1999 Bertrand Guiheneuf . + * + * 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 Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + + +#ifndef DATA_WRAPPER_REPOSITORY_H +#define DATA_WRAPPER_REPOSITORY_H 1 + + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus }*/ + +#include +#include +#include "camel-data-wrapper.h" + + + +typedef struct { + GHashTable *mime_links; +} DataWrapperRepository; + + +gint data_wrapper_repository_init (); +void data_wrapper_set_data_wrapper_type (const gchar *mime_type, GtkType object_type); +GtkType data_wrapper_get_data_wrapper_type (const gchar *mime_type); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* DATA_WRAPPER_REPOSITORY_H */ diff --git a/camel/string-utils.c b/camel/string-utils.c new file mode 100644 index 0000000000..7cfd07e6d8 --- /dev/null +++ b/camel/string-utils.c @@ -0,0 +1,251 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* string-util : utilities for gchar* strings */ + +/* + * + * Copyright (C) 1999 Bertrand Guiheneuf . + * + * 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 Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + + + +#include +#include "string-utils.h" +#include "camel-log.h" + + + +gboolean +string_equal_for_glist (gconstpointer v, gconstpointer v2) +{ + return (!strcmp ( ((const gchar *)v), ((const gchar*)v2))) == 0; +} + +/** + * string_dichotomy: + * @sep : separator + * @prefix: pointer to be field by the prefix object + * the prefix is not returned when the given pointer is NULL + * @suffix: pointer to be field by the suffix object + * the suffix is not returned when the given pointer is NULL + * + * Return the strings before and/or after + * the last occurence of the specified separator + * + * This routine returns the string before and/or after + * a character given as an argument. + * if the separator is the last character, prefix and/or + * suffix is set to NULL and result is set to 'l' + * if the separator is not in the list, prefix and/or + * suffix is set to NULL and result is set to 'n' + * When the operation succedeed, the return value is 'o' + * + * @Return Value : result of the operation ('o', 'l' or 'n') + * + **/ +gchar +string_dichotomy (const gchar *string, gchar sep, gchar **prefix, gchar **suffix, + StringDichotomyOption options) +{ + gchar *tmp_str; + gint sep_pos, first, last, len; + + g_assert (string); + CAMEL_LOG_FULL_DEBUG (\ + "string_dichotomy:: string=\"%s\"\n\tseparator=\"%c\" \n\tprefix=%p \n\tsuffix=%p \n\toptions=%ld\n",\ + string, sep, prefix, suffix, options); + len = strlen (string); + if (!len) { + if (prefix) + *prefix=NULL; + if (suffix) + *suffix=NULL; + CAMEL_LOG_FULL_DEBUG ("string_dichotomy:: input string is empty\n"); + return 'n'; + } + first = 0; + last = len-1; + + if ( (options & STRING_DICHOTOMY_STRIP_LEADING ) && (string[first] == sep) ) + do {first++;} while ( (firstfirst)) + last--; + + if (first==last) { + if (prefix) *prefix=NULL; + if (suffix) *suffix=NULL; + CAMEL_LOG_FULL_DEBUG ("string_dichotomy: after stripping, string is empty\n"); + return 'n'; + } + + if (options & STRING_DICHOTOMY_RIGHT_DIR) { + sep_pos = last; + while ((sep_pos>=first) && (string[sep_pos]!=sep)) { + sep_pos--; + } + } else { + sep_pos = first; + while ((sep_pos<=last) && (string[sep_pos]!=sep)) { + sep_pos++; + } + + } + + if ( (sep_poslast) ) + { + if (suffix) *suffix=NULL; + if (prefix) *prefix=NULL; + CAMEL_LOG_FULL_DEBUG ("string_dichotomy: separator not found\n"); + return 'n'; + } + + /* if we have stripped trailing separators, we should */ + /* never enter here */ + if (sep_pos==last) + { + if (suffix) *suffix=NULL; + if (prefix) *prefix=NULL; + CAMEL_LOG_FULL_DEBUG ("string_dichotomy: separator is last character\n"); + return 'l'; + } + /* if we have stripped leading separators, we should */ + /* never enter here */ + if (sep_pos==first) + { + if (suffix) *suffix=NULL; + if (prefix) *prefix=NULL; + CAMEL_LOG_FULL_DEBUG ("string_dichotomy: separator is first character\n"); + return 'l'; + } + CAMEL_LOG_FULL_DEBUG ("string_dichotomy: separator found at :%d\n", sep_pos); + if (prefix) { /* return the prefix */ + *prefix = g_strndup(string+first,sep_pos-first); + CAMEL_LOG_FULL_DEBUG ( "string_dichotomy:: prefix:\"%s\"\n", *prefix); + } + if (suffix) { /* return the suffix */ + *suffix = g_strndup(string+sep_pos+1, last-sep_pos); + CAMEL_LOG_FULL_DEBUG ( "string_dichotomy:: suffix:\"%s\"\n", *suffix); + } + + return 'o'; +} + + + + + + +/* utility func : frees a gchar element in a GList */ +static void +__string_list_free_string (gpointer data, gpointer user_data) +{ + gchar *string = (gchar *)data; + g_free(string); +} + + +void +string_list_free (GList *string_list) +{ + g_list_foreach (string_list, __string_list_free_string, NULL); + g_list_free (string_list); +} + + + + + + +GList * +string_split (const gchar *string, char sep, const gchar *trim_chars, StringTrimOption trim_options) +{ + GList *result = NULL; + gint first, last, pos; + gchar *new_string; + + g_assert (string); + + first = 0; + last = strlen(string) - 1; + + /* strip leading and trailing separators */ + while ( (first<=last) && (string[first]==sep) ) + first++; + while ( (first<=last) && (string[last]==sep) ) + last--; + + + CAMEL_LOG_FULL_DEBUG ("string_split:: trim options: %d\n", trim_options); + + while (first<=last) { + pos = first; + /* find next separator */ + while ((pos<=last) && (string[pos]!=sep)) pos++; + if (first != pos) { + new_string = g_strndup (string+first, pos-first); + /* could do trimming in line to speed up this code */ + if (trim_chars) string_trim (new_string, trim_chars, trim_options); + result = g_list_append (result, new_string); + } + first = pos + 1; + } + + return result; +} + + +void +string_trim (gchar *string, const gchar *trim_chars, StringTrimOption options) +{ + gint first_ok; + gint last_ok; + guint length; + + CAMEL_LOG_FULL_DEBUG ("string-utils:: Entering string_trim::\n"); + CAMEL_LOG_FULL_DEBUG ("string_trim:: trim_chars:\"%s\"", trim_chars); + CAMEL_LOG_FULL_DEBUG ("string_trim:: trim_options:%d\n", options); + + g_return_if_fail (string); + length = strlen (string); + g_return_if_fail (length > 0); + + first_ok = 0; + last_ok = length - 1; + + if (options & STRING_TRIM_STRIP_LEADING) + while ( (first_ok <= last_ok) && (strchr (trim_chars, string[first_ok])!=NULL) ) + first_ok++; + + if (options & STRING_TRIM_STRIP_TRAILING) + while ( (first_ok <= last_ok) && (strchr (trim_chars, string[last_ok])!=NULL) ) + last_ok--; + CAMEL_LOG_FULL_DEBUG ("string_trim::\n\t\"%s\":first ok:%d last_ok:%d\n", + string, first_ok, last_ok); + + if (first_ok > 0) + memmove (string, string+first_ok, last_ok - first_ok +2); + +} + + + + + + + diff --git a/camel/string-utils.h b/camel/string-utils.h new file mode 100644 index 0000000000..9805861daf --- /dev/null +++ b/camel/string-utils.h @@ -0,0 +1,67 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* string-util : utilities for normal gchar * strings */ + +/* + * + * Copyright (C) 1999 Bertrand Guiheneuf . + * + * 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 Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + + + +#ifndef STRING_UTIL_H +#define STRING_UTIL_H 1 + + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus }*/ + +#include + +typedef enum { + STRING_DICHOTOMY_NONE = 0, + STRING_DICHOTOMY_RIGHT_DIR = 1, + STRING_DICHOTOMY_STRIP_TRAILING = 2, + STRING_DICHOTOMY_STRIP_LEADING = 4, + +} StringDichotomyOption; + +typedef enum { + STRING_TRIM_NONE = 0, + STRING_TRIM_STRIP_TRAILING = 1, + STRING_TRIM_STRIP_LEADING = 2, +} StringTrimOption; + +gboolean string_equal_for_glist (gconstpointer v, gconstpointer v2); + +gchar string_dichotomy (const gchar *string, gchar sep, + gchar **prefix, gchar **suffix, + StringDichotomyOption options); +void string_list_free (GList *string_list); + +GList *string_split (const gchar *string, char sep, + const gchar *trim_chars, StringTrimOption trim_options); +void string_trim (gchar *string, const gchar *chars, + StringTrimOption options); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* STRING_UTIL_H */ diff --git a/devel-docs/camel/tmpl/camel-data-wrapper.sgml b/devel-docs/camel/tmpl/camel-data-wrapper.sgml new file mode 100644 index 0000000000..6fce9eb128 --- /dev/null +++ b/devel-docs/camel/tmpl/camel-data-wrapper.sgml @@ -0,0 +1,26 @@ + +CamelDataWrapper + + +data container with streaming methods + + + +A CamelDataWrapper is wrapper around data which can save them to a stream +and restore them from a stream. + + + + + + + + + + + + +@data_wrapper: +@stream: + + diff --git a/tests/test3.c b/tests/test3.c new file mode 100644 index 0000000000..a210ea3723 --- /dev/null +++ b/tests/test3.c @@ -0,0 +1,28 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +#include "camel.h" + +int +main (int argc, char**argv) +{ + GtkType type; + + gtk_init (&argc, &argv); + camel_init (); + + printf ("Test 3 : data wrapper repository\n"); + + printf ("\nMime type : \"multipart\"\n"); + type = data_wrapper_get_data_wrapper_type ("multipart"); + printf ("Type found %s\n", gtk_type_name (type) ); + + printf ("\nMime type : \"multipart/alternative\"\n"); + type = data_wrapper_get_data_wrapper_type ("multipart/alternative"); + printf ("Type found %s\n", gtk_type_name (type) ); + + printf ("\nMime type : \"toto/titi\"\n"); + type = data_wrapper_get_data_wrapper_type ("toto/titi"); + printf ("Type found %s\n", gtk_type_name (type) ); + + printf ("Test3 finished\n"); +} + -- cgit v1.2.3