/* * $Id$ * * MiniMIME - a library for handling MIME messages * * Copyright (C) 2003 Jann Fischer * 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 #include #include #include #include #include #include "mm_internal.h" #include "mm_util.h" /** @file mm_envelope.c * * This module contains functions for accessing a message's envelope. This * are mainly wrapper functions for easy access. */ /** @defgroup envelope Accessing and manipulating a message's envelope */ /** @{ * @name Accessing and manipulating a message's envelope */ /** * Gets an ASCII representation of all envelope headers * * @param ctx A valid MiniMIME context * @param result Where to store the resulting ASCII headers * @param length Where to store the length of the result * @returns 0 on success or -1 on failure. * @note Sets mm_errno on failure * * This is mainly a convinience function. It constructs an ASCII representation * from all of the message's envelope headers and stores the result in headers. * Memory is allocated dynamically, and the total length of the result is * stored in length. This function takes care that the output is MIME conform, * and folds long lines according to the MIME standard at position 78 of the * string. It also nicely formats all MIME related header fields, such as * the Content-Type header. * * Since the memory needed to store the result is allocated dynamically, one * should take care of freeing it again when it's not needed anymore. If an * error occurs, *result will be set to NULL, *length will be set to zero * and mm_errno will be set to a reasonable value. * */ int mm_envelope_getheaders(MM_CTX *ctx, char **result, size_t *length) { struct mm_mimepart *part; struct mm_mimeheader *hdr; char *buf, *hdrbuf; size_t headers_length, tmp_length; headers_length = 1; buf = NULL; part = mm_context_getpart(ctx, 0); if (part == NULL) { return -1; } /* Initialize our buffer */ if ((buf = (char *)xmalloc(headers_length)) == NULL) { mm_errno = MM_ERROR_ERRNO; goto cleanup; } *buf = '\0'; /* Store each envelope header */ TAILQ_FOREACH(hdr, &part->headers, next) { tmp_length = strlen(hdr->name) + strlen(hdr->value) + strlen(": \r\n"); hdrbuf = (char *) xrealloc(buf, headers_length + tmp_length); if (hdrbuf == NULL) { mm_errno = MM_ERROR_ERRNO; goto cleanup; } headers_length += tmp_length; buf = hdrbuf; strlcat(buf, hdr->name, headers_length); strlcat(buf, ": ", headers_length); strlcat(buf, hdr->value, headers_length); strlcat(buf, "\r\n", headers_length); } /* Construct and store MIME headers */ if (part->type != NULL) { char *typebuf; typebuf = mm_content_tostring(part->type); if (typebuf == NULL) { goto cleanup; } tmp_length = strlen(typebuf) + strlen("\r\n"); hdrbuf = (char *) xrealloc(buf, headers_length + tmp_length); if (hdrbuf == NULL) { mm_errno = MM_ERROR_ERRNO; goto cleanup; } headers_length += tmp_length; buf = hdrbuf; strlcat(buf, typebuf, headers_length); strlcat(buf, "\r\n", headers_length); } *result = buf; *length = headers_length; return 0; cleanup: if (buf != NULL) { xfree(buf); buf = NULL; } *result = NULL; *length = 0; return -1; } /** * Sets a header field in the envelope * * @param ctx A valid MiniMIME context * @param name The name of the header field to set * @param fmt A format string specifying the value of the header field * @return 0 on success or -1 on failure * * This function generates a new MIME header and attaches it to the first * MIME part (the envelope) found in the given context. If no part is * attached already, the function will return an error. The function will * store a copy of ``name'' as the header's name field, and dynamically * allocate the memory needed to build the format string. */ int mm_envelope_setheader(MM_CTX *ctx, const char *name, const char *fmt, ...) { va_list ap; char *buf; struct mm_mimeheader *hdr; struct mm_mimepart *part; part = mm_context_getpart(ctx, 0); if (part == NULL) { return(-1); } hdr = mm_mimeheader_new(); if (hdr == NULL) { return(-1); } hdr->name = xstrdup(name); va_start(ap, fmt); if (vasprintf(&buf, fmt, ap) == -1) { goto cleanup; } va_end(ap); hdr->value = buf; if (mm_mimepart_attachheader(part, hdr) == -1) { goto cleanup; } return(0); cleanup: if (hdr != NULL) { if (hdr->name != NULL) { xfree(hdr->name); hdr->name = NULL; } if (hdr->value != NULL) { xfree(hdr->value); hdr->value = NULL; } } return(-1); } /** * Gets the list of recipients for a MIME message * * @param ctx A valid MiniMIME context * @param result Where to store the result * @param length Where to store the length of the result * @returns 0 on success or -1 on error * @note Sets mm_errno on error * * This functions gets the list of recipients for a given MIME message. It * does so by concatenating the "From" and "Cc" header fields, and storing * the results in recipients. The memory needed to store the result is * allocated dynamically, and the total length of the result is stored in * length. * * One should take care to free() the result once it's not needed anymore. */ #if 0 int mm_envelope_getrecipients(MM_CTX *ctx, char **result, size_t *length) { struct mm_mimepart *part; struct mm_mimeheader *to, *cc; size_t recipients_length = 0; part = mm_context_getpart(ctx, 0); if (part == NULL) { return -1; } to = mm_mimepart_getheaderbyname(part, "From", 0); cc = mm_mimepart_getheaderbyname(part, "Cc", 0); if (to == NULL || cc == NULL) { *result = NULL; *length = 0; return -1; } if (to != NULL) { recipients_length += strlen(to->value); } if (cc != NULL) { recipients_length += strlen(cc->value); } return 0; } #endif /** @} */