Merge branch 'develop' of https://github.com/pocoproject/poco into develop

This commit is contained in:
Alex Fabijanic
2014-11-17 00:40:11 -06:00
16 changed files with 229 additions and 207 deletions

View File

@@ -33,7 +33,7 @@ matrix:
- env: TEST_NAME="arm-linux-gnueabi- (make)" - env: TEST_NAME="arm-linux-gnueabi- (make)"
script: script:
- ./configure --omit=Data/ODBC,Data/MySQL,Crypto,NetSSL && make -s -j2 CROSS_COMPILE=arm-linux-gnueabi- POCO_TARGET_OSARCH=armv7l - ./configure --omit=Data/ODBC,Data/MySQL,Crypto,NetSSL,PageCompiler && make -s -j2 CROSS_COMPILE=arm-linux-gnueabi- POCO_TARGET_OSARCH=armv7l
- env: TEST_NAME="gcc (CMake)" - env: TEST_NAME="gcc (CMake)"
compiler: gcc compiler: gcc

View File

@@ -122,7 +122,7 @@ public:
/// May return 0 if the priority has not been explicitly set. /// May return 0 if the priority has not been explicitly set.
static int getMinOSPriority(int policy = POLICY_DEFAULT); static int getMinOSPriority(int policy = POLICY_DEFAULT);
/// Returns the mininum operating system-specific priority value, /// Returns the minimum operating system-specific priority value,
/// which can be passed to setOSPriority() for the given policy. /// which can be passed to setOSPriority() for the given policy.
static int getMaxOSPriority(int policy = POLICY_DEFAULT); static int getMaxOSPriority(int policy = POLICY_DEFAULT);
@@ -149,6 +149,13 @@ public:
void start(Callable target, void* pData = 0); void start(Callable target, void* pData = 0);
/// Starts the thread with the given target and parameter. /// Starts the thread with the given target and parameter.
template <class Functor>
void startFunc(Functor fn)
/// Starts the thread with the given functor object or lambda.
{
startImpl(new FunctorRunnable<Functor>(fn));
}
void join(); void join();
/// Waits until the thread completes execution. /// Waits until the thread completes execution.
/// If multiple threads try to join the same /// If multiple threads try to join the same
@@ -221,7 +228,29 @@ protected:
static int uniqueId(); static int uniqueId();
/// Creates and returns a unique id for a thread. /// Creates and returns a unique id for a thread.
template <class Functor>
class FunctorRunnable: public Runnable
{
public:
FunctorRunnable(const Functor& functor):
_functor(functor)
{
}
~FunctorRunnable()
{
}
void run()
{
_functor();
}
private:
Functor _functor;
};
private: private:
Thread(const Thread&); Thread(const Thread&);
Thread& operator = (const Thread&); Thread& operator = (const Thread&);

View File

