mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-23 16:48:06 +02:00
Merge pull request #344 from RangelReale/htmlformcontentlength
HTMLForm Content-Length calculation
This commit is contained in:
@@ -69,6 +69,15 @@ public:
|
|||||||
int getCurrentLineNumber() const;
|
int getCurrentLineNumber() const;
|
||||||
/// Returns the current line number (same as lines()).
|
/// Returns the current line number (same as lines()).
|
||||||
|
|
||||||
|
void addChars(int chars);
|
||||||
|
/// Add to the total number of characters.
|
||||||
|
|
||||||
|
void addLines(int lines);
|
||||||
|
/// Add to the total number of lines.
|
||||||
|
|
||||||
|
void addPos(int pos);
|
||||||
|
/// Add to the number of characters on the current line.
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int readFromDevice();
|
int readFromDevice();
|
||||||
int writeToDevice(char c);
|
int writeToDevice(char c);
|
||||||
@@ -124,6 +133,15 @@ public:
|
|||||||
int getCurrentLineNumber() const;
|
int getCurrentLineNumber() const;
|
||||||
/// Returns the current line number (same as lines()).
|
/// Returns the current line number (same as lines()).
|
||||||
|
|
||||||
|
void addChars(int chars);
|
||||||
|
/// Add to the total number of characters.
|
||||||
|
|
||||||
|
void addLines(int lines);
|
||||||
|
/// Add to the total number of lines.
|
||||||
|
|
||||||
|
void addPos(int pos);
|
||||||
|
/// Add to the number of characters on the current line.
|
||||||
|
|
||||||
CountingStreamBuf* rdbuf();
|
CountingStreamBuf* rdbuf();
|
||||||
/// Returns a pointer to the underlying streambuf.
|
/// Returns a pointer to the underlying streambuf.
|
||||||
|
|
||||||
|
@@ -96,6 +96,24 @@ void CountingStreamBuf::setCurrentLineNumber(int line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CountingStreamBuf::addChars(int chars)
|
||||||
|
{
|
||||||
|
_chars += chars;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CountingStreamBuf::addLines(int lines)
|
||||||
|
{
|
||||||
|
_lines += lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CountingStreamBuf::addPos(int pos)
|
||||||
|
{
|
||||||
|
_pos += pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CountingIOS::CountingIOS()
|
CountingIOS::CountingIOS()
|
||||||
{
|
{
|
||||||
poco_ios_init(&_buf);
|
poco_ios_init(&_buf);
|
||||||
@@ -131,6 +149,24 @@ void CountingIOS::setCurrentLineNumber(int line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CountingIOS::addChars(int chars)
|
||||||
|
{
|
||||||
|
_buf.addChars(chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CountingIOS::addLines(int lines)
|
||||||
|
{
|
||||||
|
_buf.addLines(lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CountingIOS::addPos(int pos)
|
||||||
|
{
|
||||||
|
_buf.addPos(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CountingStreamBuf* CountingIOS::rdbuf()
|
CountingStreamBuf* CountingIOS::rdbuf()
|
||||||
{
|
{
|
||||||
return &_buf;
|
return &_buf;
|
||||||
|
@@ -54,6 +54,16 @@ void CountingStreamTest::testInput()
|
|||||||
assert (ci3.lines() == 2);
|
assert (ci3.lines() == 2);
|
||||||
assert (ci3.chars() == 8);
|
assert (ci3.chars() == 8);
|
||||||
assert (ci3.pos() == 0);
|
assert (ci3.pos() == 0);
|
||||||
|
|
||||||
|
std::istringstream istr4("foo");
|
||||||
|
CountingInputStream ci4(istr4);
|
||||||
|
while (ci4.good()) ci4.get(c);
|
||||||
|
ci4.addChars(10);
|
||||||
|
ci4.addLines(2);
|
||||||
|
ci4.addPos(3);
|
||||||
|
assert (ci4.lines() == 1 + 2);
|
||||||
|
assert (ci4.chars() == 3 + 10);
|
||||||
|
assert (ci4.pos() == 3 + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -80,6 +90,16 @@ void CountingStreamTest::testOutput()
|
|||||||
assert (co3.lines() == 2);
|
assert (co3.lines() == 2);
|
||||||
assert (co3.chars() == 8);
|
assert (co3.chars() == 8);
|
||||||
assert (co3.pos() == 0);
|
assert (co3.pos() == 0);
|
||||||
|
|
||||||
|
std::ostringstream ostr4;
|
||||||
|
CountingOutputStream co4(ostr4);
|
||||||
|
co4 << "foo";
|
||||||
|
co4.addChars(10);
|
||||||
|
co4.addLines(2);
|
||||||
|
co4.addPos(3);
|
||||||
|
assert (co4.lines() == 1 + 2);
|
||||||
|
assert (co4.chars() == 3 + 10);
|
||||||
|
assert (co4.pos() == 3 + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -63,7 +63,11 @@ public:
|
|||||||
const std::string& filename() const;
|
const std::string& filename() const;
|
||||||
/// Returns the filename portion of the path.
|
/// Returns the filename portion of the path.
|
||||||
|
|
||||||
|
std::streamsize getContentLength() const;
|
||||||
|
/// Returns the file size.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::string _path;
|
||||||
std::string _filename;
|
std::string _filename;
|
||||||
Poco::FileInputStream _istr;
|
Poco::FileInputStream _istr;
|
||||||
};
|
};
|
||||||
|
@@ -153,7 +153,14 @@ public:
|
|||||||
/// Otherwise, if the request's HTTP version is HTTP/1.1:
|
/// Otherwise, if the request's HTTP version is HTTP/1.1:
|
||||||
/// - the request's persistent connection state is left unchanged
|
/// - the request's persistent connection state is left unchanged
|
||||||
/// - the content transfer encoding is set to chunked
|
/// - the content transfer encoding is set to chunked
|
||||||
|
|
||||||
|
|
||||||
|
std::streamsize calculateContentLength();
|
||||||
|
/// Calculate the content length for the form.
|
||||||
|
/// May be UNKNOWN_CONTENT_LENGTH if not possible
|
||||||
|
/// to calculate
|
||||||
|
|
||||||
|
|
||||||
void write(std::ostream& ostr, const std::string& boundary);
|
void write(std::ostream& ostr, const std::string& boundary);
|
||||||
/// Writes the form data to the given output stream,
|
/// Writes the form data to the given output stream,
|
||||||
/// using the specified encoding.
|
/// using the specified encoding.
|
||||||
@@ -183,6 +190,7 @@ public:
|
|||||||
static const std::string ENCODING_URL; /// "application/x-www-form-urlencoded"
|
static const std::string ENCODING_URL; /// "application/x-www-form-urlencoded"
|
||||||
static const std::string ENCODING_MULTIPART; /// "multipart/form-data"
|
static const std::string ENCODING_MULTIPART; /// "multipart/form-data"
|
||||||
|
|
||||||
|
static const int UNKNOWN_CONTENT_LENGTH;
|
||||||
protected:
|
protected:
|
||||||
void readUrl(std::istream& istr);
|
void readUrl(std::istream& istr);
|
||||||
void readMultipart(std::istream& istr, PartHandler& handler);
|
void readMultipart(std::istream& istr, PartHandler& handler);
|
||||||
|
@@ -57,9 +57,15 @@ public:
|
|||||||
/// Returns a MessageHeader containing additional header
|
/// Returns a MessageHeader containing additional header
|
||||||
/// fields for the part.
|
/// fields for the part.
|
||||||
|
|
||||||
|
virtual std::streamsize getContentLength() const;
|
||||||
|
/// Returns the content length for this part
|
||||||
|
/// which may be UNKNOWN_CONTENT_LENGTH if
|
||||||
|
/// not available.
|
||||||
|
|
||||||
virtual ~PartSource();
|
virtual ~PartSource();
|
||||||
/// Destroys the PartSource.
|
/// Destroys the PartSource.
|
||||||
|
|
||||||
|
static const int UNKNOWN_CONTENT_LENGTH;
|
||||||
protected:
|
protected:
|
||||||
PartSource();
|
PartSource();
|
||||||
/// Creates the PartSource, using
|
/// Creates the PartSource, using
|
||||||
|
@@ -55,6 +55,9 @@ public:
|
|||||||
const std::string& filename() const;
|
const std::string& filename() const;
|
||||||
/// Returns the filename portion of the path.
|
/// Returns the filename portion of the path.
|
||||||
|
|
||||||
|
std::streamsize getContentLength() const;
|
||||||
|
/// Returns the string size.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::istringstream _istr;
|
std::istringstream _istr;
|
||||||
std::string _filename;
|
std::string _filename;
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include "Poco/Net/FilePartSource.h"
|
#include "Poco/Net/FilePartSource.h"
|
||||||
#include "Poco/Path.h"
|
#include "Poco/Path.h"
|
||||||
|
#include "Poco/File.h"
|
||||||
#include "Poco/Exception.h"
|
#include "Poco/Exception.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -28,7 +29,7 @@ namespace Net {
|
|||||||
|
|
||||||
|
|
||||||
FilePartSource::FilePartSource(const std::string& path):
|
FilePartSource::FilePartSource(const std::string& path):
|
||||||
_istr(path)
|
_path(path), _istr(path)
|
||||||
{
|
{
|
||||||
Path p(path);
|
Path p(path);
|
||||||
_filename = p.getFileName();
|
_filename = p.getFileName();
|
||||||
@@ -39,6 +40,7 @@ FilePartSource::FilePartSource(const std::string& path):
|
|||||||
|
|
||||||
FilePartSource::FilePartSource(const std::string& path, const std::string& mediaType):
|
FilePartSource::FilePartSource(const std::string& path, const std::string& mediaType):
|
||||||
PartSource(mediaType),
|
PartSource(mediaType),
|
||||||
|
_path(path),
|
||||||
_istr(path)
|
_istr(path)
|
||||||
{
|
{
|
||||||
Path p(path);
|
Path p(path);
|
||||||
@@ -50,6 +52,7 @@ FilePartSource::FilePartSource(const std::string& path, const std::string& media
|
|||||||
|
|
||||||
FilePartSource::FilePartSource(const std::string& path, const std::string& filename, const std::string& mediaType):
|
FilePartSource::FilePartSource(const std::string& path, const std::string& filename, const std::string& mediaType):
|
||||||
PartSource(mediaType),
|
PartSource(mediaType),
|
||||||
|
_path(path),
|
||||||
_filename(filename),
|
_filename(filename),
|
||||||
_istr(path)
|
_istr(path)
|
||||||
{
|
{
|
||||||
@@ -76,4 +79,11 @@ const std::string& FilePartSource::filename() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::streamsize FilePartSource::getContentLength() const
|
||||||
|
{
|
||||||
|
Poco::File p(_path);
|
||||||
|
return p.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::Net
|
} } // namespace Poco::Net
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
#include "Poco/StreamCopier.h"
|
#include "Poco/StreamCopier.h"
|
||||||
#include "Poco/URI.h"
|
#include "Poco/URI.h"
|
||||||
#include "Poco/String.h"
|
#include "Poco/String.h"
|
||||||
|
#include "Poco/CountingStream.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
|
||||||
@@ -41,8 +42,21 @@ namespace Poco {
|
|||||||
namespace Net {
|
namespace Net {
|
||||||
|
|
||||||
|
|
||||||
const std::string HTMLForm::ENCODING_URL = "application/x-www-form-urlencoded";
|
const std::string HTMLForm::ENCODING_URL = "application/x-www-form-urlencoded";
|
||||||
const std::string HTMLForm::ENCODING_MULTIPART = "multipart/form-data";
|
const std::string HTMLForm::ENCODING_MULTIPART = "multipart/form-data";
|
||||||
|
const int HTMLForm::UNKNOWN_CONTENT_LENGTH = -1;
|
||||||
|
|
||||||
|
|
||||||
|
class HTMLFormCountingOutputStream : public CountingOutputStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HTMLFormCountingOutputStream() : _isvalid(true) {}
|
||||||
|
|
||||||
|
bool getIsValid() const { return _isvalid; }
|
||||||
|
void setIsValid(bool v) { _isvalid = v; }
|
||||||
|
private:
|
||||||
|
bool _isvalid;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
HTMLForm::HTMLForm():
|
HTMLForm::HTMLForm():
|
||||||
@@ -217,6 +231,20 @@ void HTMLForm::prepareSubmit(HTTPRequest& request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::streamsize HTMLForm::calculateContentLength()
|
||||||
|
{
|
||||||
|
if (_boundary.empty())
|
||||||
|
throw HTMLFormException("Form must be prepared");
|
||||||
|
|
||||||
|
HTMLFormCountingOutputStream c;
|
||||||
|
write(c);
|
||||||
|
if (c.getIsValid())
|
||||||
|
return c.chars();
|
||||||
|
else
|
||||||
|
return UNKNOWN_CONTENT_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void HTMLForm::write(std::ostream& ostr, const std::string& boundary)
|
void HTMLForm::write(std::ostream& ostr, const std::string& boundary)
|
||||||
{
|
{
|
||||||
if (_encoding == ENCODING_URL)
|
if (_encoding == ENCODING_URL)
|
||||||
@@ -338,6 +366,8 @@ void HTMLForm::writeUrl(std::ostream& ostr)
|
|||||||
|
|
||||||
void HTMLForm::writeMultipart(std::ostream& ostr)
|
void HTMLForm::writeMultipart(std::ostream& ostr)
|
||||||
{
|
{
|
||||||
|
HTMLFormCountingOutputStream *costr(dynamic_cast<HTMLFormCountingOutputStream*>(&ostr));
|
||||||
|
|
||||||
MultipartWriter writer(ostr, _boundary);
|
MultipartWriter writer(ostr, _boundary);
|
||||||
for (NameValueCollection::ConstIterator it = begin(); it != end(); ++it)
|
for (NameValueCollection::ConstIterator it = begin(); it != end(); ++it)
|
||||||
{
|
{
|
||||||
@@ -365,7 +395,17 @@ void HTMLForm::writeMultipart(std::ostream& ostr)
|
|||||||
header.set("Content-Disposition", disp);
|
header.set("Content-Disposition", disp);
|
||||||
header.set("Content-Type", ita->pSource->mediaType());
|
header.set("Content-Type", ita->pSource->mediaType());
|
||||||
writer.nextPart(header);
|
writer.nextPart(header);
|
||||||
StreamCopier::copyStream(ita->pSource->stream(), ostr);
|
if (costr)
|
||||||
|
{
|
||||||
|
// count only, don't move stream position
|
||||||
|
std::streamsize partlen = ita->pSource->getContentLength();
|
||||||
|
if (partlen != PartSource::UNKNOWN_CONTENT_LENGTH)
|
||||||
|
costr->addChars(partlen);
|
||||||
|
else
|
||||||
|
costr->setIsValid(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
StreamCopier::copyStream(ita->pSource->stream(), ostr);
|
||||||
}
|
}
|
||||||
writer.close();
|
writer.close();
|
||||||
_boundary = writer.boundary();
|
_boundary = writer.boundary();
|
||||||
|
@@ -21,6 +21,9 @@ namespace Poco {
|
|||||||
namespace Net {
|
namespace Net {
|
||||||
|
|
||||||
|
|
||||||
|
const int PartSource::UNKNOWN_CONTENT_LENGTH = -1;
|
||||||
|
|
||||||
|
|
||||||
PartSource::PartSource():
|
PartSource::PartSource():
|
||||||
_mediaType("application/octet-stream")
|
_mediaType("application/octet-stream")
|
||||||
{
|
{
|
||||||
@@ -49,5 +52,9 @@ const std::string& PartSource::filename() const
|
|||||||
return EMPTY;
|
return EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::streamsize PartSource::getContentLength() const
|
||||||
|
{
|
||||||
|
return UNKNOWN_CONTENT_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
} } // namespace Poco::Net
|
} } // namespace Poco::Net
|
||||||
|
@@ -60,4 +60,10 @@ const std::string& StringPartSource::filename() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::streamsize StringPartSource::getContentLength() const
|
||||||
|
{
|
||||||
|
return _istr.str().length();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::Net
|
} } // namespace Poco::Net
|
||||||
|
@@ -147,6 +147,7 @@ void HTMLFormTest::testWriteMultipart()
|
|||||||
"This is another attachment\r\n"
|
"This is another attachment\r\n"
|
||||||
"--MIME_boundary_0123456789--\r\n"
|
"--MIME_boundary_0123456789--\r\n"
|
||||||
);
|
);
|
||||||
|
assert(s.length() == form.calculateContentLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user