1//
2// MailStream.cpp
3//
4// Library: Net
5// Package: Mail
6// Module: MailStream
7//
8// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/Net/MailStream.h"
16
17
18namespace Poco {
19namespace Net {
20
21
22MailStreamBuf::MailStreamBuf(std::istream& istr):
23 _pIstr(&istr),
24 _pOstr(0),
25 _state(ST_CR_LF)
26{
27}
28
29
30MailStreamBuf::MailStreamBuf(std::ostream& ostr):
31 _pIstr(0),
32 _pOstr(&ostr),
33 _state(ST_CR_LF)
34{
35}
36
37
38MailStreamBuf::~MailStreamBuf()
39{
40}
41
42
43void MailStreamBuf::close()
44{
45 if (_pOstr && _state != ST_CR_LF_DOT_CR_LF)
46 {
47 if (!_buffer.empty())
48 _pOstr->write(_buffer.data(), (std::streamsize) _buffer.length());
49 if (_state != ST_CR_LF)
50 _pOstr->write("\r\n", 2);
51 _pOstr->write(".\r\n", 3);
52 _state = ST_CR_LF_DOT_CR_LF;
53 }
54}
55
56
57int MailStreamBuf::readFromDevice()
58{
59 int c = std::char_traits<char>::eof();
60 if (!_buffer.empty())
61 {
62 c = _buffer[0];
63 _buffer.erase(0, 1);
64 }
65 else
66 {
67 c = readOne();
68 while (c != std::char_traits<char>::eof() && _state != ST_DATA && _state != ST_CR_LF_DOT_CR_LF)
69 c = readOne();
70 if (!_buffer.empty())
71 {
72 c = _buffer[0];
73 _buffer.erase(0, 1);
74 }
75 }
76 return c;
77}
78
79
80int MailStreamBuf::readOne()
81{
82 int c = std::char_traits<char>::eof();
83 if (_state != ST_CR_LF_DOT_CR_LF)
84 {
85 c = _pIstr->get();
86 switch (c)
87 {
88 case '\r':
89 if (_state == ST_CR_LF_DOT)
90 _state = ST_CR_LF_DOT_CR;
91 else
92 _state = ST_CR;
93 break;
94 case '\n':
95 if (_state == ST_CR)
96 _state = ST_CR_LF;
97 else if (_state == ST_CR_LF_DOT_CR)
98 _state = ST_CR_LF_DOT_CR_LF;
99 else
100 _state = ST_DATA;
101 break;
102 case '.':
103 if (_state == ST_CR_LF)
104 _state = ST_CR_LF_DOT;
105 else if (_state == ST_CR_LF_DOT)
106 _state = ST_CR_LF_DOT_DOT;
107 else
108 _state = ST_DATA;
109 break;
110 default:
111 _state = ST_DATA;
112 }
113 if (_state == ST_CR_LF_DOT_DOT)
114 _state = ST_DATA;
115 else if (_state == ST_CR_LF_DOT_CR_LF)
116 _buffer.resize(_buffer.size() - 2);
117 else if (c != std::char_traits<char>::eof())
118 _buffer += (char) c;
119 }
120 return c;
121}
122
123
124int MailStreamBuf::writeToDevice(char c)
125{
126 switch (c)
127 {
128 case '\r':
129 _state = ST_CR;
130 break;
131 case '\n':
132 if (_state == ST_CR)
133 _state = ST_CR_LF;
134 else
135 _state = ST_DATA;
136 break;
137 case '.':
138 if (_state == ST_CR_LF)
139 _state = ST_CR_LF_DOT;
140 else
141 _state = ST_DATA;
142 break;
143 default:
144 _state = ST_DATA;
145 }
146 if (_state == ST_DATA)
147 {
148 if (!_buffer.empty())
149 {
150 _pOstr->write(_buffer.data(), (std::streamsize) _buffer.length());
151 _buffer.clear();
152 }
153 _pOstr->put(c);
154 }
155 else if (_state == ST_CR_LF_DOT)
156 {
157 // buffer contains one or more CR-LF pairs
158 _pOstr->write(_buffer.data(), (std::streamsize) _buffer.length());
159 _pOstr->write("..", 2);
160 _state = ST_DATA;
161 _buffer.clear();
162 }
163 else _buffer += c;
164 return charToInt(c);
165}
166
167
168MailIOS::MailIOS(std::istream& istr): _buf(istr)
169{
170 poco_ios_init(&_buf);
171}
172
173
174MailIOS::MailIOS(std::ostream& ostr): _buf(ostr)
175{
176 poco_ios_init(&_buf);
177}
178
179
180MailIOS::~MailIOS()
181{
182}
183
184
185void MailIOS::close()
186{
187 _buf.close();
188}
189
190
191MailStreamBuf* MailIOS::rdbuf()
192{
193 return &_buf;
194}
195
196
197MailInputStream::MailInputStream(std::istream& istr):
198 MailIOS(istr),
199 std::istream(&_buf)
200{
201}
202
203
204MailInputStream::~MailInputStream()
205{
206}
207
208
209MailOutputStream::MailOutputStream(std::ostream& ostr):
210 MailIOS(ostr),
211 std::ostream(&_buf)
212{
213}
214
215
216MailOutputStream::~MailOutputStream()
217{
218}
219
220
221} } // namespace Poco::Net
222