4
// $Id: //poco/1.2/Net/src/MultipartReader.cpp#2 $
8
// Module: MultipartReader
10
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
13
// Permission is hereby granted, free of charge, to any person or organization
14
// obtaining a copy of the software and accompanying documentation covered by
15
// this license (the "Software") to use, reproduce, display, distribute,
16
// execute, and transmit the Software, and to prepare derivative works of the
17
// Software, and to permit third-parties to whom the Software is furnished to
18
// do so, all subject to the following:
20
// The copyright notices in the Software and this entire statement, including
21
// the above license grant, this restriction and the following disclaimer,
22
// must be included in all copies of the Software, in whole or in part, and
23
// all derivative works of the Software, unless such copies or derivative
24
// works are solely in the form of machine-executable object code generated by
25
// a source language processor.
27
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
30
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
31
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
32
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
33
// DEALINGS IN THE SOFTWARE.
37
#include "Poco/Net/MultipartReader.h"
38
#include "Poco/Net/MessageHeader.h"
39
#include "Poco/Net/NetException.h"
43
using Poco::BufferedStreamBuf;
55
MultipartStreamBuf::MultipartStreamBuf(std::istream& istr, const std::string& boundary):
56
BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in),
61
poco_assert (!boundary.empty() && boundary.length() < STREAM_BUFFER_SIZE - 6);
65
MultipartStreamBuf::~MultipartStreamBuf()
70
int MultipartStreamBuf::readFromDevice(char* buffer, std::streamsize length)
72
poco_assert_dbg (length >= _boundary.length() + 6);
74
static const int eof = std::char_traits<char>::eof();
77
*buffer++ = (char) ch; ++n;
78
if (ch == '\n' || ch == '\r' && _istr.peek() == '\n')
82
ch = _istr.get(); // '\n'
83
*buffer++ = (char) ch; ++n;
86
if (ch == '\r' || ch == '\n') return n;
87
*buffer++ = (char) _istr.get(); ++n;
88
if (ch == '-' && _istr.peek() == '-')
90
ch = _istr.get(); // '-'
91
*buffer++ = (char) ch; ++n;
92
std::string::const_iterator it = _boundary.begin();
93
std::string::const_iterator end = _boundary.end();
95
*buffer++ = (char) ch; ++n;
96
while (it != end && ch == *it)
100
*buffer++ = (char) ch; ++n;
104
if (ch == '\n' || ch == '\r' && _istr.peek() == '\n')
108
ch = _istr.get(); // '\n'
112
else if (ch == '-' && _istr.peek() == '-')
114
ch = _istr.get(); // '-'
122
while (ch != eof && ch != '\r' && ch != '\n' && n < length)
124
*buffer++ = (char) _istr.get(); ++n;
131
bool MultipartStreamBuf::lastPart() const
142
MultipartIOS::MultipartIOS(std::istream& istr, const std::string& boundary):
145
poco_ios_init(&_buf);
149
MultipartIOS::~MultipartIOS()
155
MultipartStreamBuf* MultipartIOS::rdbuf()
161
bool MultipartIOS::lastPart() const
163
return _buf.lastPart();
168
// MultipartInputStream
172
MultipartInputStream::MultipartInputStream(std::istream& istr, const std::string& boundary):
173
MultipartIOS(istr, boundary),
179
MultipartInputStream::~MultipartInputStream()
189
MultipartReader::MultipartReader(std::istream& istr):
196
MultipartReader::MultipartReader(std::istream& istr, const std::string& boundary):
204
MultipartReader::~MultipartReader()
210
void MultipartReader::nextPart(MessageHeader& messageHeader)
214
if (_boundary.empty())
219
else if (_pMPI->lastPart())
221
throw MultipartException("No more parts available");
223
parseHeader(messageHeader);
225
_pMPI = new MultipartInputStream(_istr, _boundary);
229
bool MultipartReader::hasNextPart()
231
return (!_pMPI || !_pMPI->lastPart()) && _istr.good();
235
std::istream& MultipartReader::stream() const
237
poco_check_ptr (_pMPI);
243
const std::string& MultipartReader::boundary() const
249
void MultipartReader::findFirstBoundary()
251
std::string expect("--");
252
expect.append(_boundary);
254
line.reserve(expect.length());
258
ok = readLine(line, expect.length());
260
while (ok && line != expect);
262
if (!ok) throw MultipartException("No boundary line found");
266
void MultipartReader::guessBoundary()
268
static const int eof = std::char_traits<char>::eof();
269
int ch = _istr.get();
272
if (ch == '-' && _istr.peek() == '-')
276
while (ch != eof && ch != '\r' && ch != '\n')
278
_boundary += (char) _istr.get();
281
if (ch == '\r' || ch == '\n')
283
if (_istr.peek() == '\n')
286
else throw MultipartException("No boundary line found");
290
void MultipartReader::parseHeader(MessageHeader& messageHeader)
292
messageHeader.clear();
293
messageHeader.read(_istr);
294
int ch = _istr.get();
295
if (ch == '\r' && _istr.peek() == '\n') ch = _istr.get();
299
bool MultipartReader::readLine(std::string& line, std::string::size_type n)
301
static const int eof = std::char_traits<char>::eof();
304
int ch = _istr.peek();
305
while (ch != eof && ch != '\r' && ch != '\n')
307
ch = (char) _istr.get();
308
if (line.length() < n) line += ch;
311
if (ch != eof) _istr.get();
312
if (ch == '\r' && _istr.peek() == '\n') _istr.get();
317
} } // namespace Poco::Net