diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /comm/mailnews/mime/src/mimeebod.cpp | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comm/mailnews/mime/src/mimeebod.cpp')
-rw-r--r-- | comm/mailnews/mime/src/mimeebod.cpp | 441 |
1 files changed, 441 insertions, 0 deletions
diff --git a/comm/mailnews/mime/src/mimeebod.cpp b/comm/mailnews/mime/src/mimeebod.cpp new file mode 100644 index 0000000000..755574b1b0 --- /dev/null +++ b/comm/mailnews/mime/src/mimeebod.cpp @@ -0,0 +1,441 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "nsCOMPtr.h" +#include "mimeebod.h" +#include "prmem.h" +#include "plstr.h" +#include "prlog.h" +#include "prio.h" +#include "msgCore.h" +#include "nsMimeStringResources.h" +#include "mimemoz2.h" +#include "nsComponentManagerUtils.h" +#include "nsMsgUtils.h" +#include "nsINetUtil.h" +#include <ctype.h> + +#define MIME_SUPERCLASS mimeObjectClass +MimeDefClass(MimeExternalBody, MimeExternalBodyClass, mimeExternalBodyClass, + &MIME_SUPERCLASS); + +#ifdef XP_MACOSX +extern MimeObjectClass mimeMultipartAppleDoubleClass; +#endif + +static int MimeExternalBody_initialize(MimeObject*); +static void MimeExternalBody_finalize(MimeObject*); +static int MimeExternalBody_parse_line(const char*, int32_t, MimeObject*); +static int MimeExternalBody_parse_eof(MimeObject*, bool); +static bool MimeExternalBody_displayable_inline_p(MimeObjectClass* clazz, + MimeHeaders* hdrs); + +#if 0 +# if defined(DEBUG) && defined(XP_UNIX) +static int MimeExternalBody_debug_print (MimeObject *, PRFileDesc *, int32_t); +# endif +#endif /* 0 */ + +static int MimeExternalBodyClassInitialize(MimeExternalBodyClass* clazz) { + MimeObjectClass* oclass = (MimeObjectClass*)clazz; + + NS_ASSERTION(!oclass->class_initialized, + "1.1 <rhp@netscape.com> 19 Mar 1999 12:00"); + oclass->initialize = MimeExternalBody_initialize; + oclass->finalize = MimeExternalBody_finalize; + oclass->parse_line = MimeExternalBody_parse_line; + oclass->parse_eof = MimeExternalBody_parse_eof; + oclass->displayable_inline_p = MimeExternalBody_displayable_inline_p; + +#if 0 +# if defined(DEBUG) && defined(XP_UNIX) + oclass->debug_print = MimeExternalBody_debug_print; +# endif +#endif /* 0 */ + + return 0; +} + +static int MimeExternalBody_initialize(MimeObject* object) { + return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(object); +} + +static void MimeExternalBody_finalize(MimeObject* object) { + MimeExternalBody* bod = (MimeExternalBody*)object; + if (bod->hdrs) { + MimeHeaders_free(bod->hdrs); + bod->hdrs = 0; + } + PR_FREEIF(bod->body); + + ((MimeObjectClass*)&MIME_SUPERCLASS)->finalize(object); +} + +static int MimeExternalBody_parse_line(const char* line, int32_t length, + MimeObject* obj) { + MimeExternalBody* bod = (MimeExternalBody*)obj; + int status = 0; + + NS_ASSERTION(line && *line, "1.1 <rhp@netscape.com> 19 Mar 1999 12:00"); + if (!line || !*line) return -1; + + if (!obj->output_p) return 0; + + /* If we're supposed to write this object, but aren't supposed to convert + it to HTML, simply pass it through unaltered. */ + if (obj->options && !obj->options->write_html_p && obj->options->output_fn) + return MimeObject_write(obj, line, length, true); + + /* If we already have a `body' then we're done parsing headers, and all + subsequent lines get tacked onto the body. */ + if (bod->body) { + int L = strlen(bod->body); + char* new_str = (char*)PR_Realloc(bod->body, L + length + 1); + if (!new_str) return MIME_OUT_OF_MEMORY; + bod->body = new_str; + memcpy(bod->body + L, line, length); + bod->body[L + length] = 0; + return 0; + } + + /* Otherwise we don't yet have a body, which means we're not done parsing + our headers. + */ + if (!bod->hdrs) { + bod->hdrs = MimeHeaders_new(); + if (!bod->hdrs) return MIME_OUT_OF_MEMORY; + } + + status = MimeHeaders_parse_line(line, length, bod->hdrs); + if (status < 0) return status; + + /* If this line is blank, we're now done parsing headers, and should + create a dummy body to show that. Gag. + */ + if (*line == '\r' || *line == '\n') { + bod->body = strdup(""); + if (!bod->body) return MIME_OUT_OF_MEMORY; + } + + return 0; +} + +char* MimeExternalBody_make_url(const char* ct, const char* at, + const char* lexp, const char* size, + const char* perm, const char* dir, + const char* mode, const char* name, + const char* url, const char* site, + const char* svr, const char* subj, + const char* body) { + char* s; + uint32_t slen; + if (!at) { + return 0; + } else if (!PL_strcasecmp(at, "ftp") || !PL_strcasecmp(at, "anon-ftp")) { + if (!site || !name) return 0; + + slen = strlen(name) + strlen(site) + (dir ? strlen(dir) : 0) + 20; + s = (char*)PR_MALLOC(slen); + + if (!s) return 0; + PL_strncpyz(s, "ftp://", slen); + PL_strcatn(s, slen, site); + PL_strcatn(s, slen, "/"); + if (dir) PL_strcatn(s, slen, (dir[0] == '/' ? dir + 1 : dir)); + if (s[strlen(s) - 1] != '/') PL_strcatn(s, slen, "/"); + PL_strcatn(s, slen, name); + return s; +#ifdef XP_UNIX + } else if (!PL_strcasecmp(at, "local-file") || !PL_strcasecmp(at, "afs")) { + if (!name) return 0; + + if (!PL_strcasecmp(at, "afs")) /* only if there is a /afs/ directory */ + { + nsCOMPtr<nsIFile> fs = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID); + bool exists = false; + if (fs) { + fs->InitWithNativePath("/afs/."_ns); + fs->Exists(&exists); + } + if (!exists) return 0; + } + + slen = (strlen(name) * 3 + 20); + s = (char*)PR_MALLOC(slen); + if (!s) return 0; + PL_strncpyz(s, "file:", slen); + + nsCString s2; + MsgEscapeString(nsDependentCString(name), nsINetUtil::ESCAPE_URL_PATH, s2); + PL_strcatn(s, slen, s2.get()); + return s; +#endif + } else if (!PL_strcasecmp(at, "mail-server")) { + if (!svr) return 0; + + slen = (strlen(svr) * 4 + (subj ? strlen(subj) * 4 : 0) + + (body ? strlen(body) * 4 : 0) + + 25); // dpv xxx: why 4x? %xx escaping should be 3x + s = (char*)PR_MALLOC(slen); + if (!s) return 0; + PL_strncpyz(s, "mailto:", slen); + + nsCString s2; + MsgEscapeString(nsDependentCString(svr), nsINetUtil::ESCAPE_XALPHAS, s2); + PL_strcatn(s, slen, s2.get()); + + if (subj) { + MsgEscapeString(nsDependentCString(subj), nsINetUtil::ESCAPE_XALPHAS, s2); + PL_strcatn(s, slen, "?subject="); + PL_strcatn(s, slen, s2.get()); + } + if (body) { + MsgEscapeString(nsDependentCString(body), nsINetUtil::ESCAPE_XALPHAS, s2); + PL_strcatn(s, slen, (subj ? "&body=" : "?body=")); + PL_strcatn(s, slen, s2.get()); + } + return s; + } else if (!PL_strcasecmp(at, "url")) /* RFC 2017 */ + { + if (url) + return strdup(url); /* it's already quoted and everything */ + else + return 0; + } else + return 0; +} + +static int MimeExternalBody_parse_eof(MimeObject* obj, bool abort_p) { + int status = 0; + MimeExternalBody* bod = (MimeExternalBody*)obj; + + if (obj->closed_p) return 0; + + /* Run parent method first, to flush out any buffered data. */ + status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p); + if (status < 0) return status; + +#ifdef XP_MACOSX + if (obj->parent && + mime_typep(obj->parent, (MimeObjectClass*)&mimeMultipartAppleDoubleClass)) + goto done; +#endif /* XP_MACOSX */ + + if (!abort_p && obj->output_p && obj->options && obj->options->write_html_p) { + bool all_headers_p = obj->options->headers == MimeHeadersAll; + MimeDisplayOptions* newopt = obj->options; /* copy it */ + + char* ct = MimeHeaders_get(obj->headers, HEADER_CONTENT_TYPE, false, false); + char *at, *lexp, *size, *perm; + char *url, *dir, *mode, *name, *site, *svr, *subj; + char *h = 0, *lname = 0, *lurl = 0, *body = 0; + MimeHeaders* hdrs = 0; + + if (!ct) return MIME_OUT_OF_MEMORY; + + at = MimeHeaders_get_parameter(ct, "access-type", NULL, NULL); + lexp = MimeHeaders_get_parameter(ct, "expiration", NULL, NULL); + size = MimeHeaders_get_parameter(ct, "size", NULL, NULL); + perm = MimeHeaders_get_parameter(ct, "permission", NULL, NULL); + dir = MimeHeaders_get_parameter(ct, "directory", NULL, NULL); + mode = MimeHeaders_get_parameter(ct, "mode", NULL, NULL); + name = MimeHeaders_get_parameter(ct, "name", NULL, NULL); + site = MimeHeaders_get_parameter(ct, "site", NULL, NULL); + svr = MimeHeaders_get_parameter(ct, "server", NULL, NULL); + subj = MimeHeaders_get_parameter(ct, "subject", NULL, NULL); + url = MimeHeaders_get_parameter(ct, "url", NULL, NULL); + PR_FREEIF(ct); + + /* the *internal* content-type */ + ct = MimeHeaders_get(bod->hdrs, HEADER_CONTENT_TYPE, true, false); + + uint32_t hlen = ((at ? strlen(at) : 0) + (lexp ? strlen(lexp) : 0) + + (size ? strlen(size) : 0) + (perm ? strlen(perm) : 0) + + (dir ? strlen(dir) : 0) + (mode ? strlen(mode) : 0) + + (name ? strlen(name) : 0) + (site ? strlen(site) : 0) + + (svr ? strlen(svr) : 0) + (subj ? strlen(subj) : 0) + + (ct ? strlen(ct) : 0) + (url ? strlen(url) : 0) + 100); + + h = (char*)PR_MALLOC(hlen); + if (!h) { + status = MIME_OUT_OF_MEMORY; + goto FAIL; + } + + /* If there's a URL parameter, remove all whitespace from it. + (The URL parameter to one of these headers is stored with + lines broken every 40 characters or less; it's assumed that + all significant whitespace was URL-hex-encoded, and all the + rest of it was inserted just to keep the lines short.) + */ + if (url) { + char *in, *out; + for (in = url, out = url; *in; in++) + if (!IS_SPACE(*in)) *out++ = *in; + *out = 0; + } + + hdrs = MimeHeaders_new(); + if (!hdrs) { + status = MIME_OUT_OF_MEMORY; + goto FAIL; + } + +#define FROB(STR, VAR) \ + if (VAR) { \ + PL_strncpyz(h, STR ": ", hlen); \ + PL_strcatn(h, hlen, VAR); \ + PL_strcatn(h, hlen, MSG_LINEBREAK); \ + status = MimeHeaders_parse_line(h, strlen(h), hdrs); \ + if (status < 0) goto FAIL; \ + } + FROB("Access-Type", at); + FROB("URL", url); + FROB("Site", site); + FROB("Server", svr); + FROB("Directory", dir); + FROB("Name", name); + FROB("Type", ct); + FROB("Size", size); + FROB("Mode", mode); + FROB("Permission", perm); + FROB("Expiration", lexp); + FROB("Subject", subj); +#undef FROB + PL_strncpyz(h, MSG_LINEBREAK, hlen); + status = MimeHeaders_parse_line(h, strlen(h), hdrs); + if (status < 0) goto FAIL; + + lurl = MimeExternalBody_make_url(ct, at, lexp, size, perm, dir, mode, name, + url, site, svr, subj, bod->body); + if (lurl) { + lname = MimeGetStringByID(MIME_MSG_LINK_TO_DOCUMENT); + } else { + lname = MimeGetStringByID(MIME_MSG_DOCUMENT_INFO); + all_headers_p = true; + } + + all_headers_p = true; /* #### just do this all the time? */ + + if (bod->body && all_headers_p) { + char* s = bod->body; + while (IS_SPACE(*s)) s++; + if (*s) { + const char* pre = "<P><PRE>"; + const char* suf = "</PRE>"; + int32_t i; + // The end condition requires i to be negative, so it's ok to + // allow the starting value to be negative. + for (i = strlen(s) - 1; i >= 0 && IS_SPACE(s[i]); i--) s[i] = 0; + nsCString s2; + nsAppendEscapedHTML(nsDependentCString(s), s2); + body = (char*)PR_MALLOC(strlen(pre) + s2.Length() + strlen(suf) + 1); + if (!body) { + goto FAIL; + } + PL_strcpy(body, pre); + PL_strcat(body, s2.get()); + PL_strcat(body, suf); + } + } + + newopt->fancy_headers_p = true; + newopt->headers = (all_headers_p ? MimeHeadersAll : MimeHeadersSome); + + FAIL: + if (hdrs) MimeHeaders_free(hdrs); + PR_FREEIF(h); + PR_FREEIF(lname); + PR_FREEIF(lurl); + PR_FREEIF(body); + PR_FREEIF(ct); + PR_FREEIF(at); + PR_FREEIF(lexp); + PR_FREEIF(size); + PR_FREEIF(perm); + PR_FREEIF(dir); + PR_FREEIF(mode); + PR_FREEIF(name); + PR_FREEIF(url); + PR_FREEIF(site); + PR_FREEIF(svr); + PR_FREEIF(subj); + } + +#ifdef XP_MACOSX +done: +#endif + + return status; +} + +#if 0 +# if defined(DEBUG) && defined(XP_UNIX) +static int +MimeExternalBody_debug_print (MimeObject *obj, PRFileDesc *stream, int32_t depth) +{ + MimeExternalBody *bod = (MimeExternalBody *) obj; + int i; + char *ct, *ct2; + char *addr = mime_part_address(obj); + + if (obj->headers) + ct = MimeHeaders_get (obj->headers, HEADER_CONTENT_TYPE, false, false); + if (bod->hdrs) + ct2 = MimeHeaders_get (bod->hdrs, HEADER_CONTENT_TYPE, false, false); + + for (i=0; i < depth; i++) + PR_Write(stream, " ", 2); +/*** + fprintf(stream, + "<%s %s\n" + "\tcontent-type: %s\n" + "\tcontent-type: %s\n" + "\tBody:%s\n\t0x%08X>\n\n", + obj->clazz->class_name, + addr ? addr : "???", + ct ? ct : "<none>", + ct2 ? ct2 : "<none>", + bod->body ? bod->body : "<none>", + (uint32_t) obj); +***/ + PR_FREEIF(addr); + PR_FREEIF(ct); + PR_FREEIF(ct2); + return 0; +} +# endif +#endif /* 0 */ + +static bool MimeExternalBody_displayable_inline_p(MimeObjectClass* clazz, + MimeHeaders* hdrs) { + char* ct = MimeHeaders_get(hdrs, HEADER_CONTENT_TYPE, false, false); + char* at = MimeHeaders_get_parameter(ct, "access-type", NULL, NULL); + bool inline_p = false; + + if (!at) + ; + else if (!PL_strcasecmp(at, "ftp") || !PL_strcasecmp(at, "anon-ftp") || + !PL_strcasecmp(at, "local-file") || + !PL_strcasecmp(at, "mail-server") || !PL_strcasecmp(at, "url")) + inline_p = true; +#ifdef XP_UNIX + else if (!PL_strcasecmp(at, "afs")) /* only if there is a /afs/ directory */ + { + nsCOMPtr<nsIFile> fs = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID); + bool exists = false; + if (fs) { + fs->InitWithNativePath("/afs/."_ns); + fs->Exists(&exists); + } + if (!exists) return 0; + + inline_p = true; + } +#endif /* XP_UNIX */ + + PR_FREEIF(ct); + PR_FREEIF(at); + return inline_p; +} |