aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Richard <[email protected]>2013-04-16 10:03:13 +0000
committerVincent Richard <[email protected]>2013-04-16 10:03:13 +0000
commit462311e382834bc893df9433b916f28ae9830090 (patch)
treebd06919a108eeff55ef8e0a7031885fcb573b60c
parentIssue #4: set envelope sender. (diff)
downloadvmime-462311e382834bc893df9433b916f28ae9830090.tar.gz
vmime-462311e382834bc893df9433b916f28ae9830090.zip
Added filtered output stream to transform LFs to CRLFs.
-rw-r--r--src/utility/filteredStream.cpp71
-rw-r--r--tests/testUtils.hpp2
-rw-r--r--tests/utility/filteredStreamTest.cpp40
-rw-r--r--vmime/utility/filteredStream.hpp26
4 files changed, 139 insertions, 0 deletions
diff --git a/src/utility/filteredStream.cpp b/src/utility/filteredStream.cpp
index 9af7b32a..294a7a94 100644
--- a/src/utility/filteredStream.cpp
+++ b/src/utility/filteredStream.cpp
@@ -286,6 +286,77 @@ void CRLFToLFFilteredOutputStream::flush()
}
+// LFToCRLFFilteredOutputStream
+
+LFToCRLFFilteredOutputStream::LFToCRLFFilteredOutputStream(outputStream& os)
+ : m_stream(os), m_previousChar('\0')
+{
+}
+
+
+outputStream& LFToCRLFFilteredOutputStream::getNextOutputStream()
+{
+ return (m_stream);
+}
+
+
+void LFToCRLFFilteredOutputStream::write
+ (const value_type* const data, const size_type count)
+{
+ if (count == 0)
+ return;
+
+ std::string buffer;
+ buffer.reserve(count);
+
+ const value_type* pos = data;
+ const value_type* end = data + count;
+
+ value_type previousChar = m_previousChar;
+
+ while (pos < end)
+ {
+ switch (*pos)
+ {
+ case '\r':
+
+ buffer.append(1, '\r');
+ buffer.append(1, '\n');
+
+ break;
+
+ case '\n':
+
+ if (previousChar != '\r')
+ {
+ buffer.append(1, '\r');
+ buffer.append(1, '\n');
+ }
+
+ break;
+
+ default:
+
+ buffer.append(1, *pos);
+ break;
+ }
+
+ previousChar = *pos;
+ ++pos;
+ }
+
+ m_stream.write(&buffer[0], buffer.length());
+
+ m_previousChar = previousChar;
+}
+
+
+void LFToCRLFFilteredOutputStream::flush()
+{
+ m_stream.flush();
+}
+
+
// stopSequenceFilteredInputStream <1>
template <>
diff --git a/tests/testUtils.hpp b/tests/testUtils.hpp
index 4fa6b457..1e138301 100644
--- a/tests/testUtils.hpp
+++ b/tests/testUtils.hpp
@@ -53,6 +53,8 @@
#define VASSERT_EQ(msg, expected, actual) \
CPPUNIT_ASSERT_EQUAL_MESSAGE(std::string(msg), expected, actual)
+#define VASSERT_NEQ(msg, expected, actual) \
+ CPPUNIT_ASSERT_MESSAGE(std::string(msg), (expected) != (actual))
#define VASSERT_THROW(msg, expression, exceptionType) \
CPPUNIT_ASSERT_THROW(expression, exceptionType)
diff --git a/tests/utility/filteredStreamTest.cpp b/tests/utility/filteredStreamTest.cpp
index 4a869c6e..76cb149b 100644
--- a/tests/utility/filteredStreamTest.cpp
+++ b/tests/utility/filteredStreamTest.cpp
@@ -35,6 +35,8 @@ VMIME_TEST_SUITE_BEGIN(filteredStreamTest)
VMIME_TEST(testStopSequenceFilteredInputStream1)
VMIME_TEST(testStopSequenceFilteredInputStreamN_2)
VMIME_TEST(testStopSequenceFilteredInputStreamN_3)
+ VMIME_TEST(testLFToCRLFFilteredOutputStream_Global)
+ VMIME_TEST(testLFToCRLFFilteredOutputStream_Edge)
VMIME_TEST_LIST_END
@@ -276,5 +278,43 @@ VMIME_TEST_SUITE_BEGIN(filteredStreamTest)
testStopSequenceFISHelper <3>("24", "xyz", "", "x", "y", "z");
}
+
+ // LFToCRLFFilteredOutputStream
+
+ void testLFToCRLFFilteredOutputStream_Global()
+ {
+ typedef vmime::utility::LFToCRLFFilteredOutputStream FILTER;
+
+ testFilteredOutputStreamHelper<FILTER>("1", "ABC\r\nDEF", "ABC\nDEF");
+ testFilteredOutputStreamHelper<FILTER>("2", "ABC\r\nDEF", "ABC\rDEF");
+ testFilteredOutputStreamHelper<FILTER>("3", "\r\n\r\nAB\r\n\r\nA\r\nB\r\n", "\n\nAB\n\nA\nB\n");
+ testFilteredOutputStreamHelper<FILTER>("4", "ABCDE\r\nF", "ABCDE\nF");
+ testFilteredOutputStreamHelper<FILTER>("5", "ABCDE\r\nF", "ABCDE\r\nF");
+ testFilteredOutputStreamHelper<FILTER>("6", "\r\n\r\n\r\n", "\n\n\n");
+ testFilteredOutputStreamHelper<FILTER>("7", "\r\n\r\n\r\n", "\r\r\n\n");
+ testFilteredOutputStreamHelper<FILTER>("8", "\r\n\r\n\r\n\r\n", "\r\r\r\r");
+ testFilteredOutputStreamHelper<FILTER>("9", "\r\n\r\n\r\n\r\n", "\n\n\n\n");
+ testFilteredOutputStreamHelper<FILTER>("10", "\r\n\r\n\r\n", "\r\n\n\n");
+ testFilteredOutputStreamHelper<FILTER>("11", "\r\n\r\n\r\n\r\n", "\n\n\n\r\n");
+ }
+
+ void testLFToCRLFFilteredOutputStream_Edge()
+ {
+ typedef vmime::utility::LFToCRLFFilteredOutputStream FILTER;
+
+ testFilteredOutputStreamHelper<FILTER>("1", "\r\n\r\n", "\r", "\r");
+ testFilteredOutputStreamHelper<FILTER>("2", "\r\n\r\n", "\r", "\n\r");
+ testFilteredOutputStreamHelper<FILTER>("3", "ABC\r\n\r\n", "ABC\r", "\n\r");
+ testFilteredOutputStreamHelper<FILTER>("4", "ABC\r\n\r\n\r\n", "ABC\r", "\n\r", "\n\n");
+ testFilteredOutputStreamHelper<FILTER>("5", "\r\n\r\n", "\n", "\n");
+ testFilteredOutputStreamHelper<FILTER>("6", "\r\n\r\n", "\r\n\r\n");
+ testFilteredOutputStreamHelper<FILTER>("7", "\r\n\r\n", "\r\n\r", "\n");
+
+ testFilteredOutputStreamHelper<FILTER>("8", "A\r\nB\r\nC\r\nD", "A\rB", "\nC\r\nD");
+ testFilteredOutputStreamHelper<FILTER>("9", "\r\nA\r\nB\r\nC\r\nD", "\rA\r", "B\nC\r\nD");
+ testFilteredOutputStreamHelper<FILTER>("10", "\r\nA\r\nB\r\nC\r\nD", "\nA\r", "B\nC\r\nD");
+ testFilteredOutputStreamHelper<FILTER>("11", "\r\nA\r\nB\r\nC\r\nD\r\n", "\nA\rB", "\nC\r\nD\r");
+ }
+
VMIME_TEST_SUITE_END
diff --git a/vmime/utility/filteredStream.hpp b/vmime/utility/filteredStream.hpp
index b7ec010f..9dc24e5d 100644
--- a/vmime/utility/filteredStream.hpp
+++ b/vmime/utility/filteredStream.hpp
@@ -155,6 +155,32 @@ private:
};
+/** A filtered output stream which replaces CR or LF characters
+ * with CRLF sequences.
+ */
+
+class LFToCRLFFilteredOutputStream : public filteredOutputStream
+{
+public:
+
+ /** Construct a new filter for the specified output stream.
+ *
+ * @param os stream into which write filtered data
+ */
+ LFToCRLFFilteredOutputStream(outputStream& os);
+
+ outputStream& getNextOutputStream();
+
+ void write(const value_type* const data, const size_type count);
+ void flush();
+
+private:
+
+ outputStream& m_stream;
+ value_type m_previousChar;
+};
+
+
/** A filtered input stream which stops when a specified sequence
* is found (eof() method will return 'true').
*/