@@ -26,6 +26,7 @@
#include "Poco/Event.h" #include "Poco/Event.h"
#include "Poco/RefCountedObject.h" #include "Poco/RefCountedObject.h"
#include "Poco/AutoPtr.h" #include "Poco/AutoPtr.h"
#include "Poco/SharedPtr.h"
#include <pthread.h> #include <pthread.h>
// must be limits.h (not <climits>) for PTHREAD_STACK_MIN on Solaris // must be limits.h (not <climits>) for PTHREAD_STACK_MIN on Solaris
#include <limits.h> #include <limits.h>
@@ -61,16 +62,6 @@ public:
POLICY_DEFAULT_IMPL = SCHED_OTHER POLICY_DEFAULT_IMPL = SCHED_OTHER
}; };
struct CallbackData: public RefCountedObject
{
CallbackData(): callback(0), pData(0)
{
}
Callable callback;
void* pData;
};
ThreadImpl(); ThreadImpl();
~ThreadImpl(); ~ThreadImpl();
@@ -83,9 +74,7 @@ public:
static int getMaxOSPriorityImpl(int policy); static int getMaxOSPriorityImpl(int policy);
void setStackSizeImpl(int size); void setStackSizeImpl(int size);
int getStackSizeImpl() const; int getStackSizeImpl() const;
void startImpl(Runnable& target); void startImpl(SharedPtr<Runnable> pTarget);
void startImpl(Callable target, void* pData = 0);
void joinImpl(); void joinImpl();
bool joinImpl(long milliseconds); bool joinImpl(long milliseconds);
bool isRunningImpl() const; bool isRunningImpl() const;
@@ -96,7 +85,6 @@ public:
protected: protected:
static void* runnableEntry(void* pThread); static void* runnableEntry(void* pThread);
static void* callableEntry(void* pThread);
static int mapPrio(int prio, int policy = SCHED_OTHER); static int mapPrio(int prio, int policy = SCHED_OTHER);
static int reverseMapPrio(int osPrio, int policy = SCHED_OTHER); static int reverseMapPrio(int osPrio, int policy = SCHED_OTHER);
@@ -129,8 +117,6 @@ private:
struct ThreadData: public RefCountedObject struct ThreadData: public RefCountedObject
{ {
ThreadData(): ThreadData():
pRunnableTarget(0),
pCallbackTarget(0),
thread(0), thread(0),
prio(PRIO_NORMAL_IMPL), prio(PRIO_NORMAL_IMPL),
policy(SCHED_OTHER), policy(SCHED_OTHER),
@@ -146,8 +132,7 @@ private:
#endif #endif
} }
Runnable* pRunnableTarget; SharedPtr<Runnable> pRunnableTarget;
AutoPtr<CallbackData> pCallbackTarget;
pthread_t thread; pthread_t thread;
int prio; int prio;
int osPrio; int osPrio;
@@ -186,8 +171,7 @@ inline int ThreadImpl::getOSPriorityImpl() const
inline bool ThreadImpl::isRunningImpl() const inline bool ThreadImpl::isRunningImpl() const
{ {
return _pData->pRunnableTarget != 0 || return !_pData->pRunnableTarget.isNull();
(_pData->pCallbackTarget.get() != 0 && _pData->pCallbackTarget->callback != 0);
} }

View File

@@ -22,6 +22,7 @@
#include "Poco/Foundation.h" #include "Poco/Foundation.h"
#include "Poco/Runnable.h" #include "Poco/Runnable.h"
#include "Poco/SharedPtr.h"
#include "Poco/UnWindows.h" #include "Poco/UnWindows.h"
@@ -40,16 +41,6 @@ public:
typedef unsigned (__stdcall *Entry)(void*); typedef unsigned (__stdcall *Entry)(void*);
#endif #endif
struct CallbackData
{
CallbackData(): callback(0), pData(0)
{
}
Callable callback;
void* pData;
};
enum Priority enum Priority
{ {
PRIO_LOWEST_IMPL = THREAD_PRIORITY_LOWEST, PRIO_LOWEST_IMPL = THREAD_PRIORITY_LOWEST,
@@ -76,9 +67,7 @@ public:
static int getMaxOSPriorityImpl(int policy); static int getMaxOSPriorityImpl(int policy);
void setStackSizeImpl(int size); void setStackSizeImpl(int size);
int getStackSizeImpl() const; int getStackSizeImpl() const;
void startImpl(Runnable& target); void startImpl(SharedPtr<Runnable> pTarget);
void startImpl(Callable target, void* pData = 0);
void joinImpl(); void joinImpl();
bool joinImpl(long milliseconds); bool joinImpl(long milliseconds);
bool isRunningImpl() const; bool isRunningImpl() const;
@@ -94,12 +83,6 @@ protected:
static unsigned __stdcall runnableEntry(void* pThread); static unsigned __stdcall runnableEntry(void* pThread);
#endif #endif
#if defined(_DLL)
static DWORD WINAPI callableEntry(LPVOID pThread);
#else
static unsigned __stdcall callableEntry(void* pThread);
#endif
void createImpl(Entry ent, void* pData); void createImpl(Entry ent, void* pData);
void threadCleanup(); void threadCleanup();
@@ -129,12 +112,11 @@ private:
DWORD _slot; DWORD _slot;
}; };
Runnable* _pRunnableTarget; SharedPtr<Runnable> _pRunnableTarget;
CallbackData _callbackTarget; HANDLE _thread;
HANDLE _thread; DWORD _threadId;
DWORD _threadId; int _prio;
int _prio; int _stackSize;
int _stackSize;
static CurrentThreadHolder _currentThreadHolder; static CurrentThreadHolder _currentThreadHolder;
}; };

