~ubuntu-branches/ubuntu/gutsy/poco/gutsy

« back to all changes in this revision

Viewing changes to Net/src/MultipartReader.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Krzysztof Burghardt
  • Date: 2007-04-27 18:33:48 UTC
  • Revision ID: james.westby@ubuntu.com-20070427183348-xgnpct0qd6a2ip34
Tags: upstream-1.2.9
ImportĀ upstreamĀ versionĀ 1.2.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// MultipartReader.cpp
 
3
//
 
4
// $Id: //poco/1.2/Net/src/MultipartReader.cpp#2 $
 
5
//
 
6
// Library: Net
 
7
// Package: Messages
 
8
// Module:  MultipartReader
 
9
//
 
10
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
 
11
// and Contributors.
 
12
//
 
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:
 
19
// 
 
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.
 
26
// 
 
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.
 
34
//
 
35
 
 
36
 
 
37
#include "Poco/Net/MultipartReader.h"
 
38
#include "Poco/Net/MessageHeader.h"
 
39
#include "Poco/Net/NetException.h"
 
40
#include <ctype.h>
 
41
 
 
42
 
 
43
using Poco::BufferedStreamBuf;
 
44
 
 
45
 
 
46
namespace Poco {
 
47
namespace Net {
 
48
 
 
49
 
 
50
//
 
51
// MultipartStreamBuf
 
52
//
 
53
 
 
54
 
 
55
MultipartStreamBuf::MultipartStreamBuf(std::istream& istr, const std::string& boundary):
 
56
        BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in),
 
57
        _istr(istr),
 
58
        _boundary(boundary),
 
59
        _lastPart(false)
 
60
{
 
61
        poco_assert (!boundary.empty() && boundary.length() < STREAM_BUFFER_SIZE - 6);
 
62
}
 
63
 
 
64
 
 
65
MultipartStreamBuf::~MultipartStreamBuf()
 
66
{
 
67
}
 
68
 
 
69
 
 
70
int MultipartStreamBuf::readFromDevice(char* buffer, std::streamsize length)
 
71
{
 
72
        poco_assert_dbg (length >= _boundary.length() + 6);
 
73
 
 
74
        static const int eof = std::char_traits<char>::eof();
 
75
        int n  = 0;
 
76
        int ch = _istr.get();
 
77
        *buffer++ = (char) ch; ++n;
 
78
        if (ch == '\n' || ch == '\r' && _istr.peek() == '\n')
 
79
        {
 
80
                if (ch == '\r')
 
81
                {
 
82
                        ch = _istr.get(); // '\n'
 
83
                        *buffer++ = (char) ch; ++n;
 
84
                }
 
85
                ch = _istr.peek();
 
86
                if (ch == '\r' || ch == '\n') return n;
 
87
                *buffer++ = (char) _istr.get(); ++n;
 
88
                if (ch == '-' && _istr.peek() == '-')
 
89
                {
 
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();
 
94
                        ch = _istr.get();
 
95
                        *buffer++ = (char) ch; ++n;
 
96
                        while (it != end && ch == *it)
 
97
                        {
 
98
                                ++it;
 
99
                                ch = _istr.get();
 
100
                                *buffer++ = (char) ch; ++n;
 
101
                        }
 
102
                        if (it == end)
 
103
                        {
 
104
                                if (ch == '\n' || ch == '\r' && _istr.peek() == '\n')
 
105
                                {
 
106
                                        if (ch == '\r')
 
107
                                        {
 
108
                                                ch = _istr.get(); // '\n'
 
109
                                        }
 
110
                                        return 0;                                       
 
111
                                }
 
112
                                else if (ch == '-' && _istr.peek() == '-')
 
113
                                {
 
114
                                        ch = _istr.get(); // '-'
 
115
                                        _lastPart = true;
 
116
                                        return 0;
 
117
                                }
 
118
                        }
 
119
                }
 
120
        }
 
121
        ch = _istr.peek();
 
122
        while (ch != eof && ch != '\r' && ch != '\n' && n < length)
 
123
        {
 
124
                *buffer++ = (char) _istr.get(); ++n;
 
125
                ch = _istr.peek();
 
126
        }
 
127
        return n;
 
128
}
 
129
 
 
130
 
 
131
bool MultipartStreamBuf::lastPart() const
 
132
{
 
133
        return _lastPart;
 
134
}
 
135
 
 
136
 
 
137
//
 
138
// MultipartIOS
 
139
//
 
140
 
 
141
 
 
142
MultipartIOS::MultipartIOS(std::istream& istr, const std::string& boundary):
 
143
        _buf(istr, boundary)
 
144
{
 
145
        poco_ios_init(&_buf);
 
146
}
 
147
 
 
148
 
 
149
MultipartIOS::~MultipartIOS()
 
150
{
 
151
        _buf.sync();
 
152
}
 
153
 
 
154
 
 
155
MultipartStreamBuf* MultipartIOS::rdbuf()
 
156
{
 
157
        return &_buf;
 
158
}
 
159
 
 
160
 
 
161
bool MultipartIOS::lastPart() const
 
162
{
 
163
        return _buf.lastPart();
 
164
}
 
165
 
 
166
 
 
167
//
 
168
// MultipartInputStream
 
169
//
 
170
 
 
171
 
 
172
MultipartInputStream::MultipartInputStream(std::istream& istr, const std::string& boundary):
 
173
        MultipartIOS(istr, boundary),
 
174
        std::istream(&_buf)
 
175
{
 
176
}
 
177
 
 
178
 
 
179
MultipartInputStream::~MultipartInputStream()
 
180
{
 
181
}
 
182
 
 
183
 
 
184
//
 
185
// MultipartReader
 
186
//
 
187
 
 
188
 
 
189
MultipartReader::MultipartReader(std::istream& istr):
 
190
        _istr(istr),
 
191
        _pMPI(0)
 
192
{
 
193
}
 
194
 
 
195
 
 
196
MultipartReader::MultipartReader(std::istream& istr, const std::string& boundary):
 
197
        _istr(istr),
 
198
        _boundary(boundary),
 
199
        _pMPI(0)
 
200
{
 
201
}
 
202
 
 
203
 
 
204
MultipartReader::~MultipartReader()
 
205
{
 
206
        delete _pMPI;
 
207
}
 
208
 
 
209
 
 
210
void MultipartReader::nextPart(MessageHeader& messageHeader)
 
211
{
 
212
        if (!_pMPI)
 
213
        {
 
214
                if (_boundary.empty())
 
215
                        guessBoundary();
 
216
                else
 
217
                        findFirstBoundary();
 
218
        }
 
219
        else if (_pMPI->lastPart())
 
220
        {
 
221
                throw MultipartException("No more parts available");
 
222
        }
 
223
        parseHeader(messageHeader);
 
224
        delete _pMPI;
 
225
        _pMPI = new MultipartInputStream(_istr, _boundary);
 
226
}
 
227
 
 
228
 
 
229
bool MultipartReader::hasNextPart()
 
230
{
 
231
        return (!_pMPI || !_pMPI->lastPart()) && _istr.good();
 
232
}
 
233
 
 
234
        
 
235
std::istream& MultipartReader::stream() const
 
236
{
 
237
        poco_check_ptr (_pMPI);
 
238
        
 
239
        return *_pMPI;
 
240
}
 
241
 
 
242
 
 
243
const std::string& MultipartReader::boundary() const
 
244
{
 
245
        return _boundary;
 
246
}
 
247
 
 
248
 
 
249
void MultipartReader::findFirstBoundary()
 
250
{
 
251
        std::string expect("--");
 
252
        expect.append(_boundary);
 
253
        std::string line;
 
254
        line.reserve(expect.length());
 
255
        bool ok = true;
 
256
        do
 
257
        {
 
258
                ok = readLine(line, expect.length());
 
259
        }
 
260
        while (ok && line != expect);
 
261
 
 
262
        if (!ok) throw MultipartException("No boundary line found");
 
263
}
 
264
 
 
265
 
 
266
void MultipartReader::guessBoundary()
 
267
{
 
268
        static const int eof = std::char_traits<char>::eof();
 
269
        int ch = _istr.get();
 
270
        while (isspace(ch))
 
271
                ch = _istr.get();
 
272
        if (ch == '-' && _istr.peek() == '-')
 
273
        {
 
274
                _istr.get();
 
275
                ch = _istr.peek();
 
276
                while (ch != eof && ch != '\r' && ch != '\n')
 
277
                {
 
278
                        _boundary += (char) _istr.get();
 
279
                        ch = _istr.peek();
 
280
                }
 
281
                if (ch == '\r' || ch == '\n')
 
282
                        ch = _istr.get();
 
283
                if (_istr.peek() == '\n')
 
284
                        _istr.get();
 
285
        }
 
286
        else throw MultipartException("No boundary line found");
 
287
}
 
288
 
 
289
 
 
290
void MultipartReader::parseHeader(MessageHeader& messageHeader)
 
291
{
 
292
        messageHeader.clear();
 
293
        messageHeader.read(_istr);
 
294
        int ch = _istr.get();
 
295
        if (ch == '\r' && _istr.peek() == '\n') ch = _istr.get();
 
296
}
 
297
 
 
298
 
 
299
bool MultipartReader::readLine(std::string& line, std::string::size_type n)
 
300
{
 
301
        static const int eof = std::char_traits<char>::eof();
 
302
 
 
303
        line.clear();
 
304
        int ch = _istr.peek();
 
305
        while (ch != eof && ch != '\r' && ch != '\n')
 
306
        {
 
307
                ch = (char) _istr.get();
 
308
                if (line.length() < n) line += ch;
 
309
                ch = _istr.peek();
 
310
        }
 
311
        if (ch != eof) _istr.get();
 
312
        if (ch == '\r' && _istr.peek() == '\n') _istr.get();
 
313
        return ch != eof;
 
314
}
 
315
 
 
316
 
 
317
} } // namespace Poco::Net