| 189 | |
| 190 | |
| 191 | void HTMLForm::readMultipart(ReadBuffer & in_, PartHandler & handler) |
| 192 | { |
| 193 | /// Assume there is always a boundary provided. |
| 194 | chassert(!boundary.empty()); |
| 195 | |
| 196 | size_t fields = 0; |
| 197 | MultipartReadBuffer in(in_, boundary); |
| 198 | |
| 199 | if (!in.skipToNextBoundary()) |
| 200 | throw Poco::Net::HTMLFormException("No boundary line found"); |
| 201 | |
| 202 | /// Read each part until next boundary (or last boundary) |
| 203 | while (!in.eof()) |
| 204 | { |
| 205 | if (max_fields_number && fields > max_fields_number) |
| 206 | throw Poco::Net::HTMLFormException("Too many form fields"); |
| 207 | |
| 208 | Poco::Net::MessageHeader header; |
| 209 | readHeaders(header, in, max_fields_number, max_field_name_size, max_field_value_size, max_request_header_size); |
| 210 | skipToNextLineOrEOF(in); |
| 211 | |
| 212 | NameValueCollection params; |
| 213 | if (header.has("Content-Disposition")) |
| 214 | { |
| 215 | std::string unused; |
| 216 | Poco::Net::MessageHeader::splitParameters(header.get("Content-Disposition"), unused, params); |
| 217 | } |
| 218 | |
| 219 | if (params.has("filename")) |
| 220 | handler.handlePart(header, in); |
| 221 | else |
| 222 | { |
| 223 | std::string name = params["name"]; |
| 224 | std::string value; |
| 225 | char ch = 0; |
| 226 | |
| 227 | while (in.read(ch)) |
| 228 | { |
| 229 | if (value.size() > max_field_value_size) |
| 230 | throw Poco::Net::HTMLFormException("Field value too long"); |
| 231 | value += ch; |
| 232 | } |
| 233 | |
| 234 | add(name, value); |
| 235 | } |
| 236 | |
| 237 | ++fields; |
| 238 | |
| 239 | /// If we already encountered EOF for the buffer |in|, it's possible that the next symbol is a start of boundary line. |
| 240 | /// In this case reading the boundary line will reset the EOF state, potentially breaking invariant of EOF idempotency - |
| 241 | /// if there is such invariant in the first place. |
| 242 | if (!in.skipToNextBoundary()) |
| 243 | break; |
| 244 | } |
| 245 | |
| 246 | /// It's important to check, because we could get "fake" EOF and incomplete request if a client suddenly died in the middle. |
| 247 | if (!in.isActualEOF()) |
| 248 | throw Exception(ErrorCodes::CANNOT_READ_ALL_DATA, "Unexpected EOF, " |
nothing calls this directly
no test coverage detected