658 lines
16 KiB
C
658 lines
16 KiB
C
|
/*
|
||
|
* $Id$
|
||
|
*
|
||
|
* MiniMIME - a library for handling MIME messages
|
||
|
*
|
||
|
* Copyright (C) 2003 Jann Fischer <rezine@mistrust.net>
|
||
|
* All rights reserved.
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions
|
||
|
* are met:
|
||
|
*
|
||
|
* 1. Redistributions of source code must retain the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer.
|
||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer in the
|
||
|
* documentation and/or other materials provided with the distribution.
|
||
|
* 3. Neither the name of the author nor the names of the contributors
|
||
|
* may be used to endorse or promote products derived from this software
|
||
|
* without specific prior written permission.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND
|
||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||
|
* ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD
|
||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
*/
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <unistd.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <ctype.h>
|
||
|
#include <assert.h>
|
||
|
|
||
|
#include "mm_internal.h"
|
||
|
|
||
|
/** @file mm_mimepart.c
|
||
|
*
|
||
|
* This module contains functions for manipulating MIME header objects.
|
||
|
*/
|
||
|
|
||
|
/** @defgroup mimepart Accessing and manipulating MIME parts
|
||
|
*
|
||
|
* MIME parts, also called entities, represent the structure of a MIME
|
||
|
* message. ``Normal'' internet messages have only a single part, and
|
||
|
* are called ``flat'' messages. Multipart messages have more then one
|
||
|
* part, and each MIME part can have it's own subset of headers.
|
||
|
*
|
||
|
* Provided here are functions to easily access all informations from
|
||
|
* a MIME part, including their specific headers and bodies.
|
||
|
*/
|
||
|
|
||
|
/** @{
|
||
|
* @name Creating and destroying MIME parts
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Allocates memory for a new mm_mimepart structure and initializes it.
|
||
|
*
|
||
|
* @return A pointer to a struct of type mm_mimeheader or NULL on failure
|
||
|
* @see mm_mimepart_free
|
||
|
* @note The memory must be freed by using mm_mimepart_free() later on.
|
||
|
*/
|
||
|
struct mm_mimepart *
|
||
|
mm_mimepart_new(void)
|
||
|
{
|
||
|
struct mm_mimepart *part;
|
||
|
|
||
|
part = (struct mm_mimepart *)xmalloc(sizeof(struct mm_mimepart));
|
||
|
|
||
|
TAILQ_INIT(&part->headers);
|
||
|
|
||
|
part->opaque_length = 0;
|
||
|
part->opaque_body = NULL;
|
||
|
|
||
|
part->length = 0;
|
||
|
part->body = NULL;
|
||
|
|
||
|
part->type = NULL;
|
||
|
|
||
|
return part;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a MIME part from a file
|
||
|
*
|
||
|
* @param filename The name of the file to create the MIME part from
|
||
|
* @return A pointer to a new MIME part object
|
||
|
*
|
||
|
* This function creates a new MIME part object from a file. The object should
|
||
|
* be freed using mm_mimepart_free() later on. This function does NOT set the
|
||
|
* Content-Type and neither does any encoding work.
|
||
|
*/
|
||
|
struct mm_mimepart *
|
||
|
mm_mimepart_fromfile(const char *filename)
|
||
|
{
|
||
|
int fd;
|
||
|
char *data;
|
||
|
size_t r;
|
||
|
struct stat st;
|
||
|
struct mm_mimepart *part;
|
||
|
|
||
|
mm_errno = MM_ERROR_NONE;
|
||
|
|
||
|
if ((fd = open(filename, O_RDONLY)) == -1) {
|
||
|
mm_errno = MM_ERROR_ERRNO;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
if ((stat(filename, &st)) == -1) {
|
||
|
mm_errno = MM_ERROR_ERRNO;
|
||
|
close(fd);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
data = xmalloc(st.st_size);
|
||
|
r = read(fd, data, st.st_size);
|
||
|
if (r != st.st_size) {
|
||
|
mm_errno = MM_ERROR_ERRNO;
|
||
|
close(fd);
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
data[r] = '\0';
|
||
|
close(fd);
|
||
|
|
||
|
part = mm_mimepart_new();
|
||
|
part->length = r;
|
||
|
part->body = data;
|
||
|
|
||
|
return part;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Frees all memory allocated by a mm_mimepart object.
|
||
|
*
|
||
|
* @param part A pointer to an allocated mm_mimepart object
|
||
|
* @see mm_mimepart_new
|
||
|
*/
|
||
|
void
|
||
|
mm_mimepart_free(struct mm_mimepart *part)
|
||
|
{
|
||
|
struct mm_mimeheader *header;
|
||
|
|
||
|
assert(part != NULL);
|
||
|
|
||
|
TAILQ_FOREACH(header, &part->headers, next) {
|
||
|
mm_mimeheader_free(header);
|
||
|
TAILQ_REMOVE(&part->headers, header, next);
|
||
|
}
|
||
|
|
||
|
if (part->opaque_body != NULL) {
|
||
|
xfree(part->opaque_body);
|
||
|
part->opaque_body = NULL;
|
||
|
part->body = NULL;
|
||
|
} else if (part->body != NULL) {
|
||
|
xfree(part->body);
|
||
|
part->body = NULL;
|
||
|
}
|
||
|
|
||
|
if (part->type != NULL) {
|
||
|
mm_content_free(part->type);
|
||
|
part->type = NULL;
|
||
|
}
|
||
|
|
||
|
xfree(part);
|
||
|
part = NULL;
|
||
|
}
|
||
|
|
||
|
/** @} */
|
||
|
|
||
|
/** @{
|
||
|
* @name Accessing the MIME part's mail header
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Attaches a mm_mimeheader object to a MIME part
|
||
|
*
|
||
|
* @param part A valid MIME part object
|
||
|
* @param header A valid MIME header object
|
||
|
* @return 0 if successfull or -1 if the header could not be attached
|
||
|
*/
|
||
|
int
|
||
|
mm_mimepart_attachheader(struct mm_mimepart *part, struct mm_mimeheader *header)
|
||
|
{
|
||
|
assert(part != NULL);
|
||
|
assert(header != NULL);
|
||
|
|
||
|
if (TAILQ_EMPTY(&part->headers)) {
|
||
|
TAILQ_INSERT_HEAD(&part->headers, header, next);
|
||
|
} else {
|
||
|
TAILQ_INSERT_TAIL(&part->headers, header, next);
|
||
|
}
|
||
|
|
||
|
return(0);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Retrieves the number of MIME headers available in a MIME part
|
||
|
*
|
||
|
* @param part A valid MIME part object
|
||
|
* @return The number of MIME headers within the MIME part
|
||
|
*/
|
||
|
int
|
||
|
mm_mimepart_countheaders(struct mm_mimepart *part)
|
||
|
{
|
||
|
int found;
|
||
|
struct mm_mimeheader *header;
|
||
|
|
||
|
assert(part != NULL);
|
||
|
|
||
|
found = 0;
|
||
|
|
||
|
TAILQ_FOREACH(header, &part->headers, next) {
|
||
|
found++;
|
||
|
}
|
||
|
|
||
|
return found;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Retrieves the number of MIME headers with a given name in a MIME part
|
||
|
*
|
||
|
* @param part A valid MIME part object
|
||
|
* @param name The name of the MIME header which to count for
|
||
|
* @return The number of MIME headers within the MIME part
|
||
|
*/
|
||
|
int
|
||
|
mm_mimepart_countheaderbyname(struct mm_mimepart *part, const char *name)
|
||
|
{
|
||
|
int found;
|
||
|
struct mm_mimeheader *header;
|
||
|
|
||
|
assert(part != NULL);
|
||
|
|
||
|
found = 0;
|
||
|
|
||
|
TAILQ_FOREACH(header, &part->headers, next) {
|
||
|
if (strcasecmp(header->name, name) == 0) {
|
||
|
found++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return found;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get a MIME header object from a MIME part
|
||
|
*
|
||
|
* @param part A valid MIME part object
|
||
|
* @param name The name of the MIME header which to retrieve
|
||
|
* @param idx Which header field to get (in case of multiple headers of the
|
||
|
* same name).
|
||
|
* @return A pointer to the requested MIME header on success, or NULL if there
|
||
|
* either isn't a header with the requested name or idx is out of
|
||
|
* range.
|
||
|
*/
|
||
|
struct mm_mimeheader *
|
||
|
mm_mimepart_getheaderbyname(struct mm_mimepart *part, const char *name, int idx)
|
||
|
{
|
||
|
struct mm_mimeheader *header;
|
||
|
int curidx;
|
||
|
|
||
|
curidx = 0;
|
||
|
|
||
|
TAILQ_FOREACH(header, &part->headers, next) {
|
||
|
if (!strcasecmp(header->name, name)) {
|
||
|
if (curidx == idx)
|
||
|
return header;
|
||
|
else
|
||
|
curidx++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Not found */
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the value of a MIME header object
|
||
|
*
|
||
|
* @param part A valid MIME part object
|
||
|
* @param name The name of the header field to get the value from
|
||
|
* @param idx The index of the header field to get, in case there are multiple
|
||
|
* headers with the same name.
|
||
|
* @return A pointer to the requested value on success, or NULL if there either
|
||
|
* isn't a header with the requested name or idx is out of range.
|
||
|
*
|
||
|
*/
|
||
|
const char *
|
||
|
mm_mimepart_getheadervalue(struct mm_mimepart *part, const char *name, int idx)
|
||
|
{
|
||
|
struct mm_mimeheader *header;
|
||
|
|
||
|
header = mm_mimepart_getheaderbyname(part, name, idx);
|
||
|
if (header == NULL)
|
||
|
return NULL;
|
||
|
else
|
||
|
return header->value;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Initializes a header loop for a given MIME part
|
||
|
*
|
||
|
* @param part A valid MIME part object
|
||
|
* @param id The address of a MIME header object (to allow reentrance)
|
||
|
* @return 0 on success or -1 on failure
|
||
|
* @see mm_mimepart_headers_next
|
||
|
*
|
||
|
* Looping through headers can be done in the following way:
|
||
|
*
|
||
|
* @code
|
||
|
* struct mm_mimeheader *header, *lheader;
|
||
|
*
|
||
|
* mm_mimepart_headers_start(part, &lheader);
|
||
|
*
|
||
|
* while ((header = mm_mimepart_headers_next(part, &lheader)) != NULL) {
|
||
|
* printf("%s: %s\n", header->name, header->value);
|
||
|
* }
|
||
|
*
|
||
|
* @endcode
|
||
|
*
|
||
|
* For convienience, the macro mm_mimepart_headers_foreach() can be used to
|
||
|
* loop through headers in a one-shot manner.
|
||
|
*/
|
||
|
int
|
||
|
mm_mimepart_headers_start(struct mm_mimepart *part, struct mm_mimeheader **id)
|
||
|
{
|
||
|
assert(part != NULL);
|
||
|
|
||
|
if (TAILQ_EMPTY(&part->headers)) {
|
||
|
return -1;
|
||
|
}
|
||
|
*id = NULL;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the next MIME header of a given MIME part object
|
||
|
*
|
||
|
* @param part A valid MIME part object
|
||
|
* @param id A previously initialized MIME header object
|
||
|
* @return A pointer to the MIME header object or NULL if end of headers was
|
||
|
* reached.
|
||
|
* @see mm_mimepart_headers_start
|
||
|
*/
|
||
|
struct mm_mimeheader *
|
||
|
mm_mimepart_headers_next(struct mm_mimepart *part, struct mm_mimeheader **id)
|
||
|
{
|
||
|
struct mm_mimeheader *header;
|
||
|
|
||
|
assert(part != NULL);
|
||
|
|
||
|
if (*id == NULL) {
|
||
|
header = TAILQ_FIRST(&part->headers);
|
||
|
} else {
|
||
|
header = TAILQ_NEXT(*id, next);
|
||
|
}
|
||
|
*id = header;
|
||
|
|
||
|
return header;
|
||
|
}
|
||
|
|
||
|
/** @} */
|
||
|
|
||
|
/** @{
|
||
|
* @name Accessing and manipulating the MIME part's body
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Gets the pointer to the MIME part's body data
|
||
|
*
|
||
|
* @param part A valid MIME part object
|
||
|
* @param opaque Whether to get the opaque part or not
|
||
|
* @return A pointer to the MIME part's body
|
||
|
* @see mm_mimepart_setbody
|
||
|
*
|
||
|
*/
|
||
|
char *
|
||
|
mm_mimepart_getbody(struct mm_mimepart *part, int opaque)
|
||
|
{
|
||
|
assert(part != NULL);
|
||
|
|
||
|
if (opaque)
|
||
|
return part->opaque_body;
|
||
|
else
|
||
|
return part->body;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the MIME part's body data
|
||
|
*
|
||
|
* @param part A valid MIME part object
|
||
|
* @param data A pointer to the data which to set
|
||
|
* @see mm_mimepart_getbody
|
||
|
*
|
||
|
* This functions sets the body data for a given MIME part. The string pointed
|
||
|
* to by data must be NUL-terminated. The data is copied into the MIME part's
|
||
|
* body, and thus, the memory pointed to by data can be freed after the
|
||
|
* operation.
|
||
|
*/
|
||
|
void
|
||
|
mm_mimepart_setbody(struct mm_mimepart *part, const char *data, int opaque)
|
||
|
{
|
||
|
assert(part != NULL);
|
||
|
assert(data != NULL);
|
||
|
|
||
|
if (opaque) {
|
||
|
part->opaque_body = xstrdup(data);
|
||
|
part->body = part->opaque_body;
|
||
|
} else {
|
||
|
part->body = xstrdup(data);
|
||
|
}
|
||
|
part->length = strlen(data);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the length of a given MIME part object
|
||
|
*
|
||
|
* @param part A valid MIME part object
|
||
|
* @returns The size of the part's body in byte.
|
||
|
*
|
||
|
* This function returns the total length of the given MIME part's body. The
|
||
|
* length does not include the headers of the MIME parts. If the function
|
||
|
* returns 0, no body part is set currently.
|
||
|
*/
|
||
|
size_t
|
||
|
mm_mimepart_getlength(struct mm_mimepart *part)
|
||
|
{
|
||
|
assert(part != NULL);
|
||
|
|
||
|
return part->length;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Decodes a MIME part according to it's encoding using MiniMIME codecs
|
||
|
*
|
||
|
* @param A valid MIME part object
|
||
|
* @return 0 if the MIME part could be successfully decoded or -1 if not
|
||
|
* @note Sets mm_errno on error
|
||
|
*
|
||
|
* This function decodes the body of a MIME part with a registered decoder
|
||
|
* according to it's Content-Transfer-Encoding header field.
|
||
|
*/
|
||
|
char *
|
||
|
mm_mimepart_decode(struct mm_mimepart *part)
|
||
|
{
|
||
|
extern struct mm_codecs codecs;
|
||
|
struct mm_codec *codec;
|
||
|
void *decoded;
|
||
|
|
||
|
assert(part != NULL);
|
||
|
assert(part->type != NULL);
|
||
|
|
||
|
decoded = NULL;
|
||
|
|
||
|
/* No encoding associated */
|
||
|
if (part->type->encstring == NULL)
|
||
|
return NULL;
|
||
|
|
||
|
/* Loop through codecs and find a suitable one */
|
||
|
SLIST_FOREACH(codec, &codecs, next) {
|
||
|
if (!strcasecmp(part->type->encstring, codec->encoding)) {
|
||
|
decoded = codec->decoder((char *)part->body);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return decoded;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates an ASCII representation of the given MIME part
|
||
|
*
|
||
|
* @param part A valid MIME part object
|
||
|
* @param result Where to store the result
|
||
|
* @param length Where to store the length of the result
|
||
|
* @param opaque Whether to use the opaque MIME part
|
||
|
* @returtn 0 on success or -1 on error.
|
||
|
* @see mm_context_flatten
|
||
|
*
|
||
|
* This function creates an ASCII representation of a given MIME part. It will
|
||
|
* dynamically allocate the memory needed and stores the result in the memory
|
||
|
* region pointed to by result. The length of the result will be stored in
|
||
|
* length. If opaque is set to 1, mm_mimepart_flatten will store an opaque
|
||
|
* version of the MIME part in result, which means no headers will be created
|
||
|
* or sanitized. This is particulary useful if the part is digitally signed by
|
||
|
* e.g. PGP, and the signature spans the header fields of the part in question.
|
||
|
*
|
||
|
*/
|
||
|
int
|
||
|
mm_mimepart_flatten(struct mm_mimepart *part, char **result, size_t *length,
|
||
|
int opaque)
|
||
|
{
|
||
|
size_t part_length;
|
||
|
char *buf;
|
||
|
char *ct_hdr;
|
||
|
|
||
|
*result = NULL;
|
||
|
*length = 0;
|
||
|
buf = NULL;
|
||
|
ct_hdr = NULL;
|
||
|
part_length = 0;
|
||
|
|
||
|
if (opaque && part->opaque_body != NULL) {
|
||
|
part_length = strlen(part->opaque_body);
|
||
|
*result = xstrdup(part->opaque_body);
|
||
|
*length = part_length;
|
||
|
return(0);
|
||
|
} else {
|
||
|
if (part->type == NULL) {
|
||
|
return(-1);
|
||
|
}
|
||
|
|
||
|
ct_hdr = mm_content_tostring(part->type);
|
||
|
if (ct_hdr == NULL) {
|
||
|
return(-1);
|
||
|
}
|
||
|
|
||
|
part_length += strlen(ct_hdr) + 2;
|
||
|
part_length += strlen("\r\n") * 2;
|
||
|
part_length += strlen(part->body);
|
||
|
|
||
|
if (part_length < 0) {
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
buf = (char *) xmalloc(part_length);
|
||
|
if (buf == NULL) {
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
snprintf(buf, part_length,
|
||
|
"%s\r\n\r\n%s\r\n",
|
||
|
ct_hdr,
|
||
|
part->body);
|
||
|
|
||
|
xfree(ct_hdr);
|
||
|
ct_hdr = NULL;
|
||
|
|
||
|
*result = buf;
|
||
|
*length = part_length;
|
||
|
}
|
||
|
|
||
|
return(0);
|
||
|
|
||
|
cleanup:
|
||
|
if (ct_hdr != NULL) {
|
||
|
xfree(ct_hdr);
|
||
|
ct_hdr = NULL;
|
||
|
}
|
||
|
if (buf != NULL) {
|
||
|
xfree(buf);
|
||
|
buf = NULL;
|
||
|
}
|
||
|
|
||
|
*result = NULL;
|
||
|
*length = 0;
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the default Content-Type for a given MIME part
|
||
|
*
|
||
|
* @param part A valid MIME part object
|
||
|
* @param part Whether the Content-Type should be for composite or not
|
||
|
* @return 0 on success or -1 on failure
|
||
|
*
|
||
|
* This function sets a default Content-Type according to RFC 2045 with a value
|
||
|
* of "text/plain; charset="us-ascii"". This function should only be used if
|
||
|
* the MIME part in question does not have a valid Content-Type specification.
|
||
|
*/
|
||
|
int
|
||
|
mm_mimepart_setdefaultcontenttype(struct mm_mimepart *part, int composite)
|
||
|
{
|
||
|
struct mm_content *type;
|
||
|
struct mm_param *param;
|
||
|
|
||
|
if (part == NULL) {
|
||
|
return(-1);
|
||
|
}
|
||
|
|
||
|
if (part->type != NULL) {
|
||
|
mm_content_free(part->type);
|
||
|
part->type = NULL;
|
||
|
}
|
||
|
|
||
|
type = mm_content_new();
|
||
|
if (composite) {
|
||
|
type->maintype = xstrdup("multipart");
|
||
|
type->subtype = xstrdup("mixed");
|
||
|
} else {
|
||
|
type->maintype = xstrdup("text");
|
||
|
type->subtype = xstrdup("plain");
|
||
|
param = mm_param_new();
|
||
|
param->name = xstrdup("charset");
|
||
|
param->value = xstrdup("us-ascii");
|
||
|
mm_content_attachtypeparam(type, param);
|
||
|
}
|
||
|
|
||
|
mm_mimepart_attachcontenttype(part, type);
|
||
|
|
||
|
return (0);
|
||
|
}
|
||
|
|
||
|
/** @{
|
||
|
* @name Accessing the MIME part's Content-Type information
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Attaches a context type object to a MIME part
|
||
|
*
|
||
|
* @param part A valid MIME part object
|
||
|
* @param ct The content type object to attach
|
||
|
* @return Nothing
|
||
|
*
|
||
|
* This function attaches a Content-Type object to a MIME part. It does not
|
||
|
* care whether the Content-Type suites the actual content in the MIME part,
|
||
|
* so the programmer should take care of that.
|
||
|
*/
|
||
|
void
|
||
|
mm_mimepart_attachcontenttype(struct mm_mimepart *part, struct mm_content *ct)
|
||
|
{
|
||
|
part->type = ct;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the Content-Type of a given MIME part object
|
||
|
*
|
||
|
* @param part A valid MIME part object
|
||
|
* @return The Content-Type object of the specified MIME part
|
||
|
*
|
||
|
* This function returns a pointer to the Content-Type object of the given
|
||
|
* MIME part. This pointer might be set to NULL, indicating that there is
|
||
|
* no Content-Type object for the given MIME part currently.
|
||
|
*/
|
||
|
struct mm_content *
|
||
|
mm_mimepart_getcontent(struct mm_mimepart *part)
|
||
|
{
|
||
|
assert(part != NULL);
|
||
|
|
||
|
return part->type;
|
||
|
}
|
||
|
|
||
|
/** @} */
|