View File

@@ -35,6 +35,9 @@ struct Foundation_API UTF8
/// ///
/// toUpper(), toUpperInPlace(), toLower() and toLowerInPlace() provide /// toUpper(), toUpperInPlace(), toLower() and toLowerInPlace() provide
/// Unicode-based character case transformation for UTF-8 encoded strings. /// Unicode-based character case transformation for UTF-8 encoded strings.
///
/// removeBOM() removes the UTF-8 Byte Order Mark sequence (0xEF, 0xBB, 0xBF)
/// from the beginning of the given string, if it's there.
{ {
static int icompare(const std::string& str, std::string::size_type pos, std::string::size_type n, std::string::const_iterator it2, std::string::const_iterator end2); static int icompare(const std::string& str, std::string::size_type pos, std::string::size_type n, std::string::const_iterator it2, std::string::const_iterator end2);
static int icompare(const std::string& str1, const std::string& str2); static int icompare(const std::string& str1, const std::string& str2);
@@ -51,6 +54,10 @@ struct Foundation_API UTF8
static std::string& toUpperInPlace(std::string& str); static std::string& toUpperInPlace(std::string& str);
static std::string toLower(const std::string& str); static std::string toLower(const std::string& str);
static std::string& toLowerInPlace(std::string& str); static std::string& toLowerInPlace(std::string& str);
static void removeBOM(std::string& str);
/// Remove the UTF-8 Byte Order Mark sequence (0xEF, 0xBB, 0xBF)
/// from the beginning of the string, if it's there.
}; };

View File

