Name

rfc2045 — RFC 2045 (MIME) parsing library

Synopsis

#include <rfc822.h>
#include <rfc2045.h>

cc ... -lrfc2045 -lrfc822

DESCRIPTION

The rfc2045 library parses MIME-formatted messages. The rfc2045 library is used to:

1) Parse the structure of a MIME formatted message

2) Examine the contents of each MIME section

3) Optionally rewrite and reformat the message.

Creating an rfc2045 structure

#include <rfc2045.h>

struct rfc2045 *ptr=rfc2045_alloc();
void rfc2045_parse(struct rfc2045 *ptr, const char *txt, size_t cnt);

struct rfc2045 *ptr=rfc2045_fromfd(int fd);
struct rfc2045 *ptr=rfc2045_fromfp(FILE *fp);

void rfc2045_free(struct rfc2045 *ptr);

void rfc2045_error(const char *errmsg)
{
        perror(errmsg);
        exit(0);
}

The rfc2045 structure is created from an existing message. The function rfc2045_alloc() allocates the structure, then rfc2045_parse() is called to initialize the structure based on the contents of a message. txt points to the contents of the message, and cnt contains the number of bytes in the message.

Large messages are parsed by calling rfc2045_parse() multiple number of times, each time passing a portion of the overall message. There is no need to call a separate function after the entire message is parsed -- the rfc2045 structure is created dynamically, on the fly.

rfc2045_alloc() returns NULL if there was insufficient memory to allocate the structure. The rfc2045_parse() also allocates memory, internally, however no error indication is return in the event of a memory allocation failure. Instead, the function rfc2045_error() is called, with errmsg set to "Out of memory". rfc2045_error() is also called by rfc2045_alloc() - it also calls rfc2045_error(), before returning a NULL pointer.

The rfc2045_error() function is not included in the rfc2045 library, it must be defined by the application to report the error in some appropriate way. All functions below will use rfc2045_error() to report an error condition (currently only insufficient memory is reported), in addition to returning any kind of an error indicator. Some functions do not return an error indicator, so rfc2045_error() is the only reliable way to detect a failure.

The rfc2045_fromfd() function initializes an rfc2045 structure from a file descriptor. It is equivalent to calling rfc2045_alloc(), then reading the contents of the given file descriptor, and calling rfc2045_parse(). The rfc2045_fromfp() function initializes an rfc2045 structure from a FILE.

After the rfc2045 structure is initialized, the functions described below may be used to access and work with the contents of the structure. When the rfc2045 structure is no longer needed, the function rfc2045_free() deallocates and destroys the structure.

Structure of a MIME message


struct rfc2045 {

        struct rfc2045 *parent;

        struct rfc2045 *firstpart;
        struct rfc2045 *next;
        int             isdummy;
        int             rfcviolation;
} ;

The rfc2045 structure has many fields, only some are publicly documented. A MIME message is represented by a recursive tree of linked rfc2045 structures. Each instance of the rfc2045 structure represents a single MIME section of a MIME-formatted message.

The top-level structure that represents the entire message is created by the rfc2045_alloc() function. The remaining structures are created dynamically by rfc2045_parse(). Any rfc2045 structure, except ones whose isdummy flag is set, may be used as an argument to any function described in the following chapters.

The rfcviolation field in the top-level rfc2045 indicates any errors found while parsing the MIME message. rfcviolation is a bitmask of the following flags:

RFC2045_ERR8BITHEADER

Illegal 8-bit characters in MIME headers.

RFC2045_ERR8BITCONTENT

Illegal 8-bit contents of a MIME section that declared a 7bit transfer encoding.

RFC2045_ERR2COMPLEX

The message has too many MIME sections, this is a potential denial-of-service attack.

RFC2045_ERRBADBOUNDARY

Ambiguous nested multipart MIME boundary strings. (Nested MIME boundary strings where one string is a prefix of another string).

In each rfc2045 structure that represents a multipart MIME section (or one that contains message/rfc822 content) the firstpart pointer points to the first MIME section in the multipart MIME section (or the included "message/rfc822" MIME section). If there are more than one MIME sections in a multipart MIME section firstpart->next gets you the second MIME section, firstpart->next->next gets you the third MIME section, and so on. parent points to the parent MIME section, which is NULL for the top-level MIME section.

Not all MIME sections are created equal. In a multipart MIME section, there is an initial, unused, "filler" section before the first MIME delimiter (see RFC 2045 for more information). This filler section typically contains a terse message saying that this is a MIME-formatted message. This is not considered to be a "real" MIME section, and all MIME-aware software must ignore those. These filler sections are designated by setting the isdummy field to a non-zero value. All rfc2045 structures that have isdummy set should be ignored, and skipped over, when traversing the rfc2045 tree.

Basic MIME information


const char *content_type, *content_transfer_encoding,
           *content_character_set;

void rfc2045_mimeinfo(const struct rfc2045 *ptr,
        &content_type, &content_transfer_encoding,
        &content_character_set);

off_t start_pos, end_pos, start_body, nlines, nbodylines;

void rfc2045_mimepos(const struct rfc2045 *ptr,
        &start_pos, &end_pos, &start_body, &nlines,
        &nbodylines);

The rfc2045_mimeinfo() function returns the MIME content type, encoding method, and the character set of the given MIME section. Where the MIME section does not specify any property, rfc2045_mimeinfo() automatically supplies a default value. The character set is only meaningful for MIME sections with a text content type, however it is still defaulted for other sections. It is not permissible to supply a NULL pointer for any argument to rfc2045_mimeinfo().

The rfc2045_mimepos() function locates the position of the given MIME section in the original message. It is not permissible to supply a NULL pointer for any argument to rfc2045_mimepos(). All arguments must be used.

start_pos and end_pos point to the starting and the ending offset, from the beginning of the message, of this MIME section. nlines is initialized to the number of lines of text in this MIME section. start_pos is the start of MIME headers for this MIME section. start_body is the start of the actual content of this MIME section (after all the MIME headers, and the delimiting blank line), and nbodylines is the number of lines of actual content in this MIME section.


const char *id=rfc2045_content_id(
                       const struct rfc2045 *ptr);

const char *desc=rfc2045_content_description(
                       const struct rfc2045 *ptr);

const char *lang=rfc2045_content_language(
                       const struct rfc2045 *ptr);

const char *md5=rfc2045_content_md5(
                       const struct rfc2045 *ptr);

These functions return the contents of the corresponding MIME headers. If these headers do not exist, these functions return an empty string, "", NOT a null pointer.


char *id=rfc2045_related_start(const struct rfc2045 *ptr);

This function returns the start attribute of the Content-Type: header, which is used by multipart/related MIME content. This function returns a dynamically-allocated buffer, which must be free(3)-ed after use (a null pointer is returned if there was insufficient memory for the buffer, and rfc2045_error() is called).


const struct rfc2045 *ptr;

const char *disposition=ptr->content_dispos