Return-Path: Delivered-To: apmail-httpd-cvs-archive@www.apache.org Received: (qmail 87124 invoked from network); 6 Jan 2006 05:18:30 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 6 Jan 2006 05:18:30 -0000 Received: (qmail 82307 invoked by uid 500); 6 Jan 2006 05:18:29 -0000 Delivered-To: apmail-httpd-cvs-archive@httpd.apache.org Received: (qmail 82250 invoked by uid 500); 6 Jan 2006 05:18:28 -0000 Mailing-List: contact cvs-help@httpd.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@httpd.apache.org list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list cvs@httpd.apache.org Received: (qmail 82239 invoked by uid 99); 6 Jan 2006 05:18:28 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 05 Jan 2006 21:18:28 -0800 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.29) with SMTP; Thu, 05 Jan 2006 21:18:26 -0800 Received: (qmail 86880 invoked by uid 65534); 6 Jan 2006 05:18:06 -0000 Message-ID: <20060106051806.86877.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r366430 - in /httpd/mod_mbox/branches/surgery: ./ include/ src/libmbox/ src/libmime/ src/module/ Date: Fri, 06 Jan 2006 05:18:04 -0000 To: cvs@httpd.apache.org From: maxime@apache.org X-Mailer: svnmailer-1.0.5 X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Author: maxime Date: Thu Jan 5 21:17:52 2006 New Revision: 366430 URL: http://svn.apache.org/viewcvs?rev=366430&view=rev Log: Include MIME decoding and CTE handling to libmbox Added: httpd/mod_mbox/branches/surgery/src/libmbox/mbox_cte.c (with props) httpd/mod_mbox/branches/surgery/src/libmbox/mbox_mime.c (with props) Removed: httpd/mod_mbox/branches/surgery/src/libmime/ httpd/mod_mbox/branches/surgery/src/module/mod_mbox_cte.c Modified: httpd/mod_mbox/branches/surgery/Makefile.am httpd/mod_mbox/branches/surgery/configure.ac httpd/mod_mbox/branches/surgery/include/libmbox.h httpd/mod_mbox/branches/surgery/src/libmbox/Makefile.am httpd/mod_mbox/branches/surgery/src/module/Makefile.am httpd/mod_mbox/branches/surgery/src/module/mod_mbox.h httpd/mod_mbox/branches/surgery/src/module/mod_mbox_mime.c Modified: httpd/mod_mbox/branches/surgery/Makefile.am URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/surgery/Makefile.am?rev=366430&r1=366429&r2=366430&view=diff ============================================================================== --- httpd/mod_mbox/branches/surgery/Makefile.am (original) +++ httpd/mod_mbox/branches/surgery/Makefile.am Thu Jan 5 21:17:52 2006 @@ -8,4 +8,4 @@ README \ STATUS -SUBDIRS = src/libmbox src/libmime src/mod-mbox-util src/module +SUBDIRS = src/libmbox src/mod-mbox-util src/module Modified: httpd/mod_mbox/branches/surgery/configure.ac URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/surgery/configure.ac?rev=366430&r1=366429&r2=366430&view=diff ============================================================================== --- httpd/mod_mbox/branches/surgery/configure.ac (original) +++ httpd/mod_mbox/branches/surgery/configure.ac Thu Jan 5 21:17:52 2006 @@ -39,7 +39,7 @@ BIN_LDFLAGS="${LUCENE4C_LIBS} `${APR_CONFIG} --link-libtool` `${APU_CONFIG} --link-libtool` `${APU_CONFIG} --ldflags --libs` `${APR_CONFIG} --ldflags --libs`" AC_SUBST(BIN_LDFLAGS) -AC_CONFIG_FILES([Makefile src/module/Makefile src/libmbox/Makefile src/libmime/Makefile src/mod-mbox-util/Makefile]) +AC_CONFIG_FILES([Makefile src/module/Makefile src/libmbox/Makefile src/mod-mbox-util/Makefile]) AC_OUTPUT echo "---" Modified: httpd/mod_mbox/branches/surgery/include/libmbox.h URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/surgery/include/libmbox.h?rev=366430&r1=366429&r2=366430&view=diff ============================================================================== --- httpd/mod_mbox/branches/surgery/include/libmbox.h (original) +++ httpd/mod_mbox/branches/surgery/include/libmbox.h Thu Jan 5 21:17:52 2006 @@ -28,6 +28,7 @@ #include "util_script.h" #include +#include #include "apr.h" #include "apr_pools.h" @@ -36,6 +37,7 @@ #include "apr_buckets.h" #include "apr_dbm.h" #include "apr_mmap.h" +#include "apr_xlate.h" #ifndef NO_MBOX_SEARCH #include "lcn_init.h" @@ -95,10 +97,6 @@ */ typedef char* ID; -/* Typedefs for Message and Container */ -typedef struct Message_Struct Message; -typedef struct Container_Struct Container; - typedef struct mbox_mime_message { char *body; @@ -115,6 +113,10 @@ unsigned int sub_count; } mbox_mime_message_t; +/* Typedefs for Message and Container */ +typedef struct Message_Struct Message; +typedef struct Container_Struct Container; + /* The basic information about a message. */ struct Message_Struct { @@ -278,6 +280,20 @@ query_callback_fn_t* cb, void* baton); apr_status_t mbox_search_close(mbox_searcher_t* ctx); + +/** mbox_mime */ +mbox_mime_message_t *mbox_mime_decode_multipart(apr_pool_t *p, char *body, + char *ct, mbox_cte_e cte, + char *boundary); + +/** mbox_cte **/ +const char *mbox_cte_to_char(mbox_cte_e cte); +apr_size_t mbox_cte_decode_qp(char* p); +apr_size_t mbox_cte_decode_b64(char *src); +apr_size_t mbox_cte_escape_html(apr_pool_t *p, const char *s, + apr_size_t len, char **body); +char *mbox_cte_decode_rfc2047(apr_pool_t *p, char *src); +char *mbox_cte_decode_header(apr_pool_t *p, char *src); #ifdef __cplusplus } Modified: httpd/mod_mbox/branches/surgery/src/libmbox/Makefile.am URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/surgery/src/libmbox/Makefile.am?rev=366430&r1=366429&r2=366430&view=diff ============================================================================== --- httpd/mod_mbox/branches/surgery/src/libmbox/Makefile.am (original) +++ httpd/mod_mbox/branches/surgery/src/libmbox/Makefile.am Thu Jan 5 21:17:52 2006 @@ -8,8 +8,10 @@ mbox_parse.c \ mbox_sort.c \ mbox_thread.c \ + mbox_mime.c \ + mbox_cte.c \ mbox_externals.c - + libmbox_la_CFLAGS = -Wall ${MODULE_CFLAGS} libmbox_la_LDFLAGS = -avoid-version ${MODULE_LDFLAGS} Added: httpd/mod_mbox/branches/surgery/src/libmbox/mbox_cte.c URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/surgery/src/libmbox/mbox_cte.c?rev=366430&view=auto ============================================================================== --- httpd/mod_mbox/branches/surgery/src/libmbox/mbox_cte.c (added) +++ httpd/mod_mbox/branches/surgery/src/libmbox/mbox_cte.c Thu Jan 5 21:17:52 2006 @@ -0,0 +1,385 @@ +/* Copyright 2001-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Decoding common Content-Encodings of E-Mail functions. + * + * These decoding functions do not copy data. + */ + +#include "libmbox.h" + +/* + * The char64 macro and `mime_decode_b64' routine are taken from + * metamail 2.7, which is copyright (c) 1991 Bell Communications + * Research, Inc. (Bellcore). The following license applies to all + * code below this point: + * + * Permission to use, copy, modify, and distribute this material + * for any purpose and without fee is hereby granted, provided + * that the above copyright notice and this permission notice + * appear in all copies, and that the name of Bellcore not be + * used in advertising or publicity pertaining to this + * material without the specific, prior written permission + * of an authorized representative of Bellcore. BELLCORE + * MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY + * OF THIS MATERIAL FOR ANY PURPOSE. IT IS PROVIDED "AS IS", + * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. + */ + +static char index_64[128] = { + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, + 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, + 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, + -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, + 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 +}; + +#define char64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) + +const char *mbox_cte_to_char(mbox_cte_e cte) +{ + switch(cte) { + case CTE_NONE: + return "None"; + case CTE_7BIT: + return "7-Bit"; + case CTE_8BIT: + return "8-Bit"; + case CTE_UUENCODE: + return "uuencode"; + case CTE_BINARY: + return "Binary"; + case CTE_QP: + return "Quoted Printable"; + case CTE_BASE64: + return "Base64"; + default: + return "Unknown CTE"; + } +} + +/* Unlike the original ap_escape_html, this one is also binary + * safe. + */ +apr_size_t mbox_cte_escape_html(apr_pool_t *p, const char *s, + apr_size_t len, char **body) +{ + char *x; + int i, j; + + /* First, count the number of extra characters */ + for (i = 0, j = 0; i < len; i++) { + if ((s[i] == '<') || (s[i] == '>')) { + j += 3; + } + else if (s[i] == '&') { + j += 4; + } + } + + /* If there is nothing to escape, just copy the body to the new + string */ + if (j == 0) { + j = len; + x = apr_pstrmemdup(p, s, len); + } + + /* Otherwise, we have some extra characters to insert : allocate + enough space for them, and process the data. */ + else { + x = apr_palloc(p, i + j); + + for (i = 0, j = 0; i < len; i++, j++) { + if (s[i] == '<') { + memcpy(&x[j], "<", 4); + j += 3; + } + else if (s[i] == '>') { + memcpy(&x[j], ">", 4); + j += 3; + } + else if (s[i] == '&') { + memcpy(&x[j], "&", 5); + j += 4; + } + else { + x[j] = s[i]; + } + } + } + + *body = x; + return j; +} + +/* Decode BASE64 encoded data */ +apr_size_t mbox_cte_decode_b64(char *src) +{ + apr_size_t len = 0; + + int newline = 1, data_done = 0; + int c1, c2, c3, c4; + char *dst; + + dst = src; + + while ((c1 = *src++) != '\0') { + if (isspace(c1)) { + if (c1 == '\n') { + newline = 1; + } else { + newline = 0; + } + continue; + } + + if (data_done) { + continue; + } + + newline = 0; + + do { + c2 = *src++; + } while (c2 != '\0' && isspace(c2)); + + do { + c3 = *src++; + } while (c3 != '\0' && isspace(c3)); + + do { + c4 = *src++; + } while (c4 != '\0' && isspace(c4)); + + /* Premature EOF. Should return an Error? */ + if ((c2 == '\0') || (c3 == '\0') || (c4 == '\0')) { + return len; + } + + if (c1 == '=' || c2 == '=') { + data_done = 1; + continue; + } + + c1 = char64(c1); + c2 = char64(c2); + *dst++ = (c1 << 2) | ((c2 & 0x30) >> 4); + len++; + + if (c3 == '=') { + data_done = 1; + } + else { + c3 = char64(c3); + *dst++ = ((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2); + len++; + + if (c4 == '=') { + data_done = 1; + } + else { + c4 = char64(c4); + *dst++ = ((c3 & 0x03) << 6) | c4; + len++; + } + } + } + + *dst = '\0'; + return len; +} + +static int hex2dec_char(char ch) +{ + if (isdigit(ch)) { + return ch - '0'; + } + else if (isupper(ch)) { + return ch - 'A' + 10; + } + else { + return ch - 'a' + 10; + } +} + +/* Decode quoted-printable to raw text. */ +apr_size_t mbox_cte_decode_qp(char* p) +{ + apr_size_t len = 0; + char *src, *dst; + + dst = src = p; + while (*src != '\0') { + if (*src == '=') { + if (*++src == '\n') { + ++src; + continue; + } + else { + int hi, lo; + hi = hex2dec_char(*src++); + lo = hex2dec_char(*src); + *dst = (hi * 16) + lo; + } + } + else { + *dst = *src; + } + + ++dst, ++src; + len++; + } + + return len; +} + +/* This function performs the decoding of strings like : + * =?UTF-8?B?QnJhbmtvIMSMaWJlag==?= + * + * These strings complies to the following syntax : + * =?charset?mode?data?= rest + */ +char *mbox_cte_decode_rfc2047(apr_pool_t *p, char *src) +{ + apr_xlate_t *xlate; + + char *charset, *mode, *data, *rest; + int i; + + /* Look for charset */ + charset = strstr(src, "=?"); + if (!charset) { + return src; + } + *charset = 0; + charset += strlen("=?"); + + /* Encoding mode (first '?' after charset) */ + mode = strstr(charset, "?"); + if (!mode) { + return src; + } + *mode = 0; + mode++; + + /* Fetch data */ + data = strstr(mode, "?"); + if (!data) { + return src; + } + *data = 0; + data++; + + /* Look for the end bound */ + rest = strstr(data, "?="); + if (!rest) { + return src; + } + *rest = 0; + + /* Quoted-Printable decoding : mode 'q' */ + if ((*mode == 'q') || (*mode == 'Q')) { + apr_size_t data_len; + int i; + + /* In QP header encoding, spaces are encoded either in =20 (as + in all QP encoding) or in underscores '_' (for header + encoding). The first case will be handle by the QP + decoding, so we must handle the other one */ + for (i = 0; i < strlen(data); i++) { + if (data[i] == '_') { + data[i] = ' '; + } + } + + data_len = mbox_cte_decode_qp(data); + data[data_len] = 0; + } + else if ((*mode == 'b') || (*mode == 'B')) { + apr_size_t data_len; + + data_len = mbox_cte_decode_b64(data); + data[data_len] = 0; + } + + /* Convert charset to uppercase */ + for (i=0; i headers_bound)) { + ct = "text/plain"; + } + + mail = apr_pcalloc(p, sizeof(mbox_mime_message_t)); + + /* If no Content-Type is given, we have to look for it. */ + if (!ct) { + tmp += sizeof("Content-Type: ") - 1; + k = strchr(tmp, ';'); + + /* Isolate the Content-Type string (between 'Content-Type: ' + and ';' or end of line */ + if (k && k < headers_bound) { + *k = 0; + } + else { + k = tmp; + while (*k) { + if (isspace(*k)) { + *k = 0; + break; + } + *k++; + } + } + + /* Copy the Content-Type and reset *k */ + mail->content_type = apr_pstrdup(p, tmp); + *k = ';'; + + /* If available, get MIME part name */ + tmp = ap_strstr(body, "name="); + if (tmp && tmp < headers_bound) { + tmp += sizeof("name=") - 1; + k = tmp; + + while (*k) { + if (isspace(*k) || *k == ';') { + *k = 0; + break; + } + *k++; + } + + /* Check for double quotes */ + if ((*tmp == '"') && (tmp[strlen(tmp)-1] == '"')) { + mail->content_name = apr_pstrndup(p, tmp+1, strlen(tmp) - 2); + } + else { + mail->content_name = apr_pstrdup(p, tmp); + } + + *k = ';'; + } + } + else { + mail->content_type = ct; + } + + /* Now we have a Content-Type. Look for other useful header information */ + + /* Check Content-Disposition if the match is within the headers */ + tmp = ap_strstr(body, "Content-Disposition: "); + if (tmp && tmp < headers_bound) { + tmp += sizeof("Content-Disposition: ") - 1; + k = tmp; + + while (*k) { + if (isspace(*k) || *k == ';') { + *k = 0; + break; + } + *k++; + } + + /* Copy the Content-Disposition and reset *k */ + mail->content_disposition = apr_pstrdup(p, tmp); + *k = '\n'; + } + else { + mail->content_disposition = apr_pstrdup(p, "inline"); + } + + /* Check Content-Transfer-Encoding, if needed */ + if (cte == CTE_NONE) + { + tmp = ap_strstr(body, "Content-Transfer-Encoding: "); + if (tmp && tmp < headers_bound) { + tmp += sizeof("Content-Transfer-Encoding: ") - 1; + k = tmp; + + while (*k) { + if (isspace(*k) || *k == ';') { + *k = 0; + break; + } + *k++; + } + + /* Copy the Content-Disposition and reset *k */ + mail->cte = mbox_parse_cte_header(tmp); + *k = '\n'; + } + } + else { + mail->cte = cte; + } + + /* Now we have all the headers we need. Start processing the + body. If the Content-Type was given at call time, the body + starts where it's given. Otherwise it's after the headers + (first new empty line) */ + + if (ct) { + mail->body = body; + } + else { + mail->body = ap_strstr(body, "\n\n"); + if (mail->body != NULL) { + mail->body += 2; + } + } + + /* If the mail is a multipart message, search for the boundary, + and process its sub parts by recursive calls. */ + if (strncmp(mail->content_type, "multipart/", strlen("multipart/")) == 0) { + int end = 0, count = 0; + char *search, *bound; + + /* If the boundary was not given, we must look for it in the headers */ + if (!boundary) { + tmp = ap_strstr(body, "boundary=\""); + if (!tmp) { + return NULL; + } + + tmp += sizeof("boundary=\"") - 1; + k = tmp; + + while (*k) { + if (*k == '"') { + *k = 0; + break; + } + *k++; + } + + mail->boundary = apr_pstrdup(p, tmp); + *k = '"'; + } + + /* Otherwise, the boundary is as given to us */ + else { + mail->boundary = boundary; + } + + /* Now we have our boundary string. We must : look for it once + (begining of MIME part) and then look for the end boundary : + --boundary-- to mark the end of the MIME part */ + + /* The start boundary */ + bound = ap_strstr(mail->body, mail->boundary); + if (!bound) { + return NULL; + } + + /* The end boudary */ + end_bound = apr_psprintf(p, "--%s--", mail->boundary); + tmp = ap_strstr(mail->body, end_bound); + if (!tmp) { + return NULL; + } + *tmp = 0; + + /* Set the search begining to the line after the start boundary. */ + search = bound + strlen(mail->boundary) + 1; + + /* While the MIME part is not finished, go through all sub parts */ + while (!end) { + char *inbound; + + inbound = ap_strstr(search+strlen(mail->boundary), mail->boundary); + if (inbound) { + char *t = inbound - 2; + *t = 0; + } + + /* Allocate a new pointer for the sub part, and parse it. */ + mail->sub = realloc(mail->sub, ++count * sizeof(struct mimemsg *)); + mail->sub[count-1] = mbox_mime_decode_multipart(p, search, NULL, CTE_NONE, NULL); + + /* If the boudary is found again, it means we have another + MIME part in the same multipart message. Set the new + search begining to the line after this new start + boundary */ + if (inbound) { + char *t = inbound - 2; + *t = '-'; + + search = inbound + strlen(mail->boundary) + 1; + + if (mail->sub[count-1] && mail->sub[count-1]->body) { + mail->sub[count-1]->body_len = inbound - mail->sub[count-1]->body - 2; + } + } + + /* Otherwise, the MIME part is finished. */ + else { + mail->sub_count = count; + end = 1; + } + } + + /* Finally reset the end-body pointer. */ + // *tmp = '-'; + } + + /* If the parsed body is not multipart or is a MIME part, the body + length is the length of the body string (no surprise here). If + it's a MIME part, its correct length will be set after the call + to mbox_mime_decode_multipart just a dozen lines above. */ + else { + if (mail->body != NULL) { + mail->body_len = strlen(mail->body); + } + else { + mail->body_len = 0; + } + } + + return mail; +} Propchange: httpd/mod_mbox/branches/surgery/src/libmbox/mbox_mime.c ------------------------------------------------------------------------------ svn:eol-style = native Modified: httpd/mod_mbox/branches/surgery/src/module/Makefile.am URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/surgery/src/module/Makefile.am?rev=366430&r1=366429&r2=366430&view=diff ============================================================================== --- httpd/mod_mbox/branches/surgery/src/module/Makefile.am (original) +++ httpd/mod_mbox/branches/surgery/src/module/Makefile.am Thu Jan 5 21:17:52 2006 @@ -5,9 +5,7 @@ mod_mbox_file.c \ mod_mbox_out.c \ mod_mbox_search.c \ - mod_mbox_index.c \ - mod_mbox_cte.c \ - mod_mbox_mime.c + mod_mbox_index.c mod_mbox_la_LIBADD = $(top_builddir)/src/libmbox/libmbox.la mod_mbox_la_CFLAGS = -Wall ${MODULE_CFLAGS} Modified: httpd/mod_mbox/branches/surgery/src/module/mod_mbox.h URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/surgery/src/module/mod_mbox.h?rev=366430&r1=366429&r2=366430&view=diff ============================================================================== --- httpd/mod_mbox/branches/surgery/src/module/mod_mbox.h (original) +++ httpd/mod_mbox/branches/surgery/src/module/mod_mbox.h Thu Jan 5 21:17:52 2006 @@ -30,10 +30,8 @@ #include "apr_dbm.h" #include "apr_hash.h" #include "apr_fnmatch.h" -#include "apr_xlate.h" #include -#include #include "libmbox.h" @@ -115,19 +113,7 @@ apr_status_t mbox_static_message(request_rec *r, apr_file_t *f); apr_status_t mbox_xml_message(request_rec *r, apr_file_t *f); -/* CTE decoding functions */ -const char *mbox_cte_to_char(mbox_cte_e cte); -apr_size_t mbox_cte_decode_qp(char* p); -apr_size_t mbox_cte_decode_b64(char *src); -apr_size_t mbox_cte_escape_html(apr_pool_t *p, const char *s, - apr_size_t len, char **body); -char *mbox_cte_decode_rfc2047(apr_pool_t *p, char *src); -char *mbox_cte_decode_header(apr_pool_t *p, char *src); - -/* MIME decoding functions */ -mbox_mime_message_t *mbox_mime_decode_multipart(apr_pool_t *p, char *body, - char *ct, mbox_cte_e cte, - char *boundary); +/* MIME structure displaying */ char *mbox_mime_decode_body(apr_pool_t *p, mbox_cte_e cte, char *body, apr_size_t len); char *mbox_mime_get_body(apr_pool_t *p, mbox_mime_message_t *m); void mbox_mime_display_static_structure(request_rec *r, mbox_mime_message_t *m, Modified: httpd/mod_mbox/branches/surgery/src/module/mod_mbox_mime.c URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/surgery/src/module/mod_mbox_mime.c?rev=366430&r1=366429&r2=366430&view=diff ============================================================================== --- httpd/mod_mbox/branches/surgery/src/module/mod_mbox_mime.c (original) +++ httpd/mod_mbox/branches/surgery/src/module/mod_mbox_mime.c Thu Jan 5 21:17:52 2006 @@ -19,266 +19,6 @@ #include "mod_mbox.h" -/* Decode a multipart (or not) email. In order to support multiple - * levels of MIME parts, this function is recursive. - */ -mbox_mime_message_t *mbox_mime_decode_multipart(apr_pool_t *p, char *body, - char *ct, mbox_cte_e cte, - char *boundary) -{ - mbox_mime_message_t *mail; - char *tmp = NULL, *k = NULL, *end_bound = NULL; - char *headers_bound = NULL; - - if (!body) { - return NULL; - } - - /* Locate the end of part headers */ - headers_bound = ap_strstr(body, "\n\n"); - if (!headers_bound) { - return NULL; - } - - /* If no Content-Type is provided, it means that we are parsing a - sub-part of the multipart message. The Content-Type header - should then be the first line of the part. If not, use - text/plain as default for the sub-part. */ - tmp = ap_strstr(body, "Content-Type: "); - if (!ct && (!tmp || tmp > headers_bound)) { - ct = "text/plain"; - } - - mail = apr_pcalloc(p, sizeof(mbox_mime_message_t)); - - /* If no Content-Type is given, we have to look for it. */ - if (!ct) { - tmp += sizeof("Content-Type: ") - 1; - k = strchr(tmp, ';'); - - /* Isolate the Content-Type string (between 'Content-Type: ' - and ';' or end of line */ - if (k && k < headers_bound) { - *k = 0; - } - else { - k = tmp; - while (*k) { - if (isspace(*k)) { - *k = 0; - break; - } - *k++; - } - } - - /* Copy the Content-Type and reset *k */ - mail->content_type = apr_pstrdup(p, tmp); - *k = ';'; - - /* If available, get MIME part name */ - tmp = ap_strstr(body, "name="); - if (tmp && tmp < headers_bound) { - tmp += sizeof("name=") - 1; - k = tmp; - - while (*k) { - if (isspace(*k) || *k == ';') { - *k = 0; - break; - } - *k++; - } - - /* Check for double quotes */ - if ((*tmp == '"') && (tmp[strlen(tmp)-1] == '"')) { - mail->content_name = apr_pstrndup(p, tmp+1, strlen(tmp) - 2); - } - else { - mail->content_name = apr_pstrdup(p, tmp); - } - - *k = ';'; - } - } - else { - mail->content_type = ct; - } - - /* Now we have a Content-Type. Look for other useful header information */ - - /* Check Content-Disposition if the match is within the headers */ - tmp = ap_strstr(body, "Content-Disposition: "); - if (tmp && tmp < headers_bound) { - tmp += sizeof("Content-Disposition: ") - 1; - k = tmp; - - while (*k) { - if (isspace(*k) || *k == ';') { - *k = 0; - break; - } - *k++; - } - - /* Copy the Content-Disposition and reset *k */ - mail->content_disposition = apr_pstrdup(p, tmp); - *k = '\n'; - } - else { - mail->content_disposition = apr_pstrdup(p, "inline"); - } - - /* Check Content-Transfer-Encoding, if needed */ - if (cte == CTE_NONE) - { - tmp = ap_strstr(body, "Content-Transfer-Encoding: "); - if (tmp && tmp < headers_bound) { - tmp += sizeof("Content-Transfer-Encoding: ") - 1; - k = tmp; - - while (*k) { - if (isspace(*k) || *k == ';') { - *k = 0; - break; - } - *k++; - } - - /* Copy the Content-Disposition and reset *k */ - mail->cte = mbox_parse_cte_header(tmp); - *k = '\n'; - } - } - else { - mail->cte = cte; - } - - /* Now we have all the headers we need. Start processing the - body. If the Content-Type was given at call time, the body - starts where it's given. Otherwise it's after the headers - (first new empty line) */ - - if (ct) { - mail->body = body; - } - else { - mail->body = ap_strstr(body, "\n\n"); - if (mail->body != NULL) { - mail->body += 2; - } - } - - /* If the mail is a multipart message, search for the boundary, - and process its sub parts by recursive calls. */ - if (strncmp(mail->content_type, "multipart/", strlen("multipart/")) == 0) { - int end = 0, count = 0; - char *search, *bound; - - /* If the boundary was not given, we must look for it in the headers */ - if (!boundary) { - tmp = ap_strstr(body, "boundary=\""); - if (!tmp) { - return NULL; - } - - tmp += sizeof("boundary=\"") - 1; - k = tmp; - - while (*k) { - if (*k == '"') { - *k = 0; - break; - } - *k++; - } - - mail->boundary = apr_pstrdup(p, tmp); - *k = '"'; - } - - /* Otherwise, the boundary is as given to us */ - else { - mail->boundary = boundary; - } - - /* Now we have our boundary string. We must : look for it once - (begining of MIME part) and then look for the end boundary : - --boundary-- to mark the end of the MIME part */ - - /* The start boundary */ - bound = ap_strstr(mail->body, mail->boundary); - if (!bound) { - return NULL; - } - - /* The end boudary */ - end_bound = apr_psprintf(p, "--%s--", mail->boundary); - tmp = ap_strstr(mail->body, end_bound); - if (!tmp) { - return NULL; - } - *tmp = 0; - - /* Set the search begining to the line after the start boundary. */ - search = bound + strlen(mail->boundary) + 1; - - /* While the MIME part is not finished, go through all sub parts */ - while (!end) { - char *inbound; - - inbound = ap_strstr(search+strlen(mail->boundary), mail->boundary); - if (inbound) { - char *t = inbound - 2; - *t = 0; - } - - /* Allocate a new pointer for the sub part, and parse it. */ - mail->sub = realloc(mail->sub, ++count * sizeof(struct mimemsg *)); - mail->sub[count-1] = mbox_mime_decode_multipart(p, search, NULL, CTE_NONE, NULL); - - /* If the boudary is found again, it means we have another - MIME part in the same multipart message. Set the new - search begining to the line after this new start - boundary */ - if (inbound) { - char *t = inbound - 2; - *t = '-'; - - search = inbound + strlen(mail->boundary) + 1; - - if (mail->sub[count-1] && mail->sub[count-1]->body) { - mail->sub[count-1]->body_len = inbound - mail->sub[count-1]->body - 2; - } - } - - /* Otherwise, the MIME part is finished. */ - else { - mail->sub_count = count; - end = 1; - } - } - - /* Finally reset the end-body pointer. */ - // *tmp = '-'; - } - - /* If the parsed body is not multipart or is a MIME part, the body - length is the length of the body string (no surprise here). If - it's a MIME part, its correct length will be set after the call - to mbox_mime_decode_multipart just a dozen lines above. */ - else { - if (mail->body != NULL) { - mail->body_len = strlen(mail->body); - } - else { - mail->body_len = 0; - } - } - - return mail; -} - /* Decode a MIME part body, according to its CTE. */ char *mbox_mime_decode_body(apr_pool_t *p, mbox_cte_e cte, char *body, apr_size_t len) {