aboutsummaryrefslogtreecommitdiffstats
path: root/src/utility/filteredStream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/utility/filteredStream.cpp')
-rw-r--r--src/utility/filteredStream.cpp123
1 files changed, 120 insertions, 3 deletions
diff --git a/src/utility/filteredStream.cpp b/src/utility/filteredStream.cpp
index d55e891e..c198c230 100644
--- a/src/utility/filteredStream.cpp
+++ b/src/utility/filteredStream.cpp
@@ -21,10 +21,99 @@
#include <algorithm>
+
namespace vmime {
namespace utility {
+// dotFilteredInputStream
+
+dotFilteredInputStream::dotFilteredInputStream(inputStream& is)
+ : m_stream(is)
+{
+}
+
+
+inputStream& dotFilteredInputStream::getPreviousInputStream()
+{
+ return (m_stream);
+}
+
+
+const bool dotFilteredInputStream::eof() const
+{
+ return (m_stream.eof());
+}
+
+
+void dotFilteredInputStream::reset()
+{
+ m_previousChar2 = '\0';
+ m_previousChar1 = '\0';
+
+ m_stream.reset();
+}
+
+
+const stream::size_type dotFilteredInputStream::read(value_type* const data, const size_type count)
+{
+ const stream::size_type read = m_stream.read(data, count);
+
+ const value_type* readPtr = data;
+ value_type* writePtr = data;
+
+ const value_type* end = data + read;
+
+ stream::size_type written = 0;
+
+ // Replace "\n.." with "\n."
+ while (readPtr < end)
+ {
+ if (*readPtr == '.')
+ {
+ const value_type prevChar2 =
+ (readPtr == data + 1 ? m_previousChar1 :
+ readPtr == data ? m_previousChar2 : *(readPtr - 2));
+ const value_type prevChar1 =
+ (readPtr == data ? m_previousChar1 : *(readPtr - 1));
+
+ if (prevChar2 == '\n' && prevChar1 == '.')
+ {
+ // Ignore last dot
+ }
+ else
+ {
+ *writePtr = *readPtr;
+
+ ++writePtr;
+ ++written;
+ }
+ }
+ else
+ {
+ *writePtr = *readPtr;
+
+ ++writePtr;
+ ++written;
+ }
+
+ ++readPtr;
+ }
+
+ m_previousChar2 = (read >= 2 ? data[read - 2] : m_previousChar1);
+ m_previousChar1 = (read >= 1 ? data[read - 1] : '\0');
+
+ return (written);
+}
+
+
+const stream::size_type dotFilteredInputStream::skip(const size_type /* count */)
+{
+ // Skipping bytes is not supported
+ return 0;
+}
+
+
// dotFilteredOutputStream
dotFilteredOutputStream::dotFilteredOutputStream(outputStream& os)
@@ -42,6 +131,9 @@ outputStream& dotFilteredOutputStream::getNextOutputStream()
void dotFilteredOutputStream::write
(const value_type* const data, const size_type count)
{
+ if (count == 0)
+ return;
+
const value_type* pos = data;
const value_type* end = data + count;
const value_type* start = data;
@@ -85,10 +177,25 @@ outputStream& CRLFToLFFilteredOutputStream::getNextOutputStream()
void CRLFToLFFilteredOutputStream::write
(const value_type* const data, const size_type count)
{
+ if (count == 0)
+ return;
+
const value_type* pos = data;
const value_type* end = data + count;
const value_type* start = data;
+ // Warning: if the whole buffer finishes with '\r', this
+ // last character will not be written back...
+ // TODO: add a finalize() method?
+ if (m_previousChar == '\r')
+ {
+ if (*pos != '\n')
+ {
+ m_stream.write("\r", 1); // write back \r
+ m_previousChar = *pos;
+ }
+ }
+
// Replace "\r\n" (CRLF) with "\n" (LF)
while ((pos = std::find(pos, end, '\n')) != end)
{
@@ -97,7 +204,9 @@ void CRLFToLFFilteredOutputStream::write
if (previousChar == '\r')
{
- m_stream.write(start, pos - 1 - data); // do not write \r
+ if (pos != data)
+ m_stream.write(start, pos - 1 - data); // do not write \r
+
m_stream.write("\n", 1);
start = pos + 1;
@@ -106,8 +215,16 @@ void CRLFToLFFilteredOutputStream::write
++pos;
}
- m_stream.write(start, end - start);
- m_previousChar = data[count - 1];
+ if (data[count - 1] == '\r')
+ {
+ m_stream.write(start, end - start - 1);
+ m_previousChar = '\r';
+ }
+ else
+ {
+ m_stream.write(start, end - start);
+ m_previousChar = data[count - 1];
+ }
}