diff options
| author | orivej <[email protected]> | 2022-02-10 16:44:49 +0300 |
|---|---|---|
| committer | Daniil Cherednik <[email protected]> | 2022-02-10 16:44:49 +0300 |
| commit | 718c552901d703c502ccbefdfc3c9028d608b947 (patch) | |
| tree | 46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/libs/poco/Net/src/HTMLForm.cpp | |
| parent | e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff) | |
Restoring authorship annotation for <[email protected]>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/poco/Net/src/HTMLForm.cpp')
| -rw-r--r-- | contrib/libs/poco/Net/src/HTMLForm.cpp | 936 |
1 files changed, 468 insertions, 468 deletions
diff --git a/contrib/libs/poco/Net/src/HTMLForm.cpp b/contrib/libs/poco/Net/src/HTMLForm.cpp index 0518bdddd6d..65defbe0144 100644 --- a/contrib/libs/poco/Net/src/HTMLForm.cpp +++ b/contrib/libs/poco/Net/src/HTMLForm.cpp @@ -1,468 +1,468 @@ -// -// HTMLForm.cpp -// -// Library: Net -// Package: HTML -// Module: HTMLForm -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTMLForm.h" -#include "Poco/Net/HTTPRequest.h" -#include "Poco/Net/PartSource.h" -#include "Poco/Net/PartHandler.h" -#include "Poco/Net/MultipartWriter.h" -#include "Poco/Net/MultipartReader.h" -#include "Poco/Net/NullPartHandler.h" -#include "Poco/Net/NetException.h" -#include "Poco/NullStream.h" -#include "Poco/CountingStream.h" -#include "Poco/StreamCopier.h" -#include "Poco/URI.h" -#include "Poco/String.h" -#include "Poco/CountingStream.h" -#include "Poco/UTF8String.h" -#include <sstream> - - -using Poco::NullInputStream; -using Poco::StreamCopier; -using Poco::SyntaxException; -using Poco::URI; -using Poco::icompare; - - -namespace Poco { -namespace Net { - - -const std::string HTMLForm::ENCODING_URL = "application/x-www-form-urlencoded"; -const std::string HTMLForm::ENCODING_MULTIPART = "multipart/form-data"; -const int HTMLForm::UNKNOWN_CONTENT_LENGTH = -1; - - -class HTMLFormCountingOutputStream: public CountingOutputStream -{ -public: - HTMLFormCountingOutputStream(): - _valid(true) - { - } - - bool isValid() const - { - return _valid; - } - - void setValid(bool v) - { - _valid = v; - } - -private: - bool _valid; -}; - - -HTMLForm::HTMLForm(): - _fieldLimit(DFL_FIELD_LIMIT), - _valueLengthLimit(DFL_MAX_VALUE_LENGTH), - _encoding(ENCODING_URL) -{ -} - - -HTMLForm::HTMLForm(const std::string& encoding): - _fieldLimit(DFL_FIELD_LIMIT), - _valueLengthLimit(DFL_MAX_VALUE_LENGTH), - _encoding(encoding) -{ -} - - -HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler): - _fieldLimit(DFL_FIELD_LIMIT), - _valueLengthLimit(DFL_MAX_VALUE_LENGTH) -{ - load(request, requestBody, handler); -} - - -HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody): - _fieldLimit(DFL_FIELD_LIMIT), - _valueLengthLimit(DFL_MAX_VALUE_LENGTH) -{ - load(request, requestBody); -} - - -HTMLForm::HTMLForm(const HTTPRequest& request): - _fieldLimit(DFL_FIELD_LIMIT), - _valueLengthLimit(DFL_MAX_VALUE_LENGTH) -{ - load(request); -} - - -HTMLForm::~HTMLForm() -{ - for (PartVec::iterator it = _parts.begin(); it != _parts.end(); ++it) - { - delete it->pSource; - } -} - - -void HTMLForm::setEncoding(const std::string& encoding) -{ - _encoding = encoding; -} - - -void HTMLForm::addPart(const std::string& name, PartSource* pSource) -{ - poco_check_ptr (pSource); - - Part part; - part.name = name; - part.pSource = pSource; - _parts.push_back(part); -} - - -void HTMLForm::load(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler) -{ - clear(); - - URI uri(request.getURI()); - const std::string& query = uri.getRawQuery(); - if (!query.empty()) - { - std::istringstream istr(query); - readUrl(istr); - } - - if (request.getMethod() == HTTPRequest::HTTP_POST || request.getMethod() == HTTPRequest::HTTP_PUT) - { - std::string mediaType; - NameValueCollection params; - MessageHeader::splitParameters(request.getContentType(), mediaType, params); - _encoding = mediaType; - if (_encoding == ENCODING_MULTIPART) - { - _boundary = params["boundary"]; - readMultipart(requestBody, handler); - } - else - { - readUrl(requestBody); - } - } -} - - -void HTMLForm::load(const HTTPRequest& request, std::istream& requestBody) -{ - NullPartHandler nah; - load(request, requestBody, nah); -} - - -void HTMLForm::load(const HTTPRequest& request) -{ - NullPartHandler nah; - NullInputStream nis; - load(request, nis, nah); -} - - -void HTMLForm::read(std::istream& istr, PartHandler& handler) -{ - if (_encoding == ENCODING_URL) - readUrl(istr); - else - readMultipart(istr, handler); -} - - -void HTMLForm::read(std::istream& istr) -{ - readUrl(istr); -} - - -void HTMLForm::read(const std::string& queryString) -{ - std::istringstream istr(queryString); - readUrl(istr); -} - - -void HTMLForm::prepareSubmit(HTTPRequest& request, int options) -{ - if (request.getMethod() == HTTPRequest::HTTP_POST || request.getMethod() == HTTPRequest::HTTP_PUT) - { - if (_encoding == ENCODING_URL) - { - request.setContentType(_encoding); - request.setChunkedTransferEncoding(false); - Poco::CountingOutputStream ostr; - writeUrl(ostr); - request.setContentLength(ostr.chars()); - } - else - { - _boundary = MultipartWriter::createBoundary(); - std::string ct(_encoding); - ct.append("; boundary=\""); - ct.append(_boundary); - ct.append("\""); - request.setContentType(ct); - } - if (request.getVersion() == HTTPMessage::HTTP_1_0) - { - request.setKeepAlive(false); - request.setChunkedTransferEncoding(false); - } - else if (_encoding != ENCODING_URL && (options & OPT_USE_CONTENT_LENGTH) == 0) - { - request.setChunkedTransferEncoding(true); - } - if (!request.getChunkedTransferEncoding() && !request.hasContentLength()) - { - request.setContentLength(calculateContentLength()); - } - } - else - { - std::string uri = request.getURI(); - std::ostringstream ostr; - writeUrl(ostr); - uri.append("?"); - uri.append(ostr.str()); - request.setURI(uri); - } -} - - -std::streamsize HTMLForm::calculateContentLength() -{ - if (_encoding == ENCODING_MULTIPART && _boundary.empty()) - throw HTMLFormException("Form must be prepared"); - - HTMLFormCountingOutputStream c; - write(c); - if (c.isValid()) - return c.chars(); - else - return UNKNOWN_CONTENT_LENGTH; -} - - -void HTMLForm::write(std::ostream& ostr, const std::string& boundary) -{ - if (_encoding == ENCODING_URL) - { - writeUrl(ostr); - } - else - { - _boundary = boundary; - writeMultipart(ostr); - } -} - - -void HTMLForm::write(std::ostream& ostr) -{ - if (_encoding == ENCODING_URL) - writeUrl(ostr); - else - writeMultipart(ostr); -} - - -void HTMLForm::readUrl(std::istream& istr) -{ - static const int eof = std::char_traits<char>::eof(); - - int fields = 0; - int ch = istr.get(); - bool isFirst = true; - while (ch != eof) - { - if (_fieldLimit > 0 && fields == _fieldLimit) - throw HTMLFormException("Too many form fields"); - std::string name; - std::string value; - while (ch != eof && ch != '=' && ch != '&') - { - if (ch == '+') ch = ' '; - if (name.size() < MAX_NAME_LENGTH) - name += (char) ch; - else - throw HTMLFormException("Field name too long"); - ch = istr.get(); - } - if (ch == '=') - { - ch = istr.get(); - while (ch != eof && ch != '&') - { - if (ch == '+') ch = ' '; - if (value.size() < _valueLengthLimit) - value += (char) ch; - else - throw HTMLFormException("Field value too long"); - ch = istr.get(); - } - } - // remove UTF-8 byte order mark from first name, if present - if (isFirst) - { - UTF8::removeBOM(name); - } - std::string decodedName; - std::string decodedValue; - URI::decode(name, decodedName); - URI::decode(value, decodedValue); - add(decodedName, decodedValue); - ++fields; - if (ch == '&') ch = istr.get(); - isFirst = false; - } -} - - -void HTMLForm::readMultipart(std::istream& istr, PartHandler& handler) -{ - static const int eof = std::char_traits<char>::eof(); - - int fields = 0; - MultipartReader reader(istr, _boundary); - while (reader.hasNextPart()) - { - if (_fieldLimit > 0 && fields == _fieldLimit) - throw HTMLFormException("Too many form fields"); - MessageHeader header; - reader.nextPart(header); - std::string disp; - NameValueCollection params; - if (header.has("Content-Disposition")) - { - std::string cd = header.get("Content-Disposition"); - MessageHeader::splitParameters(cd, disp, params); - } - if (params.has("filename")) - { - handler.handlePart(header, reader.stream()); - // Ensure that the complete part has been read. - while (reader.stream().good()) reader.stream().get(); - } - else - { - std::string name = params["name"]; - std::string value; - std::istream& input = reader.stream(); - int ch = istr.get(); - while (ch != eof) - { - if (value.size() < _valueLengthLimit) - value += (char) ch; - else - throw HTMLFormException("Field value too long"); - ch = input.get(); - } - add(name, value); - } - ++fields; - } -} - - -void HTMLForm::writeUrl(std::ostream& ostr) -{ - for (NameValueCollection::ConstIterator it = begin(); it != end(); ++it) - { - if (it != begin()) ostr << "&"; - std::string name; - URI::encode(it->first, "!?#/'\",;:$&()[]*+=@", name); - std::string value; - URI::encode(it->second, "!?#/'\",;:$&()[]*+=@", value); - ostr << name << "=" << value; - } -} - - -void HTMLForm::writeMultipart(std::ostream& ostr) -{ - HTMLFormCountingOutputStream* pCountingOutputStream(dynamic_cast<HTMLFormCountingOutputStream*>(&ostr)); - - MultipartWriter writer(ostr, _boundary); - for (NameValueCollection::ConstIterator it = begin(); it != end(); ++it) - { - MessageHeader header; - std::string disp("form-data; name=\""); - disp.append(it->first); - disp.append("\""); - header.set("Content-Disposition", disp); - writer.nextPart(header); - ostr << it->second; - } - for (PartVec::iterator ita = _parts.begin(); ita != _parts.end(); ++ita) - { - MessageHeader header(ita->pSource->headers()); - std::string disp("form-data; name=\""); - disp.append(ita->name); - disp.append("\""); - std::string filename = ita->pSource->filename(); - if (!filename.empty()) - { - disp.append("; filename=\""); - disp.append(filename); - disp.append("\""); - } - header.set("Content-Disposition", disp); - header.set("Content-Type", ita->pSource->mediaType()); - writer.nextPart(header); - if (pCountingOutputStream) - { - // count only, don't move stream position - std::streamsize partlen = ita->pSource->getContentLength(); - if (partlen != PartSource::UNKNOWN_CONTENT_LENGTH) - pCountingOutputStream->addChars(static_cast<int>(partlen)); - else - pCountingOutputStream->setValid(false); - } - else - { - StreamCopier::copyStream(ita->pSource->stream(), ostr); - } - } - writer.close(); - _boundary = writer.boundary(); -} - - -void HTMLForm::setFieldLimit(int limit) -{ - poco_assert (limit >= 0); - - _fieldLimit = limit; -} - - -void HTMLForm::setValueLengthLimit(int limit) -{ - poco_assert (limit >= 0); - - _valueLengthLimit = limit; -} - - -} } // namespace Poco::Net +// +// HTMLForm.cpp +// +// Library: Net +// Package: HTML +// Module: HTMLForm +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTMLForm.h" +#include "Poco/Net/HTTPRequest.h" +#include "Poco/Net/PartSource.h" +#include "Poco/Net/PartHandler.h" +#include "Poco/Net/MultipartWriter.h" +#include "Poco/Net/MultipartReader.h" +#include "Poco/Net/NullPartHandler.h" +#include "Poco/Net/NetException.h" +#include "Poco/NullStream.h" +#include "Poco/CountingStream.h" +#include "Poco/StreamCopier.h" +#include "Poco/URI.h" +#include "Poco/String.h" +#include "Poco/CountingStream.h" +#include "Poco/UTF8String.h" +#include <sstream> + + +using Poco::NullInputStream; +using Poco::StreamCopier; +using Poco::SyntaxException; +using Poco::URI; +using Poco::icompare; + + +namespace Poco { +namespace Net { + + +const std::string HTMLForm::ENCODING_URL = "application/x-www-form-urlencoded"; +const std::string HTMLForm::ENCODING_MULTIPART = "multipart/form-data"; +const int HTMLForm::UNKNOWN_CONTENT_LENGTH = -1; + + +class HTMLFormCountingOutputStream: public CountingOutputStream +{ +public: + HTMLFormCountingOutputStream(): + _valid(true) + { + } + + bool isValid() const + { + return _valid; + } + + void setValid(bool v) + { + _valid = v; + } + +private: + bool _valid; +}; + + +HTMLForm::HTMLForm(): + _fieldLimit(DFL_FIELD_LIMIT), + _valueLengthLimit(DFL_MAX_VALUE_LENGTH), + _encoding(ENCODING_URL) +{ +} + + +HTMLForm::HTMLForm(const std::string& encoding): + _fieldLimit(DFL_FIELD_LIMIT), + _valueLengthLimit(DFL_MAX_VALUE_LENGTH), + _encoding(encoding) +{ +} + + +HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler): + _fieldLimit(DFL_FIELD_LIMIT), + _valueLengthLimit(DFL_MAX_VALUE_LENGTH) +{ + load(request, requestBody, handler); +} + + +HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody): + _fieldLimit(DFL_FIELD_LIMIT), + _valueLengthLimit(DFL_MAX_VALUE_LENGTH) +{ + load(request, requestBody); +} + + +HTMLForm::HTMLForm(const HTTPRequest& request): + _fieldLimit(DFL_FIELD_LIMIT), + _valueLengthLimit(DFL_MAX_VALUE_LENGTH) +{ + load(request); +} + + +HTMLForm::~HTMLForm() +{ + for (PartVec::iterator it = _parts.begin(); it != _parts.end(); ++it) + { + delete it->pSource; + } +} + + +void HTMLForm::setEncoding(const std::string& encoding) +{ + _encoding = encoding; +} + + +void HTMLForm::addPart(const std::string& name, PartSource* pSource) +{ + poco_check_ptr (pSource); + + Part part; + part.name = name; + part.pSource = pSource; + _parts.push_back(part); +} + + +void HTMLForm::load(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler) +{ + clear(); + + URI uri(request.getURI()); + const std::string& query = uri.getRawQuery(); + if (!query.empty()) + { + std::istringstream istr(query); + readUrl(istr); + } + + if (request.getMethod() == HTTPRequest::HTTP_POST || request.getMethod() == HTTPRequest::HTTP_PUT) + { + std::string mediaType; + NameValueCollection params; + MessageHeader::splitParameters(request.getContentType(), mediaType, params); + _encoding = mediaType; + if (_encoding == ENCODING_MULTIPART) + { + _boundary = params["boundary"]; + readMultipart(requestBody, handler); + } + else + { + readUrl(requestBody); + } + } +} + + +void HTMLForm::load(const HTTPRequest& request, std::istream& requestBody) +{ + NullPartHandler nah; + load(request, requestBody, nah); +} + + +void HTMLForm::load(const HTTPRequest& request) +{ + NullPartHandler nah; + NullInputStream nis; + load(request, nis, nah); +} + + +void HTMLForm::read(std::istream& istr, PartHandler& handler) +{ + if (_encoding == ENCODING_URL) + readUrl(istr); + else + readMultipart(istr, handler); +} + + +void HTMLForm::read(std::istream& istr) +{ + readUrl(istr); +} + + +void HTMLForm::read(const std::string& queryString) +{ + std::istringstream istr(queryString); + readUrl(istr); +} + + +void HTMLForm::prepareSubmit(HTTPRequest& request, int options) +{ + if (request.getMethod() == HTTPRequest::HTTP_POST || request.getMethod() == HTTPRequest::HTTP_PUT) + { + if (_encoding == ENCODING_URL) + { + request.setContentType(_encoding); + request.setChunkedTransferEncoding(false); + Poco::CountingOutputStream ostr; + writeUrl(ostr); + request.setContentLength(ostr.chars()); + } + else + { + _boundary = MultipartWriter::createBoundary(); + std::string ct(_encoding); + ct.append("; boundary=\""); + ct.append(_boundary); + ct.append("\""); + request.setContentType(ct); + } + if (request.getVersion() == HTTPMessage::HTTP_1_0) + { + request.setKeepAlive(false); + request.setChunkedTransferEncoding(false); + } + else if (_encoding != ENCODING_URL && (options & OPT_USE_CONTENT_LENGTH) == 0) + { + request.setChunkedTransferEncoding(true); + } + if (!request.getChunkedTransferEncoding() && !request.hasContentLength()) + { + request.setContentLength(calculateContentLength()); + } + } + else + { + std::string uri = request.getURI(); + std::ostringstream ostr; + writeUrl(ostr); + uri.append("?"); + uri.append(ostr.str()); + request.setURI(uri); + } +} + + +std::streamsize HTMLForm::calculateContentLength() +{ + if (_encoding == ENCODING_MULTIPART && _boundary.empty()) + throw HTMLFormException("Form must be prepared"); + + HTMLFormCountingOutputStream c; + write(c); + if (c.isValid()) + return c.chars(); + else + return UNKNOWN_CONTENT_LENGTH; +} + + +void HTMLForm::write(std::ostream& ostr, const std::string& boundary) +{ + if (_encoding == ENCODING_URL) + { + writeUrl(ostr); + } + else + { + _boundary = boundary; + writeMultipart(ostr); + } +} + + +void HTMLForm::write(std::ostream& ostr) +{ + if (_encoding == ENCODING_URL) + writeUrl(ostr); + else + writeMultipart(ostr); +} + + +void HTMLForm::readUrl(std::istream& istr) +{ + static const int eof = std::char_traits<char>::eof(); + + int fields = 0; + int ch = istr.get(); + bool isFirst = true; + while (ch != eof) + { + if (_fieldLimit > 0 && fields == _fieldLimit) + throw HTMLFormException("Too many form fields"); + std::string name; + std::string value; + while (ch != eof && ch != '=' && ch != '&') + { + if (ch == '+') ch = ' '; + if (name.size() < MAX_NAME_LENGTH) + name += (char) ch; + else + throw HTMLFormException("Field name too long"); + ch = istr.get(); + } + if (ch == '=') + { + ch = istr.get(); + while (ch != eof && ch != '&') + { + if (ch == '+') ch = ' '; + if (value.size() < _valueLengthLimit) + value += (char) ch; + else + throw HTMLFormException("Field value too long"); + ch = istr.get(); + } + } + // remove UTF-8 byte order mark from first name, if present + if (isFirst) + { + UTF8::removeBOM(name); + } + std::string decodedName; + std::string decodedValue; + URI::decode(name, decodedName); + URI::decode(value, decodedValue); + add(decodedName, decodedValue); + ++fields; + if (ch == '&') ch = istr.get(); + isFirst = false; + } +} + + +void HTMLForm::readMultipart(std::istream& istr, PartHandler& handler) +{ + static const int eof = std::char_traits<char>::eof(); + + int fields = 0; + MultipartReader reader(istr, _boundary); + while (reader.hasNextPart()) + { + if (_fieldLimit > 0 && fields == _fieldLimit) + throw HTMLFormException("Too many form fields"); + MessageHeader header; + reader.nextPart(header); + std::string disp; + NameValueCollection params; + if (header.has("Content-Disposition")) + { + std::string cd = header.get("Content-Disposition"); + MessageHeader::splitParameters(cd, disp, params); + } + if (params.has("filename")) + { + handler.handlePart(header, reader.stream()); + // Ensure that the complete part has been read. + while (reader.stream().good()) reader.stream().get(); + } + else + { + std::string name = params["name"]; + std::string value; + std::istream& input = reader.stream(); + int ch = istr.get(); + while (ch != eof) + { + if (value.size() < _valueLengthLimit) + value += (char) ch; + else + throw HTMLFormException("Field value too long"); + ch = input.get(); + } + add(name, value); + } + ++fields; + } +} + + +void HTMLForm::writeUrl(std::ostream& ostr) +{ + for (NameValueCollection::ConstIterator it = begin(); it != end(); ++it) + { + if (it != begin()) ostr << "&"; + std::string name; + URI::encode(it->first, "!?#/'\",;:$&()[]*+=@", name); + std::string value; + URI::encode(it->second, "!?#/'\",;:$&()[]*+=@", value); + ostr << name << "=" << value; + } +} + + +void HTMLForm::writeMultipart(std::ostream& ostr) +{ + HTMLFormCountingOutputStream* pCountingOutputStream(dynamic_cast<HTMLFormCountingOutputStream*>(&ostr)); + + MultipartWriter writer(ostr, _boundary); + for (NameValueCollection::ConstIterator it = begin(); it != end(); ++it) + { + MessageHeader header; + std::string disp("form-data; name=\""); + disp.append(it->first); + disp.append("\""); + header.set("Content-Disposition", disp); + writer.nextPart(header); + ostr << it->second; + } + for (PartVec::iterator ita = _parts.begin(); ita != _parts.end(); ++ita) + { + MessageHeader header(ita->pSource->headers()); + std::string disp("form-data; name=\""); + disp.append(ita->name); + disp.append("\""); + std::string filename = ita->pSource->filename(); + if (!filename.empty()) + { + disp.append("; filename=\""); + disp.append(filename); + disp.append("\""); + } + header.set("Content-Disposition", disp); + header.set("Content-Type", ita->pSource->mediaType()); + writer.nextPart(header); + if (pCountingOutputStream) + { + // count only, don't move stream position + std::streamsize partlen = ita->pSource->getContentLength(); + if (partlen != PartSource::UNKNOWN_CONTENT_LENGTH) + pCountingOutputStream->addChars(static_cast<int>(partlen)); + else + pCountingOutputStream->setValid(false); + } + else + { + StreamCopier::copyStream(ita->pSource->stream(), ostr); + } + } + writer.close(); + _boundary = writer.boundary(); +} + + +void HTMLForm::setFieldLimit(int limit) +{ + poco_assert (limit >= 0); + + _fieldLimit = limit; +} + + +void HTMLForm::setValueLengthLimit(int limit) +{ + poco_assert (limit >= 0); + + _valueLengthLimit = limit; +} + + +} } // namespace Poco::Net |
