2727#include " Poco/StreamCopier.h"
2828#include " Poco/URI.h"
2929#include " Poco/String.h"
30+ #include " Poco/CountingStream.h"
3031#include < sstream>
3132
3233
@@ -41,8 +42,21 @@ namespace Poco {
4142namespace Net {
4243
4344
44- const std::string HTMLForm::ENCODING_URL = " application/x-www-form-urlencoded" ;
45- const std::string HTMLForm::ENCODING_MULTIPART = " multipart/form-data" ;
45+ const std::string HTMLForm::ENCODING_URL = " application/x-www-form-urlencoded" ;
46+ const std::string HTMLForm::ENCODING_MULTIPART = " multipart/form-data" ;
47+ const int HTMLForm::UNKNOWN_CONTENT_LENGTH = -1 ;
48+
49+
50+ class HTMLFormCountingOutputStream : public CountingOutputStream
51+ {
52+ public:
53+ HTMLFormCountingOutputStream () : _isvalid(true ) {}
54+
55+ bool getIsValid () const { return _isvalid; }
56+ void setIsValid (bool v) { _isvalid = v; }
57+ private:
58+ bool _isvalid;
59+ };
4660
4761
4862HTMLForm::HTMLForm ():
@@ -217,6 +231,20 @@ void HTMLForm::prepareSubmit(HTTPRequest& request)
217231}
218232
219233
234+ std::streamsize HTMLForm::calculateContentLength ()
235+ {
236+ if (_boundary.empty ())
237+ throw HTMLFormException (" Form must be prepared" );
238+
239+ HTMLFormCountingOutputStream c;
240+ write (c);
241+ if (c.getIsValid ())
242+ return c.chars ();
243+ else
244+ return UNKNOWN_CONTENT_LENGTH ;
245+ }
246+
247+
220248void HTMLForm::write (std::ostream& ostr, const std::string& boundary)
221249{
222250 if (_encoding == ENCODING_URL )
@@ -338,6 +366,8 @@ void HTMLForm::writeUrl(std::ostream& ostr)
338366
339367void HTMLForm::writeMultipart (std::ostream& ostr)
340368{
369+ HTMLFormCountingOutputStream *costr (dynamic_cast <HTMLFormCountingOutputStream*>(&ostr));
370+
341371 MultipartWriter writer (ostr, _boundary);
342372 for (NameValueCollection::ConstIterator it = begin (); it != end (); ++it)
343373 {
@@ -365,7 +395,17 @@ void HTMLForm::writeMultipart(std::ostream& ostr)
365395 header.set (" Content-Disposition" , disp);
366396 header.set (" Content-Type" , ita->pSource ->mediaType ());
367397 writer.nextPart (header);
368- StreamCopier::copyStream (ita->pSource ->stream (), ostr);
398+ if (costr)
399+ {
400+ // count only, don't move stream position
401+ std::streamsize partlen = ita->pSource ->getContentLength ();
402+ if (partlen != PartSource::UNKNOWN_CONTENT_LENGTH )
403+ costr->addChars (partlen);
404+ else
405+ costr->setIsValid (false );
406+ }
407+ else
408+ StreamCopier::copyStream (ita->pSource ->stream (), ostr);
369409 }
370410 writer.close ();
371411 _boundary = writer.boundary ();
0 commit comments