summaryrefslogtreecommitdiffstats
path: root/libmail/attachments.C
diff options
context:
space:
mode:
Diffstat (limited to 'libmail/attachments.C')
-rw-r--r--libmail/attachments.C631
1 files changed, 0 insertions, 631 deletions
diff --git a/libmail/attachments.C b/libmail/attachments.C
deleted file mode 100644
index f9c9a5a..0000000
--- a/libmail/attachments.C
+++ /dev/null
@@ -1,631 +0,0 @@
-/*
-** Copyright 2004-2008, Double Precision Inc.
-**
-** See COPYING for distribution information.
-*/
-#include "libmail_config.h"
-#include "misc.H"
-#include "headers.H"
-#include "rfc822/encode.h"
-#include "rfc2045/rfc2045charset.h"
-#include <sys/time.h>
-#include "attachments.H"
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sstream>
-#include <iomanip>
-#include <cstring>
-
-using namespace std;
-
-void mail::Attachment::common_init()
-{
- content_fp=NULL;
- message_rfc822=NULL;
- generating=false;
-}
-
-void mail::Attachment::common_fd_init(int fd)
-{
- int n;
- FILE *fp;
-
- if (lseek(fd, 0L, SEEK_END) >= 0 &&
- lseek(fd, 0L, SEEK_SET) >= 0)
- {
- int fd2=dup(fd);
-
- if (fd2 < 0)
- throw strerror(errno);
-
- if ((content_fp=fdopen(fd2, "r")) == NULL)
- {
- close(fd2);
- throw strerror(errno);
- }
- return;
- }
-
- fp=tmpfile();
- if (!fp)
- {
- throw strerror(errno);
- }
-
- while ((n=read(fd, encode_info.output_buffer,
- // Convenient buffer
- sizeof(encode_info.output_buffer))) > 0)
- {
- if (fwrite(encode_info.output_buffer, n, 1, fp) != 1)
- {
- fclose(fp);
- throw strerror(errno);
- }
- }
-
- if (fflush(fp) < 0 || ferror(fp))
- {
- fclose(fp);
- throw strerror(errno);
- }
- content_fp=fp;
-}
-
-void mail::Attachment::check_multipart_encoding()
-{
- string::iterator cte_start, cte_end;
-
- multipart_type=find_header("CONTENT-TYPE:", cte_start, cte_end);
- mail::upper(multipart_type);
-
- const char *p=multipart_type.c_str();
-
- if (strncmp(p, "MULTIPART/", 10) == 0 ||
- strcmp(p, "MESSAGE/RFC822") == 0)
- transfer_encoding="8bit";
-}
-
-mail::Attachment::Attachment(string h, int fd)
- : headers(h)
-{
- common_init();
- common_fd_init(fd);
-
- try {
- check_multipart_encoding();
-
- if (transfer_encoding.size() == 0)
- transfer_encoding=
- libmail_encode_autodetect_fp(content_fp, 1,
- NULL);
- } catch (...)
- {
- fclose(content_fp);
- content_fp=NULL;
- }
-
- add_content_encoding();
-}
-
-mail::Attachment::~Attachment()
-{
- if (content_fp)
- fclose(content_fp);
- if (message_rfc822 == NULL &&
- parts.size() == 0)
- {
- if (generating)
- libmail_encode_end(&encode_info);
- }
-}
-
-mail::Attachment::Attachment(std::string h, int fd,
- std::string chs,
- std::string encoding)
-
- : headers(h)
-{
- common_init();
- common_fd_init(fd);
-
- try {
- transfer_encoding=encoding;
-
- if (transfer_encoding.size() == 0)
- check_multipart_encoding();
-
- if (transfer_encoding.size() == 0)
- transfer_encoding=
- libmail_encode_autodetect_fp(content_fp, 0,
- NULL);
- add_content_encoding();
-
- } catch (...) {
- fclose(content_fp);
- throw;
- }
-}
-
-mail::Attachment::Attachment(string h, string content)
- : headers(h), content_string(content)
-{
- common_init();
- check_multipart_encoding();
- if (transfer_encoding.size() == 0)
- transfer_encoding=
- libmail_encode_autodetect_buf(content.c_str(), 1);
-
- add_content_encoding();
-}
-
-mail::Attachment::Attachment(string h, string content,
- string chs,
- string encoding)
- : headers(h), content_string(content)
-{
- common_init();
- transfer_encoding=encoding;
-
- if (transfer_encoding.size() == 0)
- check_multipart_encoding();
-
- if (transfer_encoding.size() == 0)
- transfer_encoding=
- libmail_encode_autodetect_buf(content.c_str(), 1);
- add_content_encoding();
-}
-
-void mail::Attachment::add_content_encoding()
-{
- string::iterator cte_start, cte_end;
-
- multipart_type=find_header("CONTENT-TYPE:", cte_start, cte_end);
- mail::upper(multipart_type);
-
- string existing_transfer_encoding=
- find_header("CONTENT-TRANSFER-ENCODING:", cte_start,
- cte_end);
-
- const char *p=multipart_type.c_str();
-
- if (cte_start != cte_end ||
- // Already have the header. Must be already encoded.
-
- strncmp(p, "MULTIPART/", 10) == 0 ||
- strcmp(p, "MESSAGE/RFC822") == 0)
- {
- transfer_encoding="8bit";
- return;
- }
-
- headers += "Content-Transfer-Encoding: ";
- headers += transfer_encoding;
- headers += "\n";
-}
-
-mail::Attachment::Attachment(string h,
- const vector<Attachment *> &partsArg)
- : headers(h)
-{
- common_init();
- parts=partsArg;
- common_multipart_init();
-}
-
-mail::Attachment::Attachment(string h,
- const vector<Attachment *> &partsArg,
- string multipart_typeArg,
- const mail::mimestruct::parameterList
- &multipart_parametersArg)
- : headers(h)
-{
- common_init();
- parts=partsArg;
- multipart_type=multipart_typeArg;
- multipart_parameters=multipart_parametersArg;
- common_multipart_init();
-}
-
-string mail::Attachment::find_header(const char *header_name,
- string::iterator &hstart,
- string::iterator &hend)
-{
- return find_header(header_name, headers, hstart, hend);
-}
-
-std::string mail::Attachment::find_header(const char *header_name,
- std::string &headers,
- std::string::iterator &hstart,
- std::string::iterator &hend)
-{
- size_t l=strlen(header_name);
-
- string::iterator b=headers.begin(), e=headers.end();
- string::iterator s=b;
-
- while (b != e)
- {
- while (b != e)
- {
- if (*b == '\n')
- {
- ++b;
- break;
- }
- ++b;
- }
-
- string h=string(s, b);
-
- mail::upper(h);
-
- if (strncmp(h.c_str(), header_name, l) == 0)
- break;
- s=b;
- }
-
- while (b != e)
- {
- if (*b != ' ' && *b != '\t')
- break;
-
- while (b != e)
- {
- if (*b == '\n')
- {
- ++b;
- break;
- }
- ++b;
- }
- }
-
- hstart=s;
- hend=b;
-
- if (s != b)
- s += l;
-
- while (s != b && unicode_isspace((unsigned char)*s))
- ++s;
-
- while (s != b && unicode_isspace((unsigned char)b[-1]))
- --b;
-
- return string(s,b);
-}
-
-void mail::Attachment::common_multipart_init()
-{
- string::iterator s, b;
-
- string content_type=find_header("CONTENT-TYPE:", s, b);
-
- string header=string(s,b);
-
- if (s != b)
- headers.erase(s,b);
-
- mail::Header::mime mimeHeader= mail::Header::mime::fromString(header);
-
- if (multipart_type.size() == 0)
- multipart_type=mimeHeader.value;
- multipart_parameters=mimeHeader.parameters;
-
- if (parts.size() == 0) // Woot?
- {
- multipart_type="text/plain";
- transfer_encoding="8bit";
- return;
- }
-
- mail::upper(multipart_type);
-
- if (multipart_type == "MESSAGE/RFC822")
- {
- if (parts.size() > 1) // Woot?
- {
- multipart_type="MULTIPART/MIXED";
- return;
- }
- message_rfc822=parts[0];
- }
- else
- {
- if (strncmp(multipart_type.c_str(), "MESSAGE/", 8) == 0)
- multipart_type="MULTIPART/MIXED";
- }
-
-}
-
-void mail::Attachment::begin()
-{
- begin_recursive();
-
- string::iterator s, b;
-
- string content_type=find_header("MIME-VERSION:", s, b);
-
- if (s == b)
- headers="Mime-Version: 1.0\n" + headers;
-
- string boundary;
-
- do
- {
- ostringstream fmt;
-
- struct timeval tv;
-
- gettimeofday(&tv, NULL);
-
- fmt << "=_" << mail::hostname() << "-"
- << tv.tv_sec
- << "-"
- << tv.tv_usec
- << "-"
- << getpid();
-
-
- boundary=fmt.str();
- } while (!try_boundary(boundary, 0));
-}
-
-bool mail::Attachment::try_boundary(std::string templ, int level)
-{
- string boundary;
- ostringstream fmt;
-
- // =_(mumble) can never occur in base64 or quoted-printable
-
- if (transfer_encoding == "base64")
- return true;
- if (transfer_encoding == "quoted-printable")
- return true;
-
- fmt << templ << "-" << setw(4) << setfill('0') << level;
- boundary=fmt.str();
-
- if (content_string.size() > 0)
- {
- const char *p=content_string.c_str();
-
- while (*p)
- {
- if (strncmp(p, "--", 2) == 0 &&
- strncasecmp(p+2, boundary.c_str(),
- boundary.size()) == 0)
- return false;
-
- while (*p && *p != '\n')
- ++p;
- if (*p)
- ++p;
- }
- }
- if (content_fp)
- {
- if (fseek(content_fp, 0L, SEEK_SET) < 0)
- throw strerror(errno);
-
- while (fgets(encode_info.output_buffer,
- // Convenient buffer
-
- sizeof(encode_info.output_buffer), content_fp))
- {
- if (strncmp(encode_info.output_buffer, "--", 2) == 0 &&
- strncasecmp(encode_info.output_buffer+2,
- boundary.c_str(),
- boundary.size()) == 0)
- return false;
- }
- if (ferror(content_fp))
- throw strerror(errno);
- }
-
- if (message_rfc822)
- return message_rfc822->try_boundary(templ, level);
-
- std::vector<mail::Attachment *>::iterator b, e;
-
- for (b=parts.begin(), e=parts.end(); b != e; ++b)
- if (!(*b)->try_boundary(templ, level+1))
- return false;
-
- if (parts.size() > 0)
- {
- multipart_parameters.erase("boundary");
- multipart_parameters.set_simple("boundary", boundary);
- }
-
- return true;
-}
-
-void mail::Attachment::begin_recursive()
-{
- std::vector<mail::Attachment *>::iterator b, e;
-
- generating=false;
-
- for (b=parts.begin(), e=parts.end(); b != e; ++b)
- (*b)->begin_recursive();
-}
-
-string mail::Attachment::generate(bool &error)
-{
- if (message_rfc822)
- {
- if (!generating)
- {
- generating=true;
- mail::Header::mime content_type("Content-Type",
- multipart_type);
-
- content_type.parameters=multipart_parameters;
-
- return headers + content_type.toString() + "\n\n";
- }
- return message_rfc822->generate(error);
- }
-
- if (parts.size() > 0)
- {
- if (!generating)
- {
- generating=true;
- multipart_iterator=parts.begin();
-
- mail::Header::mime content_type("Content-Type",
- multipart_type);
-
- content_type.parameters=multipart_parameters;
-
- return headers +
- content_type.toString() + "\n\n"
- RFC2045MIMEMSG "\n--"
- + multipart_parameters.get("boundary")
- + "\n";
- }
-
- if (multipart_iterator == parts.end())
- return "";
-
- string s=(*multipart_iterator)->generate(error);
-
- if (error)
- return s;
-
- if (s.size() > 0)
- return s;
-
- ++multipart_iterator;
-
- return "\n--" + multipart_parameters.get("boundary")
- + (multipart_iterator == parts.end()
- ? "--\n":"\n");
- }
-
- if (!generating)
- {
- generating=true;
- if (content_fp)
- {
- if (fseek(content_fp, 0L, SEEK_SET) < 0)
- {
- error=true;
- return "";
- }
- }
-
- libmail_encode_start(&encode_info,
- transfer_encoding.c_str(),
- &mail::Attachment::callback_func,
- this);
-
- encoded=headers + "\n";
- if (content_fp)
- return encoded;
- if (libmail_encode(&encode_info,
- content_string.c_str(),
- content_string.size()) < 0)
- {
- error=true;
- return "";
- }
- libmail_encode_end(&encode_info);
- return encoded;
- }
-
- encoded="";
- if (content_fp)
- {
- if (feof(content_fp))
- {
- libmail_encode_end(&encode_info);
- return encoded;
- }
-
- do
- {
- char buf[BUFSIZ];
- int n=fread(buf, 1, sizeof(buf), content_fp);
-
- if (n < 0)
- {
- error=true;
- return "";
- }
-
- if (n == 0)
- {
- libmail_encode_end(&encode_info);
- return encoded;
- }
-
- if (libmail_encode(&encode_info, buf, n) < 0)
- {
- error=true;
- return "";
- }
- } while (encoded.size() == 0);
- // libmail_encode() may not call the callback function,
- // so encoded will be empty, which will be interpreted by
- // the caller as EOF, so we simply try again.
- }
- return encoded;
-}
-
-int mail::Attachment::callback_func(const char *c, size_t n, void *va)
-{
- ((mail::Attachment *)va)->encoded += string(c, c+n);
- return 0;
-}
-
-mail::Attachment::Attachment(const mail::Attachment &a)
-{
- common_init();
-
- (*this)=a;
-}
-
-#define CPY(n) n=o.n
-
-mail::Attachment &mail::Attachment::operator=(const Attachment &o)
-{
- CPY(headers);
- CPY(transfer_encoding);
- if (content_fp)
- fclose(content_fp);
-
- content_fp=NULL;
-
- if (o.content_fp)
- {
- int fd2=dup(fileno(o.content_fp));
-
- if (fd2 < 0)
- throw strerror(errno);
-
- if ((content_fp=fdopen(fd2, "r")) == NULL)
- {
- close(fd2);
- throw strerror(errno);
- }
- }
- CPY(content_string);
- CPY(parts);
-
- message_rfc822=NULL;
- if (o.message_rfc822)
- message_rfc822=parts[0];
-
- CPY(multipart_type);
- CPY(multipart_parameters);
- CPY(generating);
- CPY(multipart_iterator);
- CPY(encode_info);
- CPY(encoded);
- return *this;
-}