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 | |
18 | namespace Poco { |
19 | namespace Net { |
20 | |
21 | |
22 | MailStreamBuf::MailStreamBuf(std::istream& istr): |
23 | _pIstr(&istr), |
24 | _pOstr(0), |
25 | _state(ST_CR_LF) |
26 | { |
27 | } |
28 | |
29 | |
30 | MailStreamBuf::MailStreamBuf(std::ostream& ostr): |
31 | _pIstr(0), |
32 | _pOstr(&ostr), |
33 | _state(ST_CR_LF) |
34 | { |
35 | } |
36 | |
37 | |
38 | MailStreamBuf::~MailStreamBuf() |
39 | { |
40 | } |
41 | |
42 | |
43 | void 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 | |
57 | int 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 | |
80 | int 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 | |
124 | int 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 | |
168 | MailIOS::MailIOS(std::istream& istr): _buf(istr) |
169 | { |
170 | poco_ios_init(&_buf); |
171 | } |
172 | |
173 | |
174 | MailIOS::MailIOS(std::ostream& ostr): _buf(ostr) |
175 | { |
176 | poco_ios_init(&_buf); |
177 | } |
178 | |
179 | |
180 | MailIOS::~MailIOS() |
181 | { |
182 | } |
183 | |
184 | |
185 | void MailIOS::close() |
186 | { |
187 | _buf.close(); |
188 | } |
189 | |
190 | |
191 | MailStreamBuf* MailIOS::rdbuf() |
192 | { |
193 | return &_buf; |
194 | } |
195 | |
196 | |
197 | MailInputStream::MailInputStream(std::istream& istr): |
198 | MailIOS(istr), |
199 | std::istream(&_buf) |
200 | { |
201 | } |
202 | |
203 | |
204 | MailInputStream::~MailInputStream() |
205 | { |
206 | } |
207 | |
208 | |
209 | MailOutputStream::MailOutputStream(std::ostream& ostr): |
210 | MailIOS(ostr), |
211 | std::ostream(&_buf) |
212 | { |
213 | } |
214 | |
215 | |
216 | MailOutputStream::~MailOutputStream() |
217 | { |
218 | } |
219 | |
220 | |
221 | } } // namespace Poco::Net |
222 | |