@@ -38,6 +38,57 @@
namespace Poco { namespace Poco {
namespace {
class RunnableHolder: public Runnable
{
public:
RunnableHolder(Runnable& target):
_target(target)
{
}
~RunnableHolder()
{
}
void run()
{
_target.run();
}
private:
Runnable& _target;
};
class CallableHolder: public Runnable
{
public:
CallableHolder(Thread::Callable callable, void* pData):
_callable(callable),
_pData(pData)
{
}
~CallableHolder()
{
}
void run()
{
_callable(_pData);
}
private:
Thread::Callable _callable;
void* _pData;
};
} // namespace
Thread::Thread(): Thread::Thread():
_id(uniqueId()), _id(uniqueId()),
_name(makeName()), _name(makeName()),
@@ -76,13 +127,13 @@ Thread::Priority Thread::getPriority() const
void Thread::start(Runnable& target) void Thread::start(Runnable& target)
{ {
startImpl(target); startImpl(new RunnableHolder(target));
} }
void Thread::start(Callable target, void* pData) void Thread::start(Callable target, void* pData)
{ {
startImpl(target, pData); startImpl(new CallableHolder(target, pData));
} }

View File

@@ -104,7 +104,10 @@ void ThreadImpl::setPriorityImpl(int prio)
_pData->policy = SCHED_OTHER; _pData->policy = SCHED_OTHER;
if (isRunningImpl()) if (isRunningImpl())
{ {
struct sched_param par; struct sched_param par; struct MyStruct
{
};
par.sched_priority = mapPrio(_pData->prio, SCHED_OTHER); par.sched_priority = mapPrio(_pData->prio, SCHED_OTHER);
if (pthread_setschedparam(_pData->thread, SCHED_OTHER, &par)) if (pthread_setschedparam(_pData->thread, SCHED_OTHER, &par))
throw SystemException("cannot set thread priority"); throw SystemException("cannot set thread priority");
@@ -117,7 +120,7 @@ void ThreadImpl::setOSPriorityImpl(int prio, int policy)
{ {
if (prio != _pData->osPrio || policy != _pData->policy) if (prio != _pData->osPrio || policy != _pData->policy)
{ {
if (_pData->pRunnableTarget || _pData->pCallbackTarget) if (_pData->pRunnableTarget)
{ {
struct sched_param par; struct sched_param par;
par.sched_priority = prio; par.sched_priority = prio;
@@ -177,7 +180,7 @@ void ThreadImpl::setStackSizeImpl(int size)
} }
void ThreadImpl::startImpl(Runnable& target) void ThreadImpl::startImpl(SharedPtr<Runnable> pTarget)
{ {
if (_pData->pRunnableTarget) if (_pData->pRunnableTarget)
throw SystemException("thread already running"); throw SystemException("thread already running");
@@ -194,7 +197,7 @@ void ThreadImpl::startImpl(Runnable& target)
} }
} }
_pData->pRunnableTarget = &target; _pData->pRunnableTarget = pTarget;
if (pthread_create(&_pData->thread, &attributes, runnableEntry, this)) if (pthread_create(&_pData->thread, &attributes, runnableEntry, this))
{ {
_pData->pRunnableTarget = 0; _pData->pRunnableTarget = 0;
@@ -224,56 +227,6 @@ void ThreadImpl::startImpl(Runnable& target)
} }
void ThreadImpl::startImpl(Callable target, void* pData)
{
if (_pData->pCallbackTarget && _pData->pCallbackTarget->callback)
throw SystemException("thread already running");
pthread_attr_t attributes;
pthread_attr_init(&attributes);
if (_pData->stackSize != 0)
{
if (0 != pthread_attr_setstacksize(&attributes, _pData->stackSize))
throw SystemException("can not set thread stack size");
}
if (0 == _pData->pCallbackTarget.get())
_pData->pCallbackTarget = new CallbackData;
_pData->pCallbackTarget->callback = target;
_pData->pCallbackTarget->pData = pData;
if (pthread_create(&_pData->thread, &attributes, callableEntry, this))
{
_pData->pCallbackTarget->callback = 0;
_pData->pCallbackTarget->pData = 0;
pthread_attr_destroy(&attributes);
throw SystemException("cannot start thread");
}
_pData->started = true;
pthread_attr_destroy(&attributes);
if (_pData->policy == SCHED_OTHER)
{
if (_pData->prio != PRIO_NORMAL_IMPL)
{
struct sched_param par;
par.sched_priority = mapPrio(_pData->prio, SCHED_OTHER);
if (pthread_setschedparam(_pData->thread, SCHED_OTHER, &par))
throw SystemException("cannot set thread priority");
}
}
else
{
struct sched_param par;
par.sched_priority = _pData->osPrio;
if (pthread_setschedparam(_pData->thread, _pData->policy, &par))
throw SystemException("cannot set thread priority");
}
}
void ThreadImpl::joinImpl() void ThreadImpl::joinImpl()
{ {
if (!_pData->started) return; if (!_pData->started) return;
@@ -409,48 +362,6 @@ void* ThreadImpl::runnableEntry(void* pThread)
} }
void* ThreadImpl::callableEntry(void* pThread)
{
_currentThreadHolder.set(reinterpret_cast<ThreadImpl*>(pThread));
#if defined(POCO_OS_FAMILY_UNIX)
sigset_t sset;
sigemptyset(&sset);
sigaddset(&sset, SIGQUIT);
sigaddset(&sset, SIGTERM);
sigaddset(&sset, SIGPIPE);
pthread_sigmask(SIG_BLOCK, &sset, 0);
#endif
ThreadImpl* pThreadImpl = reinterpret_cast<ThreadImpl*>(pThread);
#if defined(POCO_POSIX_DEBUGGER_THREAD_NAMES)
setThreadName(pThreadImpl->_pData->thread, reinterpret_cast<Thread*>(pThread)->getName().c_str());
#endif
AutoPtr<ThreadData> pData = pThreadImpl->_pData;
try
{
pData->pCallbackTarget->callback(pData->pCallbackTarget->pData);
}
catch (Exception& exc)
{
ErrorHandler::handle(exc);
}
catch (std::exception& exc)
{
ErrorHandler::handle(exc);
}
catch (...)
{
ErrorHandler::handle();
}
pData->pCallbackTarget->callback = 0;
pData->pCallbackTarget->pData = 0;
pData->done.set();
return 0;
}
int ThreadImpl::mapPrio(int prio, int policy) int ThreadImpl::mapPrio(int prio, int policy)
{ {
int pmin = getMinOSPriorityImpl(policy); int pmin = getMinOSPriorityImpl(policy);

View File

@@ -70,7 +70,6 @@ ThreadImpl::CurrentThreadHolder ThreadImpl::_currentThreadHolder;
ThreadImpl::ThreadImpl(): ThreadImpl::ThreadImpl():
_pRunnableTarget(0),
_thread(0), _thread(0),
_threadId(0), _threadId(0),
_prio(PRIO_NORMAL_IMPL), _prio(PRIO_NORMAL_IMPL),
@@ -105,30 +104,16 @@ void ThreadImpl::setOSPriorityImpl(int prio, int /* policy */)
} }
void ThreadImpl::startImpl(Runnable& target) void ThreadImpl::startImpl(SharedPtr<Runnable> pTarget)
{ {
if (isRunningImpl()) if (isRunningImpl())
throw SystemException("thread already running"); throw SystemException("thread already running");
_pRunnableTarget = &target; _pRunnableTarget = pTarget;
createImpl(runnableEntry, this); createImpl(runnableEntry, this);
} }
void ThreadImpl::startImpl(Callable target, void* pData)
{
if (isRunningImpl())
throw SystemException("thread already running");
threadCleanup();
_callbackTarget.callback = target;
_callbackTarget.pData = pData;
createImpl(callableEntry, this);
}
void ThreadImpl::createImpl(Entry ent, void* pData) void ThreadImpl::createImpl(Entry ent, void* pData)
{ {
#if defined(_DLL) #if defined(_DLL)
@@ -237,35 +222,4 @@ unsigned __stdcall ThreadImpl::runnableEntry(void* pThread)
} }
#if defined(_DLL)
DWORD WINAPI ThreadImpl::callableEntry(LPVOID pThread)
#else
unsigned __stdcall ThreadImpl::callableEntry(void* pThread)
#endif
{
_currentThreadHolder.set(reinterpret_cast<ThreadImpl*>(pThread));
#if defined(POCO_WIN32_DEBUGGER_THREAD_NAMES)
setThreadName(-1, reinterpret_cast<Thread*>(pThread)->getName().c_str());
#endif
try
{
ThreadImpl* pTI = reinterpret_cast<ThreadImpl*>(pThread);
pTI->_callbackTarget.callback(pTI->_callbackTarget.pData);
}
catch (Exception& exc)
{
ErrorHandler::handle(exc);
}
catch (std::exception& exc)
{
ErrorHandler::handle(exc);
}
catch (...)
{
ErrorHandler::handle();
}
return 0;
}
} // namespace Poco } // namespace Poco

View File

@@ -160,4 +160,16 @@ std::string& UTF8::toLowerInPlace(std::string& str)
} }
void UTF8::removeBOM(std::string& str)
{
if (str.size() >= 3
&& static_cast<unsigned char>(str[0]) == 0xEF
&& static_cast<unsigned char>(str[1]) == 0xBB
&& static_cast<unsigned char>(str[2]) == 0xBF)
{
str.erase(0, 3);
}
}
} // namespace Poco } // namespace Poco

View File

@@ -363,6 +363,45 @@ void ThreadTest::testThreadFunction()
} }
struct Functor
{
void operator () ()
{
++MyRunnable::_staticVar;
}
};
void ThreadTest::testThreadFunctor()
{
Thread thread;
assert (!thread.isRunning());
MyRunnable::_staticVar = 0;
thread.startFunc(Functor());
thread.join();
assert (1 == MyRunnable::_staticVar);
assert (!thread.isRunning());
#if __cplusplus >= 201103L
Thread thread2;
assert (!thread2.isRunning());
MyRunnable::_staticVar = 0;
thread.startFunc([] () {MyRunnable::_staticVar++;});
thread.join();
assert (1 == MyRunnable::_staticVar);
assert (!thread2.isRunning());
#endif
}
void ThreadTest::testThreadStackSize() void ThreadTest::testThreadStackSize()
{ {
int stackSize = 50000000; int stackSize = 50000000;
@@ -436,6 +475,7 @@ CppUnit::Test* ThreadTest::suite()
CppUnit_addTest(pSuite, ThreadTest, testTrySleep); CppUnit_addTest(pSuite, ThreadTest, testTrySleep);
CppUnit_addTest(pSuite, ThreadTest, testThreadTarget); CppUnit_addTest(pSuite, ThreadTest, testThreadTarget);
CppUnit_addTest(pSuite, ThreadTest, testThreadFunction); CppUnit_addTest(pSuite, ThreadTest, testThreadFunction);
CppUnit_addTest(pSuite, ThreadTest, testThreadFunctor);
CppUnit_addTest(pSuite, ThreadTest, testThreadStackSize); CppUnit_addTest(pSuite, ThreadTest, testThreadStackSize);
CppUnit_addTest(pSuite, ThreadTest, testSleep); CppUnit_addTest(pSuite, ThreadTest, testSleep);

View File

@@ -37,6 +37,7 @@ public:
void testTrySleep(); void testTrySleep();
void testThreadTarget(); void testThreadTarget();
void testThreadFunction(); void testThreadFunction();
void testThreadFunctor();
void testThreadStackSize(); void testThreadStackSize();
void testSleep(); void testSleep();

View File

@@ -1,7 +1,7 @@
// //
// HTTPClientSession.h // HTTPClientSession.h
// //
// $Id: //poco/1.4/Net/include/Poco/Net/HTTPClientSession.h#7 $ // $Id: //poco/1.4/Net/include/Poco/Net/HTTPClientSession.h#8 $
// //
// Library: Net // Library: Net
// Package: HTTPClient // Package: HTTPClient
@@ -100,6 +100,9 @@ public:
HTTPClientSession(const std::string& host, Poco::UInt16 port = HTTPSession::HTTP_PORT); HTTPClientSession(const std::string& host, Poco::UInt16 port = HTTPSession::HTTP_PORT);
/// Creates a HTTPClientSession using the given host and port. /// Creates a HTTPClientSession using the given host and port.
HTTPClientSession(const std::string& host, Poco::UInt16 port, const ProxyConfig& proxyConfig);
/// Creates a HTTPClientSession using the given host, port and proxy configuration.
virtual ~HTTPClientSession(); virtual ~HTTPClientSession();
/// Destroys the HTTPClientSession and closes /// Destroys the HTTPClientSession and closes
/// the underlying socket. /// the underlying socket.

View File

@@ -28,6 +28,7 @@
#include "Poco/URI.h" #include "Poco/URI.h"
#include "Poco/String.h" #include "Poco/String.h"
#include "Poco/CountingStream.h" #include "Poco/CountingStream.h"
#include "Poco/UTF8String.h"
#include <sstream> #include <sstream>
@@ -42,20 +43,31 @@ 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; const int HTMLForm::UNKNOWN_CONTENT_LENGTH = -1;
class HTMLFormCountingOutputStream : public CountingOutputStream class HTMLFormCountingOutputStream: public CountingOutputStream
{ {
public: public:
HTMLFormCountingOutputStream() : _isvalid(true) {} HTMLFormCountingOutputStream():
_valid(true)
{
}
bool isValid() const
{
return _valid;
}
void setValid(bool v)
{
_valid = v;
}
bool getIsValid() const { return _isvalid; }
void setIsValid(bool v) { _isvalid = v; }
private: private:
bool _isvalid; bool _valid;
}; };
@@ -238,7 +250,7 @@ std::streamsize HTMLForm::calculateContentLength()
HTMLFormCountingOutputStream c; HTMLFormCountingOutputStream c;
write(c); write(c);
if (c.getIsValid()) if (c.isValid())
return c.chars(); return c.chars();
else else
return UNKNOWN_CONTENT_LENGTH; return UNKNOWN_CONTENT_LENGTH;
@@ -274,6 +286,7 @@ void HTMLForm::readUrl(std::istream& istr)
int fields = 0; int fields = 0;
int ch = istr.get(); int ch = istr.get();
bool isFirst = true;
while (ch != eof) while (ch != eof)
{ {
if (_fieldLimit > 0 && fields == _fieldLimit) if (_fieldLimit > 0 && fields == _fieldLimit)
@@ -296,6 +309,11 @@ void HTMLForm::readUrl(std::istream& istr)
ch = istr.get(); ch = istr.get();
} }
} }
// remove UTF-8 byte order mark from first name, if present
if (isFirst)
{
UTF8::removeBOM(name);
}
std::string decodedName; std::string decodedName;
std::string decodedValue; std::string decodedValue;
URI::decode(name, decodedName); URI::decode(name, decodedName);
@@ -303,6 +321,7 @@ void HTMLForm::readUrl(std::istream& istr)
add(decodedName, decodedValue); add(decodedName, decodedValue);
++fields; ++fields;
if (ch == '&') ch = istr.get(); if (ch == '&') ch = istr.get();
isFirst = false;
} }
} }
@@ -402,7 +421,7 @@ void HTMLForm::writeMultipart(std::ostream& ostr)
if (partlen != PartSource::UNKNOWN_CONTENT_LENGTH) if (partlen != PartSource::UNKNOWN_CONTENT_LENGTH)
costr->addChars(static_cast<int>(partlen)); costr->addChars(static_cast<int>(partlen));
else else
costr->setIsValid(false); costr->setValid(false);
} }
else else
StreamCopier::copyStream(ita->pSource->stream(), ostr); StreamCopier::copyStream(ita->pSource->stream(), ostr);

