Merge pull request #344 from RangelReale/htmlformcontentlength

HTMLForm Content-Length calculation
This commit is contained in:
Aleksandar Fabijanic 2014-05-21 22:27:12 -05:00
Родитель 89b7228461 0d2a839f79
Коммит 731fb29fcc
12 изменённых файлов: 164 добавлений и 5 удалений

Просмотреть файл

@ -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());
}