Merge pull request #344 from RangelReale/htmlformcontentlength
HTMLForm Content-Length calculation
This commit is contained in:
Коммит
731fb29fcc
|
@ -69,6 +69,15 @@ public:
|
|||
int getCurrentLineNumber() const;
|
||||
/// 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:
|
||||
int readFromDevice();
|
||||
int writeToDevice(char c);
|
||||
|
@ -124,6 +133,15 @@ public:
|
|||
int getCurrentLineNumber() const;
|
||||
/// 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();
|
||||
/// 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()
|
||||
{
|
||||
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()
|
||||
{
|
||||
return &_buf;
|
||||
|
|
|
@ -54,6 +54,16 @@ void CountingStreamTest::testInput()
|
|||
assert (ci3.lines() == 2);
|
||||
assert (ci3.chars() == 8);
|
||||
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.chars() == 8);
|
||||
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;
|
||||
/// Returns the filename portion of the path.
|
||||
|
||||
std::streamsize getContentLength() const;
|
||||
/// Returns the file size.
|
||||
|
||||
private:
|
||||
std::string _path;
|
||||
std::string _filename;
|
||||
Poco::FileInputStream _istr;
|
||||
};
|
||||
|
|
|
@ -153,7 +153,14 @@ public:
|
|||
/// Otherwise, if the request's HTTP version is HTTP/1.1:
|
||||
/// - the request's persistent connection state is left unchanged
|
||||
/// - 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);
|
||||
/// Writes the form data to the given output stream,
|
||||
/// 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_MULTIPART; /// "multipart/form-data"
|
||||
|
||||
static const int UNKNOWN_CONTENT_LENGTH;
|
||||
protected:
|
||||
void readUrl(std::istream& istr);
|
||||
void readMultipart(std::istream& istr, PartHandler& handler);
|
||||
|
|
|
@ -57,9 +57,15 @@ public:
|
|||
/// Returns a MessageHeader containing additional header
|
||||
/// 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();
|
||||
/// Destroys the PartSource.
|
||||
|
||||
static const int UNKNOWN_CONTENT_LENGTH;
|
||||
protected:
|
||||
PartSource();
|
||||
/// Creates the PartSource, using
|
||||
|
|
|
@ -55,6 +55,9 @@ public:
|
|||
const std::string& filename() const;
|
||||
/// Returns the filename portion of the path.
|
||||
|
||||
std::streamsize getContentLength() const;
|
||||
/// Returns the string size.
|
||||
|
||||
private:
|
||||
std::istringstream _istr;
|
||||
std::string _filename;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "Poco/Net/FilePartSource.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
|
||||
|
@ -28,7 +29,7 @@ namespace Net {
|
|||
|
||||
|
||||
FilePartSource::FilePartSource(const std::string& path):
|
||||
_istr(path)
|
||||
_path(path), _istr(path)
|
||||
{
|
||||
Path p(path);
|
||||
_filename = p.getFileName();
|
||||
|
@ -39,6 +40,7 @@ FilePartSource::FilePartSource(const std::string& path):
|
|||
|
||||
FilePartSource::FilePartSource(const std::string& path, const std::string& mediaType):
|
||||
PartSource(mediaType),
|
||||
_path(path),
|
||||
_istr(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):
|
||||
PartSource(mediaType),
|
||||
_path(path),
|
||||
_filename(filename),
|
||||
_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
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "Poco/StreamCopier.h"
|
||||
#include "Poco/URI.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/CountingStream.h"
|
||||
#include <sstream>
|
||||
|
||||
|
||||
|
@ -41,8 +42,21 @@ 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 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() : _isvalid(true) {}
|
||||
|
||||
bool getIsValid() const { return _isvalid; }
|
||||
void setIsValid(bool v) { _isvalid = v; }
|
||||
private:
|
||||
bool _isvalid;
|
||||
};
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
if (_encoding == ENCODING_URL)
|
||||
|
@ -338,6 +366,8 @@ void HTMLForm::writeUrl(std::ostream& ostr)
|
|||
|
||||
void HTMLForm::writeMultipart(std::ostream& ostr)
|
||||
{
|
||||
HTMLFormCountingOutputStream *costr(dynamic_cast<HTMLFormCountingOutputStream*>(&ostr));
|
||||
|
||||
MultipartWriter writer(ostr, _boundary);
|
||||
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-Type", ita->pSource->mediaType());
|
||||
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();
|
||||
_boundary = writer.boundary();
|
||||
|
|
|
@ -21,6 +21,9 @@ namespace Poco {
|
|||
namespace Net {
|
||||
|
||||
|
||||
const int PartSource::UNKNOWN_CONTENT_LENGTH = -1;
|
||||
|
||||
|
||||
PartSource::PartSource():
|
||||
_mediaType("application/octet-stream")
|
||||
{
|
||||
|
@ -49,5 +52,9 @@ const std::string& PartSource::filename() const
|
|||
return EMPTY;
|
||||
}
|
||||
|
||||
std::streamsize PartSource::getContentLength() const
|
||||
{
|
||||
return UNKNOWN_CONTENT_LENGTH;
|
||||
}
|
||||
|
||||
} } // 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
|
||||
|
|
|
@ -147,6 +147,7 @@ void HTMLFormTest::testWriteMultipart()
|
|||
"This is another attachment\r\n"
|
||||
"--MIME_boundary_0123456789--\r\n"
|
||||
);
|
||||
assert(s.length() == form.calculateContentLength());
|
||||
}
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче