aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--SConstruct3
-rw-r--r--examples/example1.cpp2
-rw-r--r--examples/example2.cpp2
-rw-r--r--examples/example3.cpp4
-rw-r--r--src/body.cpp35
-rw-r--r--src/contentHandler.cpp333
-rw-r--r--src/defaultAttachment.cpp22
-rw-r--r--src/emptyContentHandler.cpp75
-rw-r--r--src/fileAttachment.cpp6
-rw-r--r--src/htmlTextPart.cpp50
-rw-r--r--src/plainTextPart.cpp24
-rw-r--r--src/streamContentHandler.cpp206
-rw-r--r--src/stringContentHandler.cpp192
-rw-r--r--tests/parser/bodyPartTest.cpp2
-rw-r--r--vmime/body.hpp10
-rw-r--r--vmime/contentHandler.hpp129
-rw-r--r--vmime/defaultAttachment.hpp4
-rw-r--r--vmime/emptyContentHandler.hpp56
-rw-r--r--vmime/htmlTextPart.hpp8
-rw-r--r--vmime/plainTextPart.hpp5
-rw-r--r--vmime/streamContentHandler.hpp76
-rw-r--r--vmime/stringContentHandler.hpp92
-rw-r--r--vmime/vmime.hpp4
24 files changed, 880 insertions, 467 deletions
diff --git a/ChangeLog b/ChangeLog
index c29d2bee..e68fa1f6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,13 @@
VERSION 0.6.3cvs
================
+2005-01-28 Vincent Richard <[email protected]>
+
+ * Splitted 'contentHandler' into three classes: 'emptyContentHandler',
+ 'stringContentHandler' and 'streamContentHandler'.
+
+ * Fixed bugs with signed/unsigned char in 'parserHelpers'.
+
2005-01-15 Vincent Richard <[email protected]>
* Fixed missing 'vmime/config.hpp' include when installing VMime
diff --git a/SConstruct b/SConstruct
index a1b7ee0a..c1ce20ef 100644
--- a/SConstruct
+++ b/SConstruct
@@ -94,6 +94,7 @@ libvmime_sources = [
'contentTypeField.cpp', 'contentTypeField.hpp',
'dateTime.cpp', 'dateTime.hpp',
'defaultAttachment.cpp', 'defaultAttachment.hpp',
+ 'emptyContentHandler.cpp', 'emptyContentHandler.hpp',
'encoder.cpp', 'encoder.hpp',
'encoder7bit.cpp', 'encoder7bit.hpp',
'encoder8bit.cpp', 'encoder8bit.hpp',
@@ -132,6 +133,8 @@ libvmime_sources = [
'relay.cpp', 'relay.hpp',
'standardFields.hpp',
'standardParams.hpp',
+ 'stringContentHandler.cpp', 'stringContentHandler.hpp',
+ 'streamContentHandler.cpp', 'streamContentHandler.hpp',
'text.cpp', 'text.hpp',
'textPartFactory.cpp', 'textPartFactory.hpp',
'textPart.hpp',
diff --git a/examples/example1.cpp b/examples/example1.cpp
index 52d29a1e..cbe7d032 100644
--- a/examples/example1.cpp
+++ b/examples/example1.cpp
@@ -60,7 +60,7 @@ int main()
mb.setSubject(vmime::text("My first message generated with vmime::messageBuilder"));
// Message body
- mb.getTextPart()->setText(vmime::contentHandler(
+ mb.getTextPart()->setText(vmime::stringContentHandler(
"I'm writing this short text to test message construction " \
"using the vmime::messageBuilder component."));
diff --git a/examples/example2.cpp b/examples/example2.cpp
index ae6a657e..2b309fc4 100644
--- a/examples/example2.cpp
+++ b/examples/example2.cpp
@@ -60,7 +60,7 @@ int main()
mb.setSubject(vmime::text("My first message generated with vmime::messageBuilder"));
// Message body
- mb.getTextPart()->setText(vmime::contentHandler(
+ mb.getTextPart()->setText(vmime::stringContentHandler(
"I'm writing this short text to test message construction " \
"with attachment, using the vmime::messageBuilder component."));
diff --git a/examples/example3.cpp b/examples/example3.cpp
index 29211865..9638356b 100644
--- a/examples/example3.cpp
+++ b/examples/example3.cpp
@@ -73,8 +73,8 @@ int main()
vmime::mediaType(vmime::mediaTypes::IMAGE, vmime::mediaTypes::IMAGE_JPEG));
// -- message text
- textPart.setText(vmime::contentHandler(vmime::string("This is the <b>HTML text</b>.<br/><img src=\"") + cid + vmime::string("\"/>")));
- textPart.setPlainText(vmime::contentHandler(vmime::string("This is the plain text (without HTML formatting).")));
+ textPart.setText(vmime::stringContentHandler(vmime::string("This is the <b>HTML text</b>.<br/><img src=\"") + cid + vmime::string("\"/>")));
+ textPart.setPlainText(vmime::stringContentHandler("This is the plain text (without HTML formatting)."));
// Construction
vmime::message* msg = mb.construct();
diff --git a/src/body.cpp b/src/body.cpp
index 85e1f4f7..74c3a8e8 100644
--- a/src/body.cpp
+++ b/src/body.cpp
@@ -28,25 +28,31 @@
#include "vmime/parserHelpers.hpp"
+#include "vmime/emptyContentHandler.hpp"
+#include "vmime/stringContentHandler.hpp"
+
namespace vmime
{
body::body()
- : m_part(NULL), m_header(NULL)
+ : m_contents(new emptyContentHandler()), m_part(NULL), m_header(NULL)
{
}
body::body(bodyPart* parentPart)
- : m_part(parentPart), m_header(parentPart != NULL ? parentPart->getHeader() : NULL)
+ : m_contents(new emptyContentHandler()),
+ m_part(parentPart), m_header(parentPart != NULL ? parentPart->getHeader() : NULL)
{
}
body::~body()
{
+ delete (m_contents);
+
removeAllParts();
}
@@ -190,7 +196,7 @@ void body::parse(const string& buffer, const string::size_type position,
pos = buffer.find(boundarySep, partStart);
}
- m_contents.setData("");
+ setContentsImpl(emptyContentHandler());
if (partStart < end)
m_epilogText = string(buffer.begin() + partStart, buffer.begin() + end);
@@ -199,7 +205,7 @@ void body::parse(const string& buffer, const string::size_type position,
else
{
// Extract the (encoded) contents
- m_contents.setData(buffer, position, end, getEncoding());
+ setContentsImpl(stringContentHandler(buffer, position, end, getEncoding()));
}
setParsedBounds(position, end);
@@ -298,7 +304,7 @@ void body::generate(utility::outputStream& os, const string::size_type maxLineLe
else
{
// Generate the contents
- m_contents.generate(os, getEncoding(), maxLineLength);
+ m_contents->generate(os, getEncoding(), maxLineLength);
}
}
@@ -471,7 +477,7 @@ void body::copyFrom(const component& other)
m_prologText = bdy.m_prologText;
m_epilogText = bdy.m_epilogText;
- m_contents = bdy.m_contents;
+ setContentsImpl(*bdy.m_contents);
removeAllParts();
@@ -519,19 +525,13 @@ void body::setEpilogText(const string& epilogText)
const contentHandler& body::getContents() const
{
- return (m_contents);
-}
-
-
-contentHandler& body::getContents()
-{
- return (m_contents);
+ return (*m_contents);
}
void body::setContents(const contentHandler& contents)
{
- m_contents = contents;
+ setContentsImpl(contents);
}
@@ -716,4 +716,11 @@ const std::vector <const component*> body::getChildComponents() const
}
+void body::setContentsImpl(const contentHandler& cts)
+{
+ delete (m_contents);
+ m_contents = cts.clone();
+}
+
+
} // vmime
diff --git a/src/contentHandler.cpp b/src/contentHandler.cpp
index 295df165..ced4cd3e 100644
--- a/src/contentHandler.cpp
+++ b/src/contentHandler.cpp
@@ -28,342 +28,9 @@ namespace vmime
const encoding contentHandler::NO_ENCODING(encodingTypes::BINARY);
-contentHandler::contentHandler()
- : m_type(TYPE_NONE), m_encoding(NO_ENCODING), m_ownedStream(NULL), m_stream(NULL)
-{
-}
-
-
-contentHandler::contentHandler(const string& buffer, const vmime::encoding& enc)
- : m_type(TYPE_STRING), m_encoding(enc), m_string(buffer),
- m_ownedStream(NULL), m_stream(NULL)
-{
-}
-
-
contentHandler::~contentHandler()
{
}
-contentHandler::contentHandler(const contentHandler& cts)
- : m_type(cts.m_type), m_encoding(cts.m_encoding), m_string(cts.m_string),
- m_ownedStream(const_cast <utility::smart_ptr <utility::inputStream>&>(cts.m_ownedStream)),
- m_stream(cts.m_stream), m_length(cts.m_length)
-{
-}
-
-
-contentHandler& contentHandler::operator=(const contentHandler& cts)
-{
- m_type = cts.m_type;
- m_encoding = cts.m_encoding;
-
- m_string = cts.m_string;
-
- m_ownedStream = const_cast <utility::smart_ptr <utility::inputStream>&>(cts.m_ownedStream);
- m_stream = cts.m_stream;
- m_length = cts.m_length;
-
- return (*this);
-}
-
-
-void contentHandler::setData(const utility::stringProxy& str, const vmime::encoding& enc)
-{
- m_type = TYPE_STRING;
- m_encoding = enc;
-
- m_string = str;
-
- m_ownedStream = NULL;
- m_stream = NULL;
-}
-
-
-void contentHandler::setData(const string& buffer, const vmime::encoding& enc)
-{
- m_type = TYPE_STRING;
- m_encoding = enc;
-
- m_string.set(buffer);
-
- m_ownedStream = NULL;
- m_stream = NULL;
-}
-
-
-void contentHandler::setData(const string& buffer, const string::size_type start,
- const string::size_type end, const vmime::encoding& enc)
-{
- m_type = TYPE_STRING;
- m_encoding = enc;
-
- m_string.set(buffer, start, end);
-
- m_ownedStream = NULL;
- m_stream = NULL;
-}
-
-
-void contentHandler::setData(utility::inputStream* is, const utility::stream::size_type length,
- const bool own, const vmime::encoding& enc)
-{
- m_type = TYPE_STREAM;
- m_encoding = enc;
-
- m_length = length;
-
- if (own)
- {
- m_ownedStream = is;
- m_stream = NULL;
- }
- else
- {
- m_ownedStream = NULL;
- m_stream = is;
- }
-
- m_string.detach();
-}
-
-
-contentHandler& contentHandler::operator=(const string& buffer)
-{
- setData(buffer, NO_ENCODING);
- return (*this);
-}
-
-
-void contentHandler::generate(utility::outputStream& os, const vmime::encoding& enc,
- const string::size_type maxLineLength) const
-{
- if (m_type == TYPE_NONE)
- return;
-
- // Managed data is already encoded
- if (isEncoded())
- {
- // The data is already encoded but the encoding specified for
- // the generation is different from the current one. We need
- // to re-encode data: decode from input buffer to temporary
- // buffer, and then re-encode to output stream...
- if (m_encoding != enc)
- {
- utility::auto_ptr <encoder> theDecoder(m_encoding.getEncoder());
- utility::auto_ptr <encoder> theEncoder(enc.getEncoder());
-
- theEncoder->getProperties()["maxlinelength"] = maxLineLength;
-
- switch (m_type)
- {
- default:
- {
- // No data
- break;
- }
- case TYPE_STRING:
- {
- utility::inputStreamStringProxyAdapter in(m_string);
-
- std::ostringstream oss;
- utility::outputStreamAdapter tempOut(oss);
-
- theDecoder->decode(in, tempOut);
-
- string str = oss.str();
- utility::inputStreamStringAdapter tempIn(str);
-
- theEncoder->encode(tempIn, os);
-
- break;
- }
- case TYPE_STREAM:
- {
- utility::inputStream& in = const_cast <utility::inputStream&>
- (*(m_stream ? m_stream : m_ownedStream.ptr()));
-
- in.reset(); // may not work...
-
- std::ostringstream oss;
- utility::outputStreamAdapter tempOut(oss);
-
- theDecoder->decode(in, tempOut);
-
- string str = oss.str();
- utility::inputStreamStringAdapter tempIn(str);
-
- theEncoder->encode(tempIn, os);
-
- break;
- }
-
- }
- }
- // No encoding to perform
- else
- {
- switch (m_type)
- {
- default:
- {
- // No data
- break;
- }
- case TYPE_STRING:
- {
- m_string.extract(os);
- break;
- }
- case TYPE_STREAM:
- {
- utility::inputStream& in = const_cast <utility::inputStream&>
- (*(m_stream ? m_stream : m_ownedStream.ptr()));
-
- in.reset(); // may not work...
-
- utility::bufferedStreamCopy(in, os);
- break;
- }
-
- }
- }
- }
- // Need to encode data before
- else
- {
- utility::auto_ptr <encoder> theEncoder(enc.getEncoder());
- theEncoder->getProperties()["maxlinelength"] = maxLineLength;
-
- // Encode the contents
- switch (m_type)
- {
- default:
- {
- // No data
- break;
- }
- case TYPE_STRING:
- {
- utility::inputStreamStringProxyAdapter in(m_string);
-
- theEncoder->encode(in, os);
- break;
- }
- case TYPE_STREAM:
- {
- utility::inputStream& in = const_cast <utility::inputStream&>
- (*(m_stream ? m_stream : m_ownedStream.ptr()));
-
- in.reset(); // may not work...
-
- theEncoder->encode(in, os);
- break;
- }
-
- }
- }
-}
-
-
-void contentHandler::extract(utility::outputStream& os) const
-{
- if (m_type == TYPE_NONE)
- return;
-
- // No decoding to perform
- if (!isEncoded())
- {
- switch (m_type)
- {
- default:
- {
- // No data
- break;
- }
- case TYPE_STRING:
- {
- m_string.extract(os);
- break;
- }
- case TYPE_STREAM:
- {
- utility::inputStream& in = const_cast <utility::inputStream&>
- (*(m_stream ? m_stream : m_ownedStream.ptr()));
-
- in.reset(); // may not work...
-
- utility::bufferedStreamCopy(in, os);
- break;
- }
-
- }
- }
- // Need to decode data
- else
- {
- utility::auto_ptr <encoder> theDecoder(m_encoding.getEncoder());
-
- switch (m_type)
- {
- default:
- {
- // No data
- break;
- }
- case TYPE_STRING:
- {
- utility::inputStreamStringProxyAdapter in(m_string);
-
- theDecoder->decode(in, os);
- break;
- }
- case TYPE_STREAM:
- {
- utility::inputStream& in = const_cast <utility::inputStream&>
- (*(m_stream ? m_stream : m_ownedStream.ptr()));
-
- in.reset(); // may not work...
-
- theDecoder->decode(in, os);
- break;
- }
-
- }
- }
-}
-
-
-const string::size_type contentHandler::getLength() const
-{
- switch (m_type)
- {
- case TYPE_NONE: return (0);
- case TYPE_STRING: return (m_string.length());
- case TYPE_STREAM: return (m_length);
- }
-
- return (0);
-}
-
-
-const bool contentHandler::isEmpty() const
-{
- return (m_type == TYPE_NONE);
-}
-
-
-const bool contentHandler::isEncoded() const
-{
- return (m_encoding != NO_ENCODING);
-}
-
-
-const vmime::encoding& contentHandler::getEncoding() const
-{
- return (m_encoding);
-}
-
-
} // vmime
diff --git a/src/defaultAttachment.cpp b/src/defaultAttachment.cpp
index 263ceb8a..43842eaf 100644
--- a/src/defaultAttachment.cpp
+++ b/src/defaultAttachment.cpp
@@ -32,30 +32,40 @@ defaultAttachment::defaultAttachment()
defaultAttachment::defaultAttachment(const contentHandler& data,
const encoding& enc, const mediaType& type, const text& desc)
- : m_type(type), m_desc(desc), m_data(data), m_encoding(enc)
+ : m_type(type), m_desc(desc), m_data(data.clone()), m_encoding(enc)
{
}
defaultAttachment::defaultAttachment(const contentHandler& data,
const mediaType& type, const text& desc)
- : m_type(type), m_desc(desc), m_data(data), m_encoding(encoding::decide(data))
+ : m_type(type), m_desc(desc), m_data(data.clone()),
+ m_encoding(encoding::decide(data))
{
}
defaultAttachment::defaultAttachment(const defaultAttachment& attach)
: attachment(), m_type(attach.m_type), m_desc(attach.m_desc),
- m_data(attach.m_data), m_encoding(attach.m_encoding)
+ m_data(attach.m_data->clone()), m_encoding(attach.m_encoding)
{
}
+defaultAttachment::~defaultAttachment()
+{
+ delete (m_data);
+}
+
+
defaultAttachment& defaultAttachment::operator=(const defaultAttachment& attach)
{
+ if (m_data)
+ delete (m_data);
+
m_type = attach.m_type;
m_desc = attach.m_desc;
- m_data = attach.m_data;
+ m_data = attach.m_data->clone();
m_encoding = attach.m_encoding;
return (*this);
@@ -81,7 +91,7 @@ void defaultAttachment::generatePart(bodyPart& part) const
part.getHeader()->ContentDisposition().setValue(contentDisposition(contentDispositionTypes::ATTACHMENT));
// Set contents
- part.getBody()->getContents() = m_data;
+ part.getBody()->setContents(*m_data);
}
@@ -99,7 +109,7 @@ const text& defaultAttachment::getDescription() const
const contentHandler& defaultAttachment::getData() const
{
- return (m_data);
+ return (*m_data);
}
diff --git a/src/emptyContentHandler.cpp b/src/emptyContentHandler.cpp
new file mode 100644
index 00000000..e266c678
--- /dev/null
+++ b/src/emptyContentHandler.cpp
@@ -0,0 +1,75 @@
+//
+// VMime library (http://vmime.sourceforge.net)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+
+#include "vmime/emptyContentHandler.hpp"
+
+
+namespace vmime
+{
+
+
+emptyContentHandler::emptyContentHandler()
+{
+}
+
+
+contentHandler* emptyContentHandler::clone() const
+{
+ return new emptyContentHandler();
+}
+
+
+void emptyContentHandler::generate(utility::outputStream& /* os */, const vmime::encoding& /* enc */,
+ const string::size_type /* maxLineLength */) const
+{
+ // Nothing to do.
+}
+
+
+void emptyContentHandler::extract(utility::outputStream& /* os */) const
+{
+ // Nothing to do.
+}
+
+
+const string::size_type emptyContentHandler::getLength() const
+{
+ return (0);
+}
+
+
+const bool emptyContentHandler::isEmpty() const
+{
+ return (true);
+}
+
+
+const bool emptyContentHandler::isEncoded() const
+{
+ return (false);
+}
+
+
+const vmime::encoding& emptyContentHandler::getEncoding() const
+{
+ return (NO_ENCODING);
+}
+
+
+} // vmime
diff --git a/src/fileAttachment.cpp b/src/fileAttachment.cpp
index 9eff4af9..c156eb98 100644
--- a/src/fileAttachment.cpp
+++ b/src/fileAttachment.cpp
@@ -23,6 +23,8 @@
#include "vmime/fileAttachment.hpp"
#include "vmime/exception.hpp"
+#include "vmime/streamContentHandler.hpp"
+
namespace vmime
{
@@ -35,7 +37,7 @@ fileAttachment::fileAttachment(const string& filename, const mediaType& type, co
setData(filename);
- m_encoding = encoding::decide(m_data);
+ m_encoding = encoding::decide(*m_data);
}
@@ -62,7 +64,7 @@ void fileAttachment::setData(const string& filename)
throw exceptions::open_file_error();
}
- m_data.setData(new utility::inputStreamPointerAdapter(file, true), 0, true);
+ m_data = new streamContentHandler(new utility::inputStreamPointerAdapter(file, true), 0, true);
}
diff --git a/src/htmlTextPart.cpp b/src/htmlTextPart.cpp
index c8631142..0d2fdf17 100644
--- a/src/htmlTextPart.cpp
+++ b/src/htmlTextPart.cpp
@@ -20,14 +20,27 @@
#include "vmime/htmlTextPart.hpp"
#include "vmime/exception.hpp"
+#include "vmime/emptyContentHandler.hpp"
+#include "vmime/stringContentHandler.hpp"
+
namespace vmime
{
+htmlTextPart::htmlTextPart()
+ : m_plainText(new emptyContentHandler),
+ m_text(new emptyContentHandler)
+{
+}
+
+
htmlTextPart::~htmlTextPart()
{
free_container(m_objects);
+
+ delete (m_plainText);
+ delete (m_text);
}
@@ -39,14 +52,14 @@ const mediaType htmlTextPart::getType() const
const int htmlTextPart::getPartCount() const
{
- return (m_plainText.isEmpty() ? 1 : 2);
+ return (m_plainText->isEmpty() ? 1 : 2);
}
void htmlTextPart::generateIn(bodyPart& /* message */, bodyPart& parent) const
{
// Plain text
- if (!m_plainText.isEmpty())
+ if (!m_plainText->isEmpty())
{
// -- Create a new part
bodyPart* part = new bodyPart();
@@ -58,7 +71,7 @@ void htmlTextPart::generateIn(bodyPart& /* message */, bodyPart& parent) const
part->getHeader()->ContentTransferEncoding().setValue(encoding(encodingTypes::QUOTED_PRINTABLE));
// -- Set contents
- part->getBody()->setContents(m_plainText);
+ part->getBody()->setContents(*m_plainText);
}
// HTML text
@@ -71,7 +84,7 @@ void htmlTextPart::generateIn(bodyPart& /* message */, bodyPart& parent) const
htmlPart->getHeader()->ContentTransferEncoding().setValue(encoding(encodingTypes::QUOTED_PRINTABLE));
// -- Set contents
- htmlPart->getBody()->setContents(m_text);
+ htmlPart->getBody()->setContents(*m_text);
// Handle the case we have embedded objects
if (!m_objects.empty())
@@ -185,7 +198,8 @@ void htmlTextPart::parse(const bodyPart& message, const bodyPart& parent, const
const string data = oss.str();
- m_text = textPart.getBody()->getContents();
+ delete (m_text);
+ m_text = textPart.getBody()->getContents().clone();
try
{
@@ -234,7 +248,11 @@ void htmlTextPart::parse(const bodyPart& message, const bodyPart& parent, const
}
// Extract plain text, if any.
- findPlainTextPart(message, parent, textPart);
+ if (!findPlainTextPart(message, parent, textPart))
+ {
+ delete (m_plainText);
+ m_plainText = new emptyContentHandler();
+ }
}
@@ -279,7 +297,8 @@ bool htmlTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& paren
if (ctf.getValue().getType() == mediaTypes::TEXT &&
ctf.getValue().getSubType() == mediaTypes::TEXT_PLAIN)
{
- m_plainText = p.getBody()->getContents();
+ delete (m_plainText);
+ m_plainText = p.getBody()->getContents().clone();
found = true;
}
}
@@ -326,25 +345,27 @@ void htmlTextPart::setCharset(const charset& ch)
const contentHandler& htmlTextPart::getPlainText() const
{
- return (m_plainText);
+ return (*m_plainText);
}
void htmlTextPart::setPlainText(const contentHandler& plainText)
{
- m_plainText = plainText;
+ delete (m_plainText);
+ m_plainText = plainText.clone();
}
const contentHandler& htmlTextPart::getText() const
{
- return (m_text);
+ return (*m_text);
}
void htmlTextPart::setText(const contentHandler& text)
{
- m_text = text;
+ delete (m_text);
+ m_text = text.clone();
}
@@ -406,7 +427,8 @@ const string htmlTextPart::addObject(const contentHandler& data, const mediaType
const string htmlTextPart::addObject(const string& data, const mediaType& type)
{
- return (addObject(contentHandler(data), encoding::decide(data), type));
+ stringContentHandler cts(data);
+ return (addObject(cts, encoding::decide(cts), type));
}
@@ -418,14 +440,14 @@ const string htmlTextPart::addObject(const string& data, const mediaType& type)
htmlTextPart::embeddedObject::embeddedObject
(const contentHandler& data, const encoding& enc,
const string& id, const mediaType& type)
- : m_data(data), m_encoding(enc), m_id(id), m_type(type)
+ : m_data(data.clone()), m_encoding(enc), m_id(id), m_type(type)
{
}
const contentHandler& htmlTextPart::embeddedObject::getData() const
{
- return (m_data);
+ return (*m_data);
}
diff --git a/src/plainTextPart.cpp b/src/plainTextPart.cpp
index a1902bb6..cfaf35a4 100644
--- a/src/plainTextPart.cpp
+++ b/src/plainTextPart.cpp
@@ -21,11 +21,25 @@
#include "vmime/header.hpp"
#include "vmime/exception.hpp"
+#include "vmime/emptyContentHandler.hpp"
+
namespace vmime
{
+plainTextPart::plainTextPart()
+ : m_text(new emptyContentHandler)
+{
+}
+
+
+plainTextPart::~plainTextPart()
+{
+ delete (m_text);
+}
+
+
const mediaType plainTextPart::getType() const
{
return (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN));
@@ -50,14 +64,15 @@ void plainTextPart::generateIn(bodyPart& /* message */, bodyPart& parent) const
part->getHeader()->ContentTransferEncoding().setValue(encoding(encodingTypes::QUOTED_PRINTABLE));
// Set contents
- part->getBody()->setContents(m_text);
+ part->getBody()->setContents(*m_text);
}
void plainTextPart::parse(const bodyPart& /* message */,
const bodyPart& /* parent */, const bodyPart& textPart)
{
- m_text = textPart.getBody()->getContents();
+ delete (m_text);
+ m_text = textPart.getBody()->getContents().clone();
try
{
@@ -91,13 +106,14 @@ void plainTextPart::setCharset(const charset& ch)
const contentHandler& plainTextPart::getText() const
{
- return (m_text);
+ return (*m_text);
}
void plainTextPart::setText(const contentHandler& text)
{
- m_text = text;
+ delete (m_text);
+ m_text = text.clone();
}
diff --git a/src/streamContentHandler.cpp b/src/streamContentHandler.cpp
new file mode 100644
index 00000000..e0ff56bc
--- /dev/null
+++ b/src/streamContentHandler.cpp
@@ -0,0 +1,206 @@
+//
+// VMime library (http://vmime.sourceforge.net)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+
+#include "vmime/streamContentHandler.hpp"
+
+
+namespace vmime
+{
+
+
+streamContentHandler::streamContentHandler()
+ : m_encoding(NO_ENCODING), m_ownedStream(NULL), m_stream(NULL)
+{
+}
+
+
+streamContentHandler::streamContentHandler(utility::inputStream* is,
+ const utility::stream::size_type length, const bool own, const vmime::encoding& enc)
+{
+ setData(is, length, own, enc);
+}
+
+
+streamContentHandler::~streamContentHandler()
+{
+}
+
+
+streamContentHandler::streamContentHandler(const streamContentHandler& cts)
+ : contentHandler(), m_encoding(cts.m_encoding),
+ m_ownedStream(const_cast <utility::smart_ptr <utility::inputStream>&>(cts.m_ownedStream)),
+ m_stream(cts.m_stream), m_length(cts.m_length)
+{
+}
+
+
+contentHandler* streamContentHandler::clone() const
+{
+ return new streamContentHandler(*this);
+}
+
+
+streamContentHandler& streamContentHandler::operator=(const streamContentHandler& cts)
+{
+ m_encoding = cts.m_encoding;
+
+ m_ownedStream = const_cast <utility::smart_ptr <utility::inputStream>&>(cts.m_ownedStream);
+ m_stream = cts.m_stream;
+ m_length = cts.m_length;
+
+ return (*this);
+}
+
+
+void streamContentHandler::setData(utility::inputStream* is,
+ const utility::stream::size_type length, const bool own, const vmime::encoding& enc)
+{
+ m_encoding = enc;
+ m_length = length;
+
+ if (own)
+ {
+ m_ownedStream = is;
+ m_stream = NULL;
+ }
+ else
+ {
+ m_ownedStream = NULL;
+ m_stream = is;
+ }
+}
+
+
+void streamContentHandler::generate(utility::outputStream& os, const vmime::encoding& enc,
+ const string::size_type maxLineLength) const
+{
+ if (m_stream == NULL && m_ownedStream.ptr() == NULL)
+ return;
+
+ // Managed data is already encoded
+ if (isEncoded())
+ {
+ // The data is already encoded but the encoding specified for
+ // the generation is different from the current one. We need
+ // to re-encode data: decode from input buffer to temporary
+ // buffer, and then re-encode to output stream...
+ if (m_encoding != enc)
+ {
+ utility::auto_ptr <encoder> theDecoder(m_encoding.getEncoder());
+ utility::auto_ptr <encoder> theEncoder(enc.getEncoder());
+
+ theEncoder->getProperties()["maxlinelength"] = maxLineLength;
+
+ utility::inputStream& in = const_cast <utility::inputStream&>
+ (*(m_stream ? m_stream : m_ownedStream.ptr()));
+
+ in.reset(); // may not work...
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter tempOut(oss);
+
+ theDecoder->decode(in, tempOut);
+
+ string str = oss.str();
+ utility::inputStreamStringAdapter tempIn(str);
+
+ theEncoder->encode(tempIn, os);
+ }
+ // No encoding to perform
+ else
+ {
+ utility::inputStream& in = const_cast <utility::inputStream&>
+ (*(m_stream ? m_stream : m_ownedStream.ptr()));
+
+ in.reset(); // may not work...
+
+ utility::bufferedStreamCopy(in, os);
+ }
+ }
+ // Need to encode data before
+ else
+ {
+ utility::auto_ptr <encoder> theEncoder(enc.getEncoder());
+ theEncoder->getProperties()["maxlinelength"] = maxLineLength;
+
+ utility::inputStream& in = const_cast <utility::inputStream&>
+ (*(m_stream ? m_stream : m_ownedStream.ptr()));
+
+ in.reset(); // may not work...
+
+ theEncoder->encode(in, os);
+ }
+}
+
+
+void streamContentHandler::extract(utility::outputStream& os) const
+{
+ if (m_stream == NULL && m_ownedStream.ptr() == NULL)
+ return;
+
+ // No decoding to perform
+ if (!isEncoded())
+ {
+ utility::inputStream& in = const_cast <utility::inputStream&>
+ (*(m_stream ? m_stream : m_ownedStream.ptr()));
+
+ in.reset(); // may not work...
+
+ utility::bufferedStreamCopy(in, os);
+ }
+ // Need to decode data
+ else
+ {
+ utility::auto_ptr <encoder> theDecoder(m_encoding.getEncoder());
+
+ utility::inputStream& in = const_cast <utility::inputStream&>
+ (*(m_stream ? m_stream : m_ownedStream.ptr()));
+
+ in.reset(); // may not work...
+
+ theDecoder->decode(in, os);
+ }
+}
+
+
+const string::size_type streamContentHandler::getLength() const
+{
+ return (m_length);
+}
+
+
+const bool streamContentHandler::isEmpty() const
+{
+ return (m_length == 0 || (m_stream == NULL && m_ownedStream.ptr() == NULL));
+}
+
+
+const bool streamContentHandler::isEncoded() const
+{
+ return (m_encoding != NO_ENCODING);
+}
+
+
+const vmime::encoding& streamContentHandler::getEncoding() const
+{
+ return (m_encoding);
+}
+
+
+} // vmime
diff --git a/src/stringContentHandler.cpp b/src/stringContentHandler.cpp
new file mode 100644
index 00000000..4c67756d
--- /dev/null
+++ b/src/stringContentHandler.cpp
@@ -0,0 +1,192 @@
+//
+// VMime library (http://vmime.sourceforge.net)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+
+#include "vmime/stringContentHandler.hpp"
+
+
+namespace vmime
+{
+
+
+stringContentHandler::stringContentHandler(const string& buffer, const vmime::encoding& enc)
+ : m_encoding(enc), m_string(buffer)
+{
+}
+
+
+stringContentHandler::stringContentHandler(const stringContentHandler& cts)
+ : contentHandler(), m_encoding(cts.m_encoding), m_string(cts.m_string)
+{
+}
+
+
+stringContentHandler::stringContentHandler(const utility::stringProxy& str, const vmime::encoding& enc)
+ : m_encoding(enc), m_string(str)
+{
+}
+
+
+stringContentHandler::stringContentHandler(const string& buffer, const string::size_type start,
+ const string::size_type end, const vmime::encoding& enc)
+ : m_encoding(enc), m_string(buffer, start, end)
+{
+}
+
+
+stringContentHandler::~stringContentHandler()
+{
+}
+
+
+contentHandler* stringContentHandler::clone() const
+{
+ return new stringContentHandler(*this);
+}
+
+
+stringContentHandler& stringContentHandler::operator=(const stringContentHandler& cts)
+{
+ m_encoding = cts.m_encoding;
+ m_string = cts.m_string;
+
+ return (*this);
+}
+
+
+void stringContentHandler::setData(const utility::stringProxy& str, const vmime::encoding& enc)
+{
+ m_encoding = enc;
+ m_string = str;
+}
+
+
+void stringContentHandler::setData(const string& buffer, const vmime::encoding& enc)
+{
+ m_encoding = enc;
+ m_string.set(buffer);
+}
+
+
+void stringContentHandler::setData(const string& buffer, const string::size_type start,
+ const string::size_type end, const vmime::encoding& enc)
+{
+ m_encoding = enc;
+ m_string.set(buffer, start, end);
+}
+
+
+stringContentHandler& stringContentHandler::operator=(const string& buffer)
+{
+ setData(buffer, NO_ENCODING);
+ return (*this);
+}
+
+
+void stringContentHandler::generate(utility::outputStream& os,
+ const vmime::encoding& enc, const string::size_type maxLineLength) const
+{
+ // Managed data is already encoded
+ if (isEncoded())
+ {
+ // The data is already encoded but the encoding specified for
+ // the generation is different from the current one. We need
+ // to re-encode data: decode from input buffer to temporary
+ // buffer, and then re-encode to output stream...
+ if (m_encoding != enc)
+ {
+ utility::auto_ptr <encoder> theDecoder(m_encoding.getEncoder());
+ utility::auto_ptr <encoder> theEncoder(enc.getEncoder());
+
+ theEncoder->getProperties()["maxlinelength"] = maxLineLength;
+
+ utility::inputStreamStringProxyAdapter in(m_string);
+
+ std::ostringstream oss;
+ utility::outputStreamAdapter tempOut(oss);
+
+ theDecoder->decode(in, tempOut);
+
+ string str = oss.str();
+ utility::inputStreamStringAdapter tempIn(str);
+
+ theEncoder->encode(tempIn, os);
+ }
+ // No encoding to perform
+ else
+ {
+ m_string.extract(os);
+ }
+ }
+ // Need to encode data before
+ else
+ {
+ utility::auto_ptr <encoder> theEncoder(enc.getEncoder());
+ theEncoder->getProperties()["maxlinelength"] = maxLineLength;
+
+ utility::inputStreamStringProxyAdapter in(m_string);
+
+ theEncoder->encode(in, os);
+ }
+}
+
+
+void stringContentHandler::extract(utility::outputStream& os) const
+{
+ // No decoding to perform
+ if (!isEncoded())
+ {
+ m_string.extract(os);
+ }
+ // Need to decode data
+ else
+ {
+ utility::auto_ptr <encoder> theDecoder(m_encoding.getEncoder());
+
+ utility::inputStreamStringProxyAdapter in(m_string);
+
+ theDecoder->decode(in, os);
+ }
+}
+
+
+const string::size_type stringContentHandler::getLength() const
+{
+ return (m_string.length());
+}
+
+
+const bool stringContentHandler::isEmpty() const
+{
+ return (m_string.length() == 0);
+}
+
+
+const bool stringContentHandler::isEncoded() const
+{
+ return (m_encoding != NO_ENCODING);
+}
+
+
+const vmime::encoding& stringContentHandler::getEncoding() const
+{
+ return (m_encoding);
+}
+
+
+} // vmime
diff --git a/tests/parser/bodyPartTest.cpp b/tests/parser/bodyPartTest.cpp
index 59741736..0bfdb1e1 100644
--- a/tests/parser/bodyPartTest.cpp
+++ b/tests/parser/bodyPartTest.cpp
@@ -68,7 +68,7 @@ namespace
{
vmime::bodyPart p1;
p1.getHeader()->getField("Foo")->setValue(vmime::string("bar"));
- p1.getBody()->getContents() = "Baz";
+ p1.getBody()->setContents(vmime::stringContentHandler("Baz"));
assert_eq("1", "Foo: bar\r\n\r\nBaz", p1.generate());
}
diff --git a/vmime/body.hpp b/vmime/body.hpp
index cd2f8074..5c03f7fe 100644
--- a/vmime/body.hpp
+++ b/vmime/body.hpp
@@ -178,12 +178,6 @@ public:
*/
const contentHandler& getContents() const;
- /** Return a modifiable reference to body contents.
- *
- * @return body contents
- */
- contentHandler& getContents();
-
/** Set the body contents.
*
* @param contents new body contents
@@ -238,7 +232,7 @@ private:
string m_prologText;
string m_epilogText;
- contentHandler m_contents;
+ contentHandler* m_contents;
bodyPart* m_part;
header* m_header;
@@ -249,6 +243,8 @@ private:
void initNewPart(bodyPart* part);
+ void setContentsImpl(const contentHandler& cts);
+
public:
using component::parse;
diff --git a/vmime/contentHandler.hpp b/vmime/contentHandler.hpp
index f3fa8a6e..3fee6d88 100644
--- a/vmime/contentHandler.hpp
+++ b/vmime/contentHandler.hpp
@@ -35,87 +35,62 @@ namespace vmime
class contentHandler
{
-private:
+public:
+ /** Used to specify that enclosed data is not encoded. */
static const vmime::encoding NO_ENCODING;
-public:
- contentHandler();
- contentHandler(const string& buffer, const vmime::encoding& enc = NO_ENCODING); // for compatibility
- ~contentHandler();
-
- // Copy
- contentHandler(const contentHandler& cts);
- contentHandler& operator=(const contentHandler& cts);
-
- // Set the data contained in the body.
- //
- // The two first functions take advantage of the COW (copy-on-write) system that
- // might be implemented into std::string. This is done using "stringProxy" object.
- //
- // Set "enc" parameter to anything other than NO_ENCODING if the data managed by
- // this content handler is already encoded with the specified encoding (so, no
- // encoding/decoding will be performed on generate()/extract()). Note that the
- // data may be re-encoded (that is, decoded and encoded) if the encoding passed
- // to generate() is different from this one...
- //
- // The 'length' parameter is optional (user-defined). You can pass 0 if you want,
- // VMime does not make use of it.
- void setData(const utility::stringProxy& str, const vmime::encoding& enc = NO_ENCODING);
- void setData(const string& buffer, const vmime::encoding& enc = NO_ENCODING);
- void setData(const string& buffer, const string::size_type start, const string::size_type end, const vmime::encoding& enc = NO_ENCODING);
- void setData(utility::inputStream* is, const utility::stream::size_type length, const bool own, const vmime::encoding& enc = NO_ENCODING);
-
- // For compatibility
- contentHandler& operator=(const string& buffer);
-
- // WRITE: Output the contents into the specified stream. Data will be
- // encoded before being written into the stream. This is used internally
- // by the body object to generate the message, you may not need to use
- // this (see function extract() if you want to get the contents).
- void generate(utility::outputStream& os, const vmime::encoding& enc, const string::size_type maxLineLength = lineLengthLimits::infinite) const;
-
- // READ: Extract the contents into the specified stream. If needed, data
- // will be decoded before being written into the stream.
- void extract(utility::outputStream& os) const;
-
- // Returns the actual length of the data. WARNING: this can return 0 if no
- // length was specified when setting data of this object.
- const string::size_type getLength() const;
-
- // Returns 'true' if the data managed by this object is encoded.
- const bool isEncoded() const;
-
- // Returns the encoding used for the data (or "binary" if not encoded).
- const vmime::encoding& getEncoding() const;
-
- // Returns 'true' if there is no data set.
- const bool isEmpty() const;
-
-private:
-
- // Source of data managed by this content handler
- enum Types
- {
- TYPE_NONE,
- TYPE_STRING,
- TYPE_STREAM
- };
-
- Types m_type;
-
- // Equals to NO_ENCODING if data is not encoded, otherwise this
- // specifies the encoding that have been used to encode the data.
- vmime::encoding m_encoding;
-
- // Used if m_type == TYPE_STRING
- utility::stringProxy m_string;
-
- // Used if m_type == TYPE_STREAM
- utility::smart_ptr <utility::inputStream> m_ownedStream; // 'contentHandler' objects are copiable...
- utility::inputStream* m_stream;
- string::size_type m_length;
+ virtual ~contentHandler();
+
+ /** Return a copy of this object.
+ *
+ * @return copy of this object
+ */
+ virtual contentHandler* clone() const = 0;
+
+ /** Output the contents into the specified stream. Data will be
+ * encoded before being written into the stream. This is used internally
+ * by the body object to generate the message, you may not need to use
+ * this (see contentHandler::extract() if you want to get the contents).
+ *
+ * @param os output stream
+ * @param enc encoding for output
+ * @param maxLineLength maximum line length for output
+ */
+ virtual void generate(utility::outputStream& os, const vmime::encoding& enc, const string::size_type maxLineLength = lineLengthLimits::infinite) const = 0;
+
+ /** Extract the contents into the specified stream. If needed, data
+ * will be decoded before being written into the stream.
+ *
+ * @param os output stream
+ */
+ virtual void extract(utility::outputStream& os) const = 0;
+
+ /** Returns the actual length of data. WARNING: this can return 0 if no
+ * length was specified when setting data of this object.
+ *
+ * @return length of data
+ */
+ virtual const string::size_type getLength() const = 0;
+
+ /** Returns 'true' if data managed by this object is encoded.
+ *
+ * @return true if data is encoded, false otherwise
+ */
+ virtual const bool isEncoded() const = 0;
+
+ /** Returns the encoding used for data (or "binary" if not encoded).
+ *
+ * @return encoding used for data
+ */
+ virtual const vmime::encoding& getEncoding() const = 0;
+
+ /** Returns 'true' if there is no data set.
+ *
+ * @return true if no data is managed by this object, false otherwise
+ */
+ virtual const bool isEmpty() const = 0;
};
diff --git a/vmime/defaultAttachment.hpp b/vmime/defaultAttachment.hpp
index 825f1084..cdc44fbd 100644
--- a/vmime/defaultAttachment.hpp
+++ b/vmime/defaultAttachment.hpp
@@ -45,6 +45,8 @@ public:
defaultAttachment(const contentHandler& data, const mediaType& type, const text& desc = NULL_TEXT);
defaultAttachment(const defaultAttachment& attach);
+ ~defaultAttachment();
+
defaultAttachment& operator=(const defaultAttachment& attach);
const mediaType& getType() const;
@@ -56,7 +58,7 @@ protected:
mediaType m_type; // Media type (eg. "application/octet-stream")
text m_desc; // Description (eg. "The image you requested")
- contentHandler m_data; // Attachment data (eg. the file contents)
+ contentHandler* m_data; // Attachment data (eg. the file contents)
encoding m_encoding; // Encoding
private:
diff --git a/vmime/emptyContentHandler.hpp b/vmime/emptyContentHandler.hpp
new file mode 100644
index 00000000..b02d3182
--- /dev/null
+++ b/vmime/emptyContentHandler.hpp
@@ -0,0 +1,56 @@
+//
+// VMime library (http://vmime.sourceforge.net)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+
+#ifndef VMIME_EMPTYCONTENTHANDLER_HPP_INCLUDED
+#define VMIME_EMPTYCONTENTHANDLER_HPP_INCLUDED
+
+
+#include "vmime/contentHandler.hpp"
+
+
+namespace vmime
+{
+
+
+class emptyContentHandler : public contentHandler
+{
+public:
+
+ emptyContentHandler();
+
+ contentHandler* clone() const;
+
+ void generate(utility::outputStream& os, const vmime::encoding& enc, const string::size_type maxLineLength = lineLengthLimits::infinite) const;
+
+ void extract(utility::outputStream& os) const;
+
+ const string::size_type getLength() const;
+
+ const bool isEncoded() const;
+
+ const vmime::encoding& getEncoding() const;
+
+ const bool isEmpty() const;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_EMPTYCONTENTHANDLER_HPP_INCLUDED
diff --git a/vmime/htmlTextPart.hpp b/vmime/htmlTextPart.hpp
index 4e8797da..e033461d 100644
--- a/vmime/htmlTextPart.hpp
+++ b/vmime/htmlTextPart.hpp
@@ -43,6 +43,8 @@ protected:
public:
+ htmlTextPart();
+
const mediaType getType() const;
const charset& getCharset() const;
@@ -91,7 +93,7 @@ public:
private:
- contentHandler m_data;
+ contentHandler* m_data;
encoding m_encoding;
string m_id;
mediaType m_type;
@@ -160,8 +162,8 @@ public:
private:
- contentHandler m_plainText;
- contentHandler m_text;
+ contentHandler* m_plainText;
+ contentHandler* m_text;
charset m_charset;
std::vector <embeddedObject*> m_objects;
diff --git a/vmime/plainTextPart.hpp b/vmime/plainTextPart.hpp
index aebe1e6a..bb0322c8 100644
--- a/vmime/plainTextPart.hpp
+++ b/vmime/plainTextPart.hpp
@@ -35,6 +35,9 @@ class plainTextPart : public textPart
{
public:
+ plainTextPart();
+ ~plainTextPart();
+
const mediaType getType() const;
const charset& getCharset() const;
@@ -45,7 +48,7 @@ public:
private:
- contentHandler m_text;
+ contentHandler* m_text;
charset m_charset;
const int getPartCount() const;
diff --git a/vmime/streamContentHandler.hpp b/vmime/streamContentHandler.hpp
new file mode 100644
index 00000000..34f66d39
--- /dev/null
+++ b/vmime/streamContentHandler.hpp
@@ -0,0 +1,76 @@
+//
+// VMime library (http://vmime.sourceforge.net)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+
+#ifndef VMIME_STREAMCONTENTHANDLER_HPP_INCLUDED
+#define VMIME_STREAMCONTENTHANDLER_HPP_INCLUDED
+
+
+#include "vmime/contentHandler.hpp"
+
+
+namespace vmime
+{
+
+
+class streamContentHandler : public contentHandler
+{
+public:
+
+ streamContentHandler();
+ streamContentHandler(utility::inputStream* is, const utility::stream::size_type length, const bool own, const vmime::encoding& enc = NO_ENCODING);
+
+ ~streamContentHandler();
+
+ streamContentHandler(const streamContentHandler& cts);
+ streamContentHandler& operator=(const streamContentHandler& cts);
+
+ contentHandler* clone() const;
+
+ void setData(utility::inputStream* is, const utility::stream::size_type length, const bool own, const vmime::encoding& enc = NO_ENCODING);
+
+
+ void generate(utility::outputStream& os, const vmime::encoding& enc, const string::size_type maxLineLength = lineLengthLimits::infinite) const;
+
+ void extract(utility::outputStream& os) const;
+
+ const string::size_type getLength() const;
+
+ const bool isEncoded() const;
+
+ const vmime::encoding& getEncoding() const;
+
+ const bool isEmpty() const;
+
+private:
+
+ // Equals to NO_ENCODING if data is not encoded, otherwise this
+ // specifies the encoding that have been used to encode the data.
+ vmime::encoding m_encoding;
+
+ // Actual data
+ utility::smart_ptr <utility::inputStream> m_ownedStream; // 'contentHandler' objects are copiable...
+ utility::inputStream* m_stream;
+ string::size_type m_length;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_STREAMCONTENTHANDLER_HPP_INCLUDED
diff --git a/vmime/stringContentHandler.hpp b/vmime/stringContentHandler.hpp
new file mode 100644
index 00000000..f859c1bb
--- /dev/null
+++ b/vmime/stringContentHandler.hpp
@@ -0,0 +1,92 @@
+//
+// VMime library (http://vmime.sourceforge.net)
+// Copyright (C) 2002-2005 Vincent Richard <[email protected]>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+
+#ifndef VMIME_STRINGCONTENTHANDLER_HPP_INCLUDED
+#define VMIME_STRINGCONTENTHANDLER_HPP_INCLUDED
+
+
+#include "vmime/contentHandler.hpp"
+
+
+namespace vmime
+{
+
+
+class stringContentHandler : public contentHandler
+{
+public:
+
+ stringContentHandler();
+ stringContentHandler(const string& buffer, const vmime::encoding& enc = NO_ENCODING);
+ stringContentHandler(const utility::stringProxy& str, const vmime::encoding& enc = NO_ENCODING);
+ stringContentHandler(const string& buffer, const string::size_type start, const string::size_type end, const vmime::encoding& enc = NO_ENCODING);
+
+ ~stringContentHandler();
+
+ stringContentHandler(const stringContentHandler& cts);
+ stringContentHandler& operator=(const stringContentHandler& cts);
+
+ contentHandler* clone() const;
+
+ // Set the data contained in the body.
+ //
+ // The two first functions take advantage of the COW (copy-on-write) system that
+ // might be implemented into std::string. This is done using "stringProxy" object.
+ //
+ // Set "enc" parameter to anything other than NO_ENCODING if the data managed by
+ // this content handler is already encoded with the specified encoding (so, no
+ // encoding/decoding will be performed on generate()/extract()). Note that the
+ // data may be re-encoded (that is, decoded and encoded) if the encoding passed
+ // to generate() is different from this one...
+ //
+ // The 'length' parameter is optional (user-defined). You can pass 0 if you want,
+ // VMime does not make use of it.
+ void setData(const utility::stringProxy& str, const vmime::encoding& enc = NO_ENCODING);
+ void setData(const string& buffer, const vmime::encoding& enc = NO_ENCODING);
+ void setData(const string& buffer, const string::size_type start, const string::size_type end, const vmime::encoding& enc = NO_ENCODING);
+
+ stringContentHandler& operator=(const string& buffer);
+
+ void generate(utility::outputStream& os, const vmime::encoding& enc, const string::size_type maxLineLength = lineLengthLimits::infinite) const;
+
+ void extract(utility::outputStream& os) const;
+
+ const string::size_type getLength() const;
+
+ const bool isEncoded() const;
+
+ const vmime::encoding& getEncoding() const;
+
+ const bool isEmpty() const;
+
+private:
+
+ // Equals to NO_ENCODING if data is not encoded, otherwise this
+ // specifies the encoding that have been used to encode the data.
+ vmime::encoding m_encoding;
+
+ // The actual data
+ utility::stringProxy m_string;
+};
+
+
+} // vmime
+
+
+#endif // VMIME_STRINGCONTENTHANDLER_HPP_INCLUDED
diff --git a/vmime/vmime.hpp b/vmime/vmime.hpp
index fe5ac77b..910eea9c 100644
--- a/vmime/vmime.hpp
+++ b/vmime/vmime.hpp
@@ -46,6 +46,10 @@
#include "vmime/messageId.hpp"
#include "vmime/relay.hpp"
+#include "vmime/emptyContentHandler.hpp"
+#include "vmime/stringContentHandler.hpp"
+#include "vmime/streamContentHandler.hpp"
+
// Message components
#include "vmime/message.hpp"