View File

@@ -1,7 +1,7 @@
// //
// HTTPClientSession.cpp // HTTPClientSession.cpp
// //
// $Id: //poco/1.4/Net/src/HTTPClientSession.cpp#14 $ // $Id: //poco/1.4/Net/src/HTTPClientSession.cpp#15 $
// //
// Library: Net // Library: Net
// Package: HTTPClient // Package: HTTPClient
@@ -87,6 +87,18 @@ HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port)
} }
HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port, const ProxyConfig& proxyConfig):
_host(host),
_port(port),
_proxyConfig(proxyConfig),
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
_reconnect(false),
_mustReconnect(false),
_expectResponseBody(false)
{
}
HTTPClientSession::~HTTPClientSession() HTTPClientSession::~HTTPClientSession()
{ {
} }
@@ -379,7 +391,8 @@ void HTTPClientSession::proxyAuthenticateImpl(HTTPRequest& request)
StreamSocket HTTPClientSession::proxyConnect() StreamSocket HTTPClientSession::proxyConnect()
{ {
HTTPClientSession proxySession(getProxyHost(), getProxyPort()); ProxyConfig emptyProxyConfig;
HTTPClientSession proxySession(getProxyHost(), getProxyPort(), emptyProxyConfig);
proxySession.setTimeout(getTimeout()); proxySession.setTimeout(getTimeout());
std::string targetAddress(_host); std::string targetAddress(_host);
targetAddress.append(":"); targetAddress.append(":");

View File

@@ -191,6 +191,20 @@ void HTMLFormTest::testReadUrlPUT()
} }
void HTMLFormTest::testReadUrlBOM()
{
HTTPRequest req("PUT", "/form.cgi?field0=value0");
std::istringstream istr("\357\273\277field1=value1&field2=value%202&field3=value%3D3&field4=value%264");
HTMLForm form(req, istr);
assert (form.size() == 5);
assert (form["field0"] == "value0");
assert (form["field1"] == "value1");
assert (form["field2"] == "value 2");
assert (form["field3"] == "value=3");
assert (form["field4"] == "value&4");
}
void HTMLFormTest::testReadMultipart() void HTMLFormTest::testReadMultipart()
{ {
std::istringstream istr( std::istringstream istr(
@@ -359,6 +373,7 @@ CppUnit::Test* HTMLFormTest::suite()
CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlGET); CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlGET);
CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlPOST); CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlPOST);
CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlPUT); CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlPUT);
CppUnit_addTest(pSuite, HTMLFormTest, testReadUrlBOM);
CppUnit_addTest(pSuite, HTMLFormTest, testReadMultipart); CppUnit_addTest(pSuite, HTMLFormTest, testReadMultipart);
CppUnit_addTest(pSuite, HTMLFormTest, testSubmit1); CppUnit_addTest(pSuite, HTMLFormTest, testSubmit1);
CppUnit_addTest(pSuite, HTMLFormTest, testSubmit2); CppUnit_addTest(pSuite, HTMLFormTest, testSubmit2);

View File

@@ -31,6 +31,7 @@ public:
void testReadUrlGET(); void testReadUrlGET();
void testReadUrlPOST(); void testReadUrlPOST();
void testReadUrlPUT(); void testReadUrlPUT();
void testReadUrlBOM();
void testReadMultipart(); void testReadMultipart();
void testSubmit1(); void testSubmit1();
void testSubmit2(); void testSubmit2();