No, we're not going to have g_strcasecmp for no good reason,
not even if its slipped in with no changelog. 2000-05-04 NotZed <NotZed@HelixCode.com> * providers/mbox/camel-mbox-summary.c: Yes, and anotherone. * camel-mime-utils.c: And another one. * camel-mime-part.c: And another one. * camel-mime-part-utils.c: And another one. * camel-folder-search.c: And another one. * camel-mime-parser.c: Reverted a change wihtout a ChangeLog entry. 2000-05-04 NotZed <NotZed@HelixCode.com> * camel-folder-summary.[hc]: Yes, CamelFolderSummary is back ... ... re-usable class to summarise and index any stream or message and to manage/load/save the created summaries. * camel-folder.c: Include string.h to kill a warning. 2000-05-03 NotZed <NotZed@HelixCode.com> * camel-folder.h: Added pos/bodypos/endpos to the basic message content info object. Size to be removed? Moved the messageconentinfo and messageinfo back to camel-folder-summary.h. * camel-mime-filter-index.c (camel_mime_filter_index_set_ibex): New function to (re)set the index to use on a filter. * camel-mime-parser.c (camel_mime_parser_scan_from): Whole bunch of inline docs. (camel_mime_parser_drop_step): New function to drop a state from the parser. Needs more testing. svn path=/trunk/; revision=2789
This commit is contained in:
@ -1,3 +1,25 @@
|
||||
2000-05-04 NotZed <NotZed@HelixCode.com>
|
||||
|
||||
* providers/mbox/camel-mbox-summary.c: Yes, and anotherone.
|
||||
|
||||
* camel-mime-utils.c: And another one.
|
||||
|
||||
* camel-mime-part.c: And another one.
|
||||
|
||||
* camel-mime-part-utils.c: And another one.
|
||||
|
||||
* camel-folder-search.c: And another one.
|
||||
|
||||
* camel-mime-parser.c: Reverted a change wihtout a ChangeLog entry.
|
||||
|
||||
2000-05-04 NotZed <NotZed@HelixCode.com>
|
||||
|
||||
* camel-folder-summary.[hc]: Yes, CamelFolderSummary is back ...
|
||||
... re-usable class to summarise and index any stream or message
|
||||
and to manage/load/save the created summaries.
|
||||
|
||||
* camel-folder.c: Include string.h to kill a warning.
|
||||
|
||||
2000-05-03 Jason Leach <leach@wam.umd.edu>
|
||||
|
||||
* Makefile.am (INCLUDES): add $(UNICODE_CFLAGS) to the INCLUDES,
|
||||
@ -6,6 +28,18 @@
|
||||
|
||||
2000-05-03 NotZed <NotZed@HelixCode.com>
|
||||
|
||||
* camel-folder.h: Added pos/bodypos/endpos to the basic message
|
||||
content info object. Size to be removed? Moved the
|
||||
messageconentinfo and messageinfo back to camel-folder-summary.h.
|
||||
|
||||
* camel-mime-filter-index.c (camel_mime_filter_index_set_ibex):
|
||||
New function to (re)set the index to use on a filter.
|
||||
|
||||
* camel-mime-parser.c (camel_mime_parser_scan_from): Whole bunch
|
||||
of inline docs.
|
||||
(camel_mime_parser_drop_step): New function to drop a state from
|
||||
the parser. Needs more testing.
|
||||
|
||||
* camel-mime-utils.c (rfc2047_decode_word): If the iconv handle is
|
||||
-1, then dont try and convert (crashes unicode_iconv?).
|
||||
(rfc2047_decode_word): Use alloca for variables instead of
|
||||
|
||||
@ -38,6 +38,7 @@ libcamel_la_SOURCES = \
|
||||
camel-exception.c \
|
||||
camel-folder.c \
|
||||
camel-folder-search.c \
|
||||
camel-folder-summary.c \
|
||||
camel-medium.c \
|
||||
camel-marshal-utils.c \
|
||||
camel-mime-message.c \
|
||||
@ -81,6 +82,7 @@ libcamelinclude_HEADERS = \
|
||||
camel-exception.h \
|
||||
camel-folder.h \
|
||||
camel-folder-search.h \
|
||||
camel-folder-summary.h \
|
||||
camel-marshal-utils.h \
|
||||
camel-medium.h \
|
||||
camel-mime-message.h \
|
||||
|
||||
@ -358,15 +358,15 @@ search_header_contains(struct _ESExp *f, int argc, struct _ESExpResult **argv, C
|
||||
|
||||
/* only a subset of headers are supported .. */
|
||||
headername = argv[0]->value.string;
|
||||
if (!g_strcasecmp(headername, "subject")) {
|
||||
if (!strcasecmp(headername, "subject")) {
|
||||
header = search->current->subject;
|
||||
} else if (!g_strcasecmp(headername, "date")) {
|
||||
} else if (!strcasecmp(headername, "date")) {
|
||||
/* FIXME: not a very useful form of the date */
|
||||
sprintf(strbuf, "%d", (int)search->current->date_sent);
|
||||
header = strbuf;
|
||||
} else if (!g_strcasecmp(headername, "from")) {
|
||||
} else if (!strcasecmp(headername, "from")) {
|
||||
header = search->current->from;
|
||||
} else if (!g_strcasecmp(headername, "to")) {
|
||||
} else if (!strcasecmp(headername, "to")) {
|
||||
header = search->current->from;
|
||||
} else {
|
||||
g_warning("Performing query on unknown header: %s", headername);
|
||||
|
||||
1041
camel/camel-folder-summary.c
Normal file
1041
camel/camel-folder-summary.c
Normal file
File diff suppressed because it is too large
Load Diff
181
camel/camel-folder-summary.h
Normal file
181
camel/camel-folder-summary.h
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (C) 2000 Helix Code Inc.
|
||||
*
|
||||
* Authors: Michael Zucchi <notzed@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 Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef _CAMEL_FOLDER_SUMMARY_H
|
||||
#define _CAMEL_FOLDER_SUMMARY_H
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <camel/camel-mime-parser.h>
|
||||
#include <libibex/ibex.h>
|
||||
|
||||
#define CAMEL_FOLDER_SUMMARY(obj) GTK_CHECK_CAST (obj, camel_folder_summary_get_type (), CamelFolderSummary)
|
||||
#define CAMEL_FOLDER_SUMMARY_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, camel_folder_summary_get_type (), CamelFolderSummaryClass)
|
||||
#define IS_CAMEL_FOLDER_SUMMARY(obj) GTK_CHECK_TYPE (obj, camel_folder_summary_get_type ())
|
||||
|
||||
/*typedef struct _CamelFolderSummary CamelFolderSummary;*/
|
||||
typedef struct _CamelFolderSummaryClass CamelFolderSummaryClass;
|
||||
|
||||
/* these structs from camel-folder-summary.h ... (remove comment after cleanup soon) */
|
||||
/* TODO: perhaps they should be full-block objects? */
|
||||
/* FIXME: rename this to something more suitable */
|
||||
typedef struct {
|
||||
gchar *name;
|
||||
gint nb_message; /* ick, these should be renamed to something better */
|
||||
gint nb_unread_message;
|
||||
gint nb_deleted_message;
|
||||
} CamelFolderInfo;
|
||||
|
||||
/* A tree of message content info structures
|
||||
describe the content structure of the message (if it has any) */
|
||||
typedef struct _CamelMessageContentInfo {
|
||||
struct _CamelMessageContentInfo *next;
|
||||
|
||||
struct _CamelMessageContentInfo *childs;
|
||||
struct _CamelMessageContentInfo *parent;
|
||||
|
||||
struct _header_content_type *type;
|
||||
char *id;
|
||||
char *description;
|
||||
char *encoding;
|
||||
|
||||
/* information about where this object lives in the stream.
|
||||
if pos is -1 these are all invalid */
|
||||
off_t pos;
|
||||
off_t bodypos;
|
||||
off_t endpos;
|
||||
} CamelMessageContentInfo;
|
||||
|
||||
/* information about a given object */
|
||||
typedef struct {
|
||||
/* public fields */
|
||||
gchar *subject;
|
||||
gchar *to;
|
||||
gchar *from;
|
||||
|
||||
gchar *uid;
|
||||
guint32 flags;
|
||||
guint32 size;
|
||||
|
||||
time_t date_sent;
|
||||
time_t date_received;
|
||||
|
||||
/* tree of content description - NULL if it is not available */
|
||||
CamelMessageContentInfo *content;
|
||||
} CamelMessageInfo;
|
||||
|
||||
enum _CamelFolderSummaryFlags {
|
||||
CAMEL_SUMMARY_DIRTY = 1<<0,
|
||||
};
|
||||
|
||||
struct _CamelFolderSummary {
|
||||
GtkObject parent;
|
||||
|
||||
struct _CamelFolderSummaryPrivate *priv;
|
||||
|
||||
/* header info */
|
||||
guint32 version; /* version of file required, should be set by implementors */
|
||||
guint32 flags; /* flags */
|
||||
guint32 nextuid; /* next uid? */
|
||||
guint32 saved_count; /* how many were saved/loaded */
|
||||
time_t time; /* timestamp for this summary */
|
||||
|
||||
/* sizes of memory objects */
|
||||
guint32 message_info_size;
|
||||
guint32 content_info_size;
|
||||
|
||||
char *summary_path;
|
||||
gboolean build_content; /* do we try and parse/index the content, or not? */
|
||||
|
||||
GPtrArray *messages; /* CamelMessageInfo's */
|
||||
GHashTable *messages_uid; /* CamelMessageInfo's by uid */
|
||||
};
|
||||
|
||||
struct _CamelFolderSummaryClass {
|
||||
GtkObjectClass parent_class;
|
||||
|
||||
/* load/save the global info */
|
||||
int (*summary_header_load)(CamelFolderSummary *, FILE *);
|
||||
int (*summary_header_save)(CamelFolderSummary *, FILE *);
|
||||
|
||||
/* create/save/load an individual message info */
|
||||
CamelMessageInfo * (*message_info_new)(CamelFolderSummary *, struct _header_raw *);
|
||||
CamelMessageInfo * (*message_info_new_from_parser)(CamelFolderSummary *, CamelMimeParser *);
|
||||
CamelMessageInfo * (*message_info_load)(CamelFolderSummary *, FILE *);
|
||||
int (*message_info_save)(CamelFolderSummary *, FILE *, CamelMessageInfo *);
|
||||
void (*message_info_free)(CamelFolderSummary *, CamelMessageInfo *);
|
||||
|
||||
/* save/load individual content info's */
|
||||
CamelMessageContentInfo * (*content_info_new)(CamelFolderSummary *, struct _header_raw *);
|
||||
CamelMessageContentInfo * (*content_info_new_from_parser)(CamelFolderSummary *, CamelMimeParser *);
|
||||
CamelMessageContentInfo * (*content_info_load)(CamelFolderSummary *, FILE *);
|
||||
int (*content_info_save)(CamelFolderSummary *, FILE *, CamelMessageContentInfo *);
|
||||
void (*content_info_free)(CamelFolderSummary *, CamelMessageContentInfo *);
|
||||
};
|
||||
|
||||
guint camel_folder_summary_get_type (void);
|
||||
CamelFolderSummary *camel_folder_summary_new (void);
|
||||
|
||||
void camel_folder_summary_set_filename(CamelFolderSummary *, const char *);
|
||||
void camel_folder_summary_set_index(CamelFolderSummary *, ibex *);
|
||||
void camel_folder_summary_set_uid(CamelFolderSummary *, guint32);
|
||||
void camel_folder_summary_set_build_content(CamelFolderSummary *, gboolean state);
|
||||
|
||||
guint32 camel_folder_summary_next_uid(CamelFolderSummary *s);
|
||||
|
||||
/* load/save the summary in its entirety */
|
||||
int camel_folder_summary_load(CamelFolderSummary *);
|
||||
int camel_folder_summary_save(CamelFolderSummary *);
|
||||
|
||||
/* add a new raw summary item */
|
||||
void camel_folder_summary_add(CamelFolderSummary *, CamelMessageInfo *info);
|
||||
void camel_folder_summary_add_from_header(CamelFolderSummary *, struct _header_raw *);
|
||||
void camel_folder_summary_add_from_parser(CamelFolderSummary *, CamelMimeParser *);
|
||||
|
||||
/* removes a summary item, fixes offsets? */
|
||||
void camel_mbox_summary_remove_uid(CamelFolderSummary *s, const char *uid);
|
||||
|
||||
/* lookup functions */
|
||||
int camel_folder_summary_count(CamelFolderSummary *);
|
||||
CamelMessageInfo *camel_folder_summary_index(CamelFolderSummary *, int);
|
||||
CamelMessageInfo *camel_folder_summary_uid(CamelFolderSummary *, const char *uid);
|
||||
|
||||
/* utility functions */
|
||||
void camel_folder_summary_set_flags_by_uid(CamelFolderSummary *s, const char *uid, guint32 flags);
|
||||
/* shift content ... */
|
||||
void camel_folder_summary_offset_content(CamelMessageContentInfo *content, off_t offset);
|
||||
|
||||
/* summary file loading/saving helper functions */
|
||||
int camel_folder_summary_encode_fixed_int32(FILE *, gint32);
|
||||
int camel_folder_summary_decode_fixed_int32(FILE *, gint32 *);
|
||||
|
||||
int camel_folder_summary_encode_uint32(FILE *, guint32);
|
||||
int camel_folder_summary_decode_uint32(FILE *, guint32 *);
|
||||
|
||||
int camel_folder_summary_encode_string(FILE *, char *);
|
||||
int camel_folder_summary_decode_string(FILE *, char **);
|
||||
|
||||
/* basically like strings, but certain keywords can be compressed and de-cased */
|
||||
int camel_folder_summary_encode_token(FILE *, char *);
|
||||
int camel_folder_summary_decode_token(FILE *, char **);
|
||||
|
||||
#endif /* ! _CAMEL_FOLDER_SUMMARY_H */
|
||||
@ -24,6 +24,7 @@
|
||||
* USA
|
||||
*/
|
||||
#include <config.h>
|
||||
#include <string.h>
|
||||
#include "camel-folder.h"
|
||||
#include "camel-exception.h"
|
||||
#include "camel-store.h"
|
||||
|
||||
@ -56,11 +56,8 @@ typedef enum {
|
||||
} CamelFolderOpenMode;
|
||||
|
||||
|
||||
typedef void (*CamelFolderAsyncCallback) ();
|
||||
#warning old summary stuff to be removed!
|
||||
|
||||
/* these structs from camel-folder-summary.h ... (remove comment after cleanup soon) */
|
||||
/* TODO: perhaps they should be full-block objects? */
|
||||
/* FIXME: rename this to something more suitable */
|
||||
typedef struct {
|
||||
gchar *name;
|
||||
gint nb_message; /* ick, these should be renamed to something better */
|
||||
@ -82,10 +79,10 @@ typedef struct _CamelMessageContentInfo {
|
||||
char *encoding;
|
||||
|
||||
guint32 size;
|
||||
|
||||
} CamelMessageContentInfo;
|
||||
|
||||
/* TODO: rename this?? */
|
||||
/* TODO: Make this an object, maybe? */
|
||||
/* information about a given object */
|
||||
typedef struct {
|
||||
/* public fields */
|
||||
gchar *subject;
|
||||
@ -98,11 +95,13 @@ typedef struct {
|
||||
time_t date_sent;
|
||||
time_t date_received;
|
||||
|
||||
/* tree of content description */
|
||||
/* tree of content description - NULL if it is not available */
|
||||
CamelMessageContentInfo *content;
|
||||
} CamelMessageInfo;
|
||||
|
||||
|
||||
typedef void (*CamelFolderAsyncCallback) ();
|
||||
|
||||
struct _CamelFolder
|
||||
{
|
||||
GtkObject parent_object;
|
||||
|
||||
@ -163,4 +163,16 @@ void camel_mime_filter_index_set_name (CamelMimeFilterIndex *mf, char *name)
|
||||
mf->name = g_strdup(name);
|
||||
}
|
||||
|
||||
void camel_mime_filter_index_set_ibex (CamelMimeFilterIndex *mf, ibex *index)
|
||||
{
|
||||
if (mf->index) {
|
||||
char *out;
|
||||
size_t outlen, outspace;
|
||||
|
||||
camel_mime_filter_complete((CamelMimeFilter *)mf, "", 0, 0, &out, &outlen, &outspace);
|
||||
}
|
||||
mf->index = index;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -53,5 +53,6 @@ CamelMimeFilterIndex *camel_mime_filter_index_new_ibex (ibex *);
|
||||
|
||||
/* Set the match name for any indexed words */
|
||||
void camel_mime_filter_index_set_name (CamelMimeFilterIndex *, char *);
|
||||
void camel_mime_filter_index_set_ibex (CamelMimeFilterIndex *mf, ibex *index);
|
||||
|
||||
#endif /* ! _CAMEL_MIME_FILTER_INDEX_H */
|
||||
|
||||
@ -118,6 +118,7 @@ struct _header_scan_filter {
|
||||
};
|
||||
|
||||
static void folder_scan_step(struct _header_scan_state *s, char **databuffer, int *datalength);
|
||||
static void folder_scan_drop_step(struct _header_scan_state *s);
|
||||
static int folder_scan_init_with_fd(struct _header_scan_state *s, int fd);
|
||||
static int folder_scan_init_with_stream(struct _header_scan_state *s, CamelStream *stream);
|
||||
static struct _header_scan_state *folder_scan_init(void);
|
||||
@ -226,6 +227,22 @@ camel_mime_parser_new (void)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* camel_mime_parser_filter_add:
|
||||
* @m:
|
||||
* @mf:
|
||||
*
|
||||
* Add a filter that will be applied to any body content before it is passed
|
||||
* to the caller. Filters may be pipelined to perform multi-pass operations
|
||||
* on the content, and are applied in the order they were added.
|
||||
*
|
||||
* Note that filters are only applied to the body content of messages, and once
|
||||
* a filter has been set, all content returned by a filter_step() with a state
|
||||
* of HSCAN_BODY will have passed through the filter.
|
||||
*
|
||||
* Return value: An id that may be passed to filter_remove() to remove
|
||||
* the filter, or -1 if the operation failed.
|
||||
**/
|
||||
int
|
||||
camel_mime_parser_filter_add(CamelMimeParser *m, CamelMimeFilter *mf)
|
||||
{
|
||||
@ -248,6 +265,14 @@ camel_mime_parser_filter_add(CamelMimeParser *m, CamelMimeFilter *mf)
|
||||
return new->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* camel_mime_parser_filter_remove:
|
||||
* @m:
|
||||
* @id:
|
||||
*
|
||||
* Remove a processing filter from the pipeline. There is no
|
||||
* restriction on the order the filters can be removed.
|
||||
**/
|
||||
void
|
||||
camel_mime_parser_filter_remove(CamelMimeParser *m, int id)
|
||||
{
|
||||
@ -268,6 +293,18 @@ camel_mime_parser_filter_remove(CamelMimeParser *m, int id)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* camel_mime_parser_header:
|
||||
* @m:
|
||||
* @name: Name of header.
|
||||
* @offset: Pointer that can receive the offset of the header in
|
||||
* the stream from the start of parsing.
|
||||
*
|
||||
* Lookup a header by name.
|
||||
*
|
||||
* Return value: The header value, or NULL if the header is not
|
||||
* defined.
|
||||
**/
|
||||
const char *
|
||||
camel_mime_parser_header(CamelMimeParser *m, const char *name, int *offset)
|
||||
{
|
||||
@ -280,6 +317,17 @@ camel_mime_parser_header(CamelMimeParser *m, const char *name, int *offset)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* camel_mime_parser_headers_raw:
|
||||
* @m:
|
||||
*
|
||||
* Get the list of the raw headers which are defined for the
|
||||
* current state of the parser. These headers are valid
|
||||
* until the next call to parser_step(), or parser_drop_step().
|
||||
*
|
||||
* Return value: The raw headers, or NULL if there are no headers
|
||||
* defined for the current part or state.
|
||||
**/
|
||||
struct _header_raw *
|
||||
camel_mime_parser_headers_raw(CamelMimeParser *m)
|
||||
{
|
||||
@ -290,6 +338,21 @@ camel_mime_parser_headers_raw(CamelMimeParser *m)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* camel_mime_parser_init_with_fd:
|
||||
* @m:
|
||||
* @fd: A valid file descriptor.
|
||||
*
|
||||
* Initialise the scanner with an fd. The scanner's offsets
|
||||
* will be relative to the current file position of the file
|
||||
* descriptor. As a result, seekable descritors should
|
||||
* be seeked using the parser seek functions.
|
||||
*
|
||||
* An initial buffer will be read from the file descriptor
|
||||
* immediately, although no parsing will occur.
|
||||
*
|
||||
* Return value: Returns -1 on error.
|
||||
**/
|
||||
int
|
||||
camel_mime_parser_init_with_fd(CamelMimeParser *m, int fd)
|
||||
{
|
||||
@ -298,6 +361,21 @@ camel_mime_parser_init_with_fd(CamelMimeParser *m, int fd)
|
||||
return folder_scan_init_with_fd(s, fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* camel_mime_parser_init_with_stream:
|
||||
* @m:
|
||||
* @stream:
|
||||
*
|
||||
* Initialise the scanner with a source stream. The scanner's
|
||||
* offsets will be relative to the current file position of
|
||||
* the stream. As a result, seekable streams should only
|
||||
* be seeked using the parser seek function.
|
||||
*
|
||||
* An initial buffer will be read from the stream
|
||||
* immediately, although no parsing will occur.
|
||||
*
|
||||
* Return value: -1 on error.
|
||||
**/
|
||||
int
|
||||
camel_mime_parser_init_with_stream(CamelMimeParser *m, CamelStream *stream)
|
||||
{
|
||||
@ -306,6 +384,17 @@ camel_mime_parser_init_with_stream(CamelMimeParser *m, CamelStream *stream)
|
||||
return folder_scan_init_with_stream(s, stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* camel_mime_parser_scan_from:
|
||||
* @m:
|
||||
* @scan_from: #TRUE if the scanner should scan From lines.
|
||||
*
|
||||
* Tell the scanner if it should scan "^From " lines or not.
|
||||
*
|
||||
* If the scanner is scanning from lines, two additional
|
||||
* states HSCAN_FROM and HSCAN_FROM_END will be returned
|
||||
* to the caller during parsing.
|
||||
**/
|
||||
void
|
||||
camel_mime_parser_scan_from(CamelMimeParser *m, int scan_from)
|
||||
{
|
||||
@ -313,6 +402,16 @@ camel_mime_parser_scan_from(CamelMimeParser *m, int scan_from)
|
||||
s->scan_from = scan_from;
|
||||
}
|
||||
|
||||
/**
|
||||
* camel_mime_parser_content_type:
|
||||
* @m:
|
||||
*
|
||||
* Get the content type defined in the current part.
|
||||
*
|
||||
* Return value: A content_type structure, or NULL if there
|
||||
* is no content-type defined for this part of state of the
|
||||
* parser.
|
||||
**/
|
||||
struct _header_content_type *
|
||||
camel_mime_parser_content_type(CamelMimeParser *m)
|
||||
{
|
||||
@ -325,6 +424,17 @@ camel_mime_parser_content_type(CamelMimeParser *m)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* camel_mime_parser_unstep:
|
||||
* @m:
|
||||
*
|
||||
* Cause the last step operation to repeat itself. If this is
|
||||
* called repeated times, then the same step will be repeated
|
||||
* that many times.
|
||||
*
|
||||
* Note that it is not possible to scan back using this function,
|
||||
* only to have a way of peeking the next state.
|
||||
**/
|
||||
void camel_mime_parser_unstep(CamelMimeParser *m)
|
||||
{
|
||||
struct _header_scan_state *s = _PRIVATE(m);
|
||||
@ -332,6 +442,49 @@ void camel_mime_parser_unstep(CamelMimeParser *m)
|
||||
s->unstep++;
|
||||
}
|
||||
|
||||
/**
|
||||
* camel_mime_parser_drop_step:
|
||||
* @m:
|
||||
*
|
||||
* Drop the last step call. This should only be used
|
||||
* in conjunction with seeking of the stream as the
|
||||
* stream may be in an undefined state relative to the
|
||||
* state of the parser.
|
||||
*
|
||||
* Use this call with care.
|
||||
**/
|
||||
void camel_mime_parser_drop_step(CamelMimeParser *m)
|
||||
{
|
||||
struct _header_scan_state *s = _PRIVATE(m);
|
||||
|
||||
s->unstep = 0;
|
||||
folder_scan_drop_step(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* camel_mime_parser_step:
|
||||
* @m:
|
||||
* @databuffer: Pointer to accept a pointer to the data
|
||||
* associated with this step (if any).
|
||||
* @datalength: Pointer to accept a pointer to the data
|
||||
* length associated with this step (if any).
|
||||
*
|
||||
* Parse the next part of the MIME message. If _unstep()
|
||||
* has been called, then continue to return the same state
|
||||
* for that many calls.
|
||||
*
|
||||
* If the step is HSCAN_BODY then the databuffer and datalength
|
||||
* pointers will be setup to point to the internal data buffer
|
||||
* of the scanner and may be processed as required. Any
|
||||
* filters will have already been applied to this data.
|
||||
*
|
||||
* Refer to the state diagram elsewhere for a full listing of
|
||||
* the states an application is gauranteed to get from the
|
||||
* scanner.
|
||||
*
|
||||
* Return value: The current new state of the parser
|
||||
* is returned.
|
||||
**/
|
||||
enum _header_state
|
||||
camel_mime_parser_step(CamelMimeParser *m, char **databuffer, int *datalength)
|
||||
{
|
||||
@ -349,6 +502,26 @@ camel_mime_parser_step(CamelMimeParser *m, char **databuffer, int *datalength)
|
||||
return s->state;
|
||||
}
|
||||
|
||||
/**
|
||||
* camel_mime_parser_tell:
|
||||
* @m:
|
||||
*
|
||||
* Return the current scanning offset. The meaning of this
|
||||
* value will depend on the current state of the parser.
|
||||
*
|
||||
* An incomplete listing of the states:
|
||||
*
|
||||
* HSCAN_INITIAL, The start of the current message.
|
||||
* HSCAN_HEADER, HSCAN_MESSAGE, HSCAN_MULTIPART, the character
|
||||
* position immediately after the end of the header.
|
||||
* HSCAN_BODY, Position within the message of the start
|
||||
* of the current data block.
|
||||
* HSCAN_*_END, The position of the character starting
|
||||
* the next section of the scan (the last position + 1 of
|
||||
* the respective current state).
|
||||
*
|
||||
* Return value: See above.
|
||||
**/
|
||||
off_t camel_mime_parser_tell(CamelMimeParser *m)
|
||||
{
|
||||
struct _header_scan_state *s = _PRIVATE(m);
|
||||
@ -356,6 +529,17 @@ off_t camel_mime_parser_tell(CamelMimeParser *m)
|
||||
return folder_tell(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* camel_mime_parser_tell_start_headers:
|
||||
* @m:
|
||||
*
|
||||
* Find out the position within the file of where the
|
||||
* headers started, this is cached by the parser
|
||||
* at the time.
|
||||
*
|
||||
* Return value: The header start position, or -1 if
|
||||
* no headers were scanned in the current state.
|
||||
**/
|
||||
off_t camel_mime_parser_tell_start_headers(CamelMimeParser *m)
|
||||
{
|
||||
struct _header_scan_state *s = _PRIVATE(m);
|
||||
@ -363,6 +547,16 @@ off_t camel_mime_parser_tell_start_headers(CamelMimeParser *m)
|
||||
return s->start_of_headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* camel_mime_parser_tell_start_from:
|
||||
* @m:
|
||||
*
|
||||
* If the parser is scanning From lines, then this returns
|
||||
* the position of the start of the From line.
|
||||
*
|
||||
* Return value: The start of the from line, or -1 if there
|
||||
* was no From line, or From lines are not being scanned.
|
||||
**/
|
||||
off_t camel_mime_parser_tell_start_from(CamelMimeParser *m)
|
||||
{
|
||||
struct _header_scan_state *s = _PRIVATE(m);
|
||||
@ -370,24 +564,76 @@ off_t camel_mime_parser_tell_start_from(CamelMimeParser *m)
|
||||
return s->start_of_from;
|
||||
}
|
||||
|
||||
/**
|
||||
* camel_mime_parser_seek:
|
||||
* @m:
|
||||
* @off: Number of bytes to offset the seek by.
|
||||
* @whence: SEEK_SET, SEEK_CUR, SEEK_END
|
||||
*
|
||||
* Reset the source position to a known value.
|
||||
*
|
||||
* Note that if the source stream/descriptor was not
|
||||
* positioned at 0 to begin with, and an absolute seek
|
||||
* is specified (whence != SEEK_CUR), then the seek
|
||||
* position may not match the desired seek position.
|
||||
*
|
||||
* Return value: The new seek offset, or -1 on
|
||||
* an error (for example, trying to seek on a non-seekable
|
||||
* stream or file descriptor).
|
||||
**/
|
||||
off_t camel_mime_parser_seek(CamelMimeParser *m, off_t off, int whence)
|
||||
{
|
||||
struct _header_scan_state *s = _PRIVATE(m);
|
||||
return folder_seek(s, off, whence);
|
||||
}
|
||||
|
||||
/**
|
||||
* camel_mime_parser_state:
|
||||
* @m:
|
||||
*
|
||||
* Get the current parser state.
|
||||
*
|
||||
* Return value: The current parser state.
|
||||
**/
|
||||
enum _header_state camel_mime_parser_state(CamelMimeParser *m)
|
||||
{
|
||||
struct _header_scan_state *s = _PRIVATE(m);
|
||||
return s->state;
|
||||
}
|
||||
|
||||
/**
|
||||
* camel_mime_parser_stream:
|
||||
* @m:
|
||||
*
|
||||
* Get the stream, if any, the parser has been initialised
|
||||
* with. May be used to setup sub-streams, but should not
|
||||
* be read from directly (without saving and restoring
|
||||
* the seek position in between).
|
||||
*
|
||||
* Return value: The stream from _init_with_stream(), or NULL
|
||||
* if the parser is reading from a file descriptor or is
|
||||
* uninitialised.
|
||||
**/
|
||||
CamelStream *camel_mime_parser_stream(CamelMimeParser *m)
|
||||
{
|
||||
struct _header_scan_state *s = _PRIVATE(m);
|
||||
return s->stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* camel_mime_parser_fd:
|
||||
* @m:
|
||||
*
|
||||
* Return the file descriptor, if any, the parser has been
|
||||
* initialised with.
|
||||
*
|
||||
* Should not be read from unless the parser it to terminate,
|
||||
* or the seek offset can be reset before the next parse
|
||||
* step.
|
||||
*
|
||||
* Return value: The file descriptor or -1 if the parser
|
||||
* is reading from a stream or has not been initialised.
|
||||
**/
|
||||
int camel_mime_parser_fd(CamelMimeParser *m)
|
||||
{
|
||||
struct _header_scan_state *s = _PRIVATE(m);
|
||||
@ -1022,7 +1268,7 @@ tail_recurse:
|
||||
type = HSCAN_HEADER;
|
||||
if ( (content = header_raw_find(&h->headers, "Content-Type", NULL))
|
||||
&& (ct = header_content_type_decode(content))) {
|
||||
if (!g_strcasecmp(ct->type, "multipart")) {
|
||||
if (!strcasecmp(ct->type, "multipart")) {
|
||||
bound = header_content_type_param(ct, "boundary");
|
||||
if (bound) {
|
||||
d(printf("multipart, boundary = %s\n", bound));
|
||||
@ -1037,9 +1283,9 @@ tail_recurse:
|
||||
/* header_raw_replace(&h->headers, "Content-Type", "text/plain", offset);*/
|
||||
g_warning("Multipart with no boundary, treating as text/plain");
|
||||
}
|
||||
} else if (!g_strcasecmp(ct->type, "message")) {
|
||||
if (!g_strcasecmp(ct->subtype, "rfc822")
|
||||
/*|| !g_strcasecmp(ct->subtype, "partial")*/) {
|
||||
} else if (!strcasecmp(ct->type, "message")) {
|
||||
if (!strcasecmp(ct->subtype, "rfc822")
|
||||
/*|| !strcasecmp(ct->subtype, "partial")*/) {
|
||||
type = HSCAN_MESSAGE;
|
||||
}
|
||||
}
|
||||
@ -1138,6 +1384,38 @@ tail_recurse:
|
||||
return;
|
||||
}
|
||||
|
||||
/* drops the current state back one */
|
||||
static void
|
||||
folder_scan_drop_step(struct _header_scan_state *s)
|
||||
{
|
||||
switch (s->state) {
|
||||
case HSCAN_INITIAL:
|
||||
case HSCAN_EOF:
|
||||
return;
|
||||
|
||||
case HSCAN_FROM:
|
||||
s->state = HSCAN_INITIAL;
|
||||
folder_pull_part(s);
|
||||
return;
|
||||
|
||||
case HSCAN_MESSAGE:
|
||||
case HSCAN_HEADER:
|
||||
case HSCAN_MULTIPART:
|
||||
|
||||
case HSCAN_FROM_END:
|
||||
case HSCAN_BODY_END:
|
||||
case HSCAN_MULTIPART_END:
|
||||
case HSCAN_MESSAGE_END:
|
||||
|
||||
s->state = s->parts->savestate;
|
||||
folder_pull_part(s);
|
||||
if (s->state & HSCAN_END) {
|
||||
s->state &= ~HSCAN_END;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef STANDALONE
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
@ -1182,7 +1460,7 @@ int main(int argc, char **argv)
|
||||
case HSCAN_HEADER:
|
||||
if (s->parts->content_type
|
||||
&& (charset = header_content_type_param(s->parts->content_type, "charset"))) {
|
||||
if (g_strcasecmp(charset, "us-ascii")) {
|
||||
if (strcasecmp(charset, "us-ascii")) {
|
||||
folder_push_filter_charset(s, "UTF-8", charset);
|
||||
} else {
|
||||
charset = NULL;
|
||||
|
||||
@ -89,6 +89,7 @@ void camel_mime_parser_scan_from(CamelMimeParser *, int);
|
||||
/* normal interface */
|
||||
enum _header_state camel_mime_parser_step(CamelMimeParser *, char **, int *);
|
||||
void camel_mime_parser_unstep(CamelMimeParser *);
|
||||
void camel_mime_parser_drop_step(CamelMimeParser *m);
|
||||
enum _header_state camel_mime_parser_state(CamelMimeParser *);
|
||||
|
||||
/* get content type for the current part/header */
|
||||
|
||||
@ -71,11 +71,11 @@ simple_data_wrapper_construct_from_parser(CamelDataWrapper *dw, CamelMimeParser
|
||||
/* first, work out conversion, if any, required, we dont care about what we dont know about */
|
||||
encoding = header_content_encoding_decode(camel_mime_parser_header(mp, "content-transfer-encoding", NULL));
|
||||
if (encoding) {
|
||||
if (!g_strcasecmp(encoding, "base64")) {
|
||||
if (!strcasecmp(encoding, "base64")) {
|
||||
d(printf("Adding base64 decoder ...\n"));
|
||||
fdec = (CamelMimeFilter *)camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_BASE64_DEC);
|
||||
decid = camel_mime_parser_filter_add(mp, fdec);
|
||||
} else if (!g_strcasecmp(encoding, "quoted-printable")) {
|
||||
} else if (!strcasecmp(encoding, "quoted-printable")) {
|
||||
d(printf("Adding quoted-printable decoder ...\n"));
|
||||
fdec = (CamelMimeFilter *)camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_QP_DEC);
|
||||
decid = camel_mime_parser_filter_add(mp, fdec);
|
||||
@ -88,8 +88,8 @@ simple_data_wrapper_construct_from_parser(CamelDataWrapper *dw, CamelMimeParser
|
||||
if (header_content_type_is(ct, "text", "*")) {
|
||||
const char *charset = header_content_type_param(ct, "charset");
|
||||
if (charset!=NULL
|
||||
&& !(g_strcasecmp(charset, "us-ascii")==0
|
||||
|| g_strcasecmp(charset, "utf-8")==0)) {
|
||||
&& !(strcasecmp(charset, "us-ascii")==0
|
||||
|| strcasecmp(charset, "utf-8")==0)) {
|
||||
d(printf("Adding conversion filter from %s to utf-8\n", charset));
|
||||
fch = (CamelMimeFilter *)camel_mime_filter_charset_new_convert(charset, "utf-8");
|
||||
if (fch) {
|
||||
|
||||
@ -606,13 +606,13 @@ camel_mime_part_encoding_from_string (const gchar *string)
|
||||
{
|
||||
if (string == NULL)
|
||||
return CAMEL_MIME_PART_ENCODING_DEFAULT;
|
||||
else if (g_strcasecmp (string, "7bit") == 0)
|
||||
else if (strcasecmp (string, "7bit") == 0)
|
||||
return CAMEL_MIME_PART_ENCODING_7BIT;
|
||||
else if (g_strcasecmp (string, "8bit") == 0)
|
||||
else if (strcasecmp (string, "8bit") == 0)
|
||||
return CAMEL_MIME_PART_ENCODING_8BIT;
|
||||
else if (g_strcasecmp (string, "base64") == 0)
|
||||
else if (strcasecmp (string, "base64") == 0)
|
||||
return CAMEL_MIME_PART_ENCODING_BASE64;
|
||||
else if (g_strcasecmp (string, "quoted-printable") == 0)
|
||||
else if (strcasecmp (string, "quoted-printable") == 0)
|
||||
return CAMEL_MIME_PART_ENCODING_QUOTEDPRINTABLE;
|
||||
else
|
||||
/* FIXME? Spit a warning? */
|
||||
|
||||
@ -808,7 +808,7 @@ char *rfc2047_encode_word(const char *in, int len, char *type)
|
||||
out = buffer;
|
||||
|
||||
/* if we can't convert from utf-8, just encode as utf-8 */
|
||||
if (!g_strcasecmp(type, "UTF-8")
|
||||
if (!strcasecmp(type, "UTF-8")
|
||||
|| (ic = unicode_iconv_open(type, "UTF-8")) == (unicode_iconv_t)-1) {
|
||||
memcpy(buffer, in, len);
|
||||
out = buffer+len;
|
||||
@ -1065,7 +1065,7 @@ header_decode_param(const char **in, char **paramp, char **valuep)
|
||||
char *
|
||||
header_param(struct _header_param *p, const char *name)
|
||||
{
|
||||
while (p && g_strcasecmp(p->name, name) != 0)
|
||||
while (p && strcasecmp(p->name, name) != 0)
|
||||
p = p->next;
|
||||
if (p)
|
||||
return p->value;
|
||||
@ -1079,7 +1079,7 @@ header_set_param(struct _header_param **l, const char *name, const char *value)
|
||||
|
||||
while (p->next) {
|
||||
pn = p->next;
|
||||
if (!g_strcasecmp(pn->name, name)) {
|
||||
if (!strcasecmp(pn->name, name)) {
|
||||
g_free(pn->value);
|
||||
if (value) {
|
||||
pn->value = g_strdup(value);
|
||||
@ -1135,16 +1135,16 @@ header_content_type_is(struct _header_content_type *ct, const char *type, const
|
||||
{
|
||||
/* no type == text/plain or text/"*" */
|
||||
if (ct==NULL) {
|
||||
return (!g_strcasecmp(type, "text")
|
||||
&& (!g_strcasecmp(subtype, "plain")
|
||||
|| !g_strcasecmp(subtype, "*")));
|
||||
return (!strcasecmp(type, "text")
|
||||
&& (!strcasecmp(subtype, "plain")
|
||||
|| !strcasecmp(subtype, "*")));
|
||||
}
|
||||
|
||||
return (ct->type != NULL
|
||||
&& (!g_strcasecmp(ct->type, type)
|
||||
&& (!strcasecmp(ct->type, type)
|
||||
&& ((ct->subtype != NULL
|
||||
&& !g_strcasecmp(ct->subtype, subtype))
|
||||
|| !g_strcasecmp("*", subtype))));
|
||||
&& !strcasecmp(ct->subtype, subtype))
|
||||
|| !strcasecmp("*", subtype))));
|
||||
}
|
||||
|
||||
void
|
||||
@ -1660,7 +1660,7 @@ header_content_type_decode(const char *in)
|
||||
inptr++;
|
||||
subtype = decode_token(&inptr);
|
||||
}
|
||||
if (subtype == NULL && (!g_strcasecmp(type, "text"))) {
|
||||
if (subtype == NULL && (!strcasecmp(type, "text"))) {
|
||||
g_warning("text type with no subtype, resorting to text/plain: %s", in);
|
||||
subtype = g_strdup("plain");
|
||||
}
|
||||
@ -1713,7 +1713,7 @@ header_content_type_format(struct _header_content_type *ct)
|
||||
g_warning("Content-Type with no main type");
|
||||
} else if (ct->subtype == NULL) {
|
||||
g_warning("Content-Type with no sub type: %s", ct->type);
|
||||
if (!g_strcasecmp(ct->type, "multipart"))
|
||||
if (!strcasecmp(ct->type, "multipart"))
|
||||
g_string_sprintfa(out, "%s/mixed", ct->type);
|
||||
else
|
||||
g_string_sprintfa(out, "%s", ct->type);
|
||||
@ -1879,7 +1879,7 @@ header_decode_date(const char *in, int *saveoffset)
|
||||
monthname = decode_token(&inptr);
|
||||
if (monthname) {
|
||||
for (i=0;i<sizeof(tz_months)/sizeof(tz_months[0]);i++) {
|
||||
if (!g_strcasecmp(tz_months[i], monthname)) {
|
||||
if (!strcasecmp(tz_months[i], monthname)) {
|
||||
tm.tm_mon = i;
|
||||
break;
|
||||
}
|
||||
@ -1916,7 +1916,7 @@ header_decode_date(const char *in, int *saveoffset)
|
||||
|
||||
if (tz) {
|
||||
for (i=0;i<sizeof(tz_offsets)/sizeof(tz_offsets[0]);i++) {
|
||||
if (!g_strcasecmp(tz_offsets[i].name, tz)) {
|
||||
if (!strcasecmp(tz_offsets[i].name, tz)) {
|
||||
offset = tz_offsets[i].offset;
|
||||
break;
|
||||
}
|
||||
@ -2031,13 +2031,13 @@ header_raw_append(struct _header_raw **list, const char *name, const char *value
|
||||
|
||||
/* debug */
|
||||
#if 0
|
||||
if (!g_strcasecmp(name, "To")) {
|
||||
if (!strcasecmp(name, "To")) {
|
||||
printf("- Decoding To\n");
|
||||
header_to_decode(value);
|
||||
} else if (!g_strcasecmp(name, "Content-type")) {
|
||||
} else if (!strcasecmp(name, "Content-type")) {
|
||||
printf("- Decoding content-type\n");
|
||||
header_content_type_dump(header_content_type_decode(value));
|
||||
} else if (!g_strcasecmp(name, "MIME-Version")) {
|
||||
} else if (!strcasecmp(name, "MIME-Version")) {
|
||||
printf("- Decoding mime version\n");
|
||||
header_mime_decode(value);
|
||||
}
|
||||
@ -2051,7 +2051,7 @@ header_raw_find_node(struct _header_raw **list, const char *name)
|
||||
|
||||
l = *list;
|
||||
while (l) {
|
||||
if (!g_strcasecmp(l->name, name))
|
||||
if (!strcasecmp(l->name, name))
|
||||
break;
|
||||
l = l->next;
|
||||
}
|
||||
@ -2103,7 +2103,7 @@ header_raw_remove(struct _header_raw **list, const char *name)
|
||||
p = (struct _header_raw *)list;
|
||||
l = *list;
|
||||
while (l) {
|
||||
if (!g_strcasecmp(l->name, name)) {
|
||||
if (!strcasecmp(l->name, name)) {
|
||||
p->next = l->next;
|
||||
header_raw_free(l);
|
||||
l = p->next;
|
||||
|
||||
@ -595,7 +595,7 @@ header_write(int fd, struct _header_raw *header, unsigned int uid, unsigned int
|
||||
iv[3].iov_len = 1;
|
||||
|
||||
while (header) {
|
||||
if (g_strcasecmp(header->name, "x-evolution")) {
|
||||
if (strcasecmp(header->name, "x-evolution")) {
|
||||
int len;
|
||||
|
||||
iv[0].iov_base = header->name;
|
||||
@ -876,12 +876,12 @@ static int index_folder(CamelMboxSummary *s, int startoffset)
|
||||
messages/message parts */
|
||||
encoding = header_content_encoding_decode(camel_mime_parser_header(mp, "content-transfer-encoding", NULL));
|
||||
if (encoding) {
|
||||
if (!g_strcasecmp(encoding, "base64")) {
|
||||
if (!strcasecmp(encoding, "base64")) {
|
||||
d(printf("Adding decoding filter for base64\n"));
|
||||
if (mf64 == NULL)
|
||||
mf64 = camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_BASE64_DEC);
|
||||
enc_id = camel_mime_parser_filter_add(mp, (CamelMimeFilter *)mf64);
|
||||
} else if (!g_strcasecmp(encoding, "quoted-printable")) {
|
||||
} else if (!strcasecmp(encoding, "quoted-printable")) {
|
||||
d(printf("Adding decoding filter for quoted-printable\n"));
|
||||
if (mfqp == NULL)
|
||||
mfqp = camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_QP_DEC);
|
||||
@ -892,8 +892,8 @@ static int index_folder(CamelMboxSummary *s, int startoffset)
|
||||
|
||||
charset = header_content_type_param(ct, "charset");
|
||||
if (charset!=NULL
|
||||
&& !(g_strcasecmp(charset, "us-ascii")==0
|
||||
|| g_strcasecmp(charset, "utf-8")==0)) {
|
||||
&& !(strcasecmp(charset, "us-ascii")==0
|
||||
|| strcasecmp(charset, "utf-8")==0)) {
|
||||
d(printf("Adding conversion filter from %s to utf-8\n", charset));
|
||||
if (mfc == NULL)
|
||||
mfc = camel_mime_filter_charset_new_convert(charset, "utf-8");
|
||||
|
||||
Reference in New Issue
Block a user