I have some proposed additions to wxCurl that allow HTTP form posts.
The multithreaded classes for HTTP in wxCurl are really great for GUI applications, but currently they only have GET (wxCurlDownloadThread) and PUT requests (wxCurlUploadThread). I made a wxCurlFormPostThread class that is made for multithreaded HTTP POST requests on top of the wxCurlHTTP class.
wxcode/components/wxcurl/include/wx/curl/thread.h
Code: Select all
> // ----------------------------------------------------------------------------
> // wxCurlFormPostThread
> // ----------------------------------------------------------------------------
>
> //! A simple joinable thread which allows uploading
> //! resources to the net without blocking the GUI of your app.
> class WXDLLIMPEXP_CURL wxCurlFormPostThread : public wxCurlBaseThread
> {
>
>
> public:
> wxCurlFormPostThread(wxEvtHandler *handler = NULL,
> int id = wxID_ANY,
> const wxString &url = wxEmptyString)
> : wxCurlBaseThread(handler, id)
> {
> if (!url.IsEmpty())
> Post(url);
> }
>
> public: // public API
>
>
> //! Creates and runs this thread for upload to the given URL of the given
> //! input stream (internally calls #SetURL and #SetOutputStream).
> wxCurlThreadError Post(const wxString &url);
>
> //! Uploads the URL previously set with #SetURL using the input stream
> //! previously set with #SetInputStream.
> wxCurlThreadError Post();
>
> //void AddFileToForm(const wxString& name,const wxString& filepath);
> bool AddForm(const bool& bClear, const wxString& szName,
> struct curl_forms* pForms, CURLFORMcode* outErr);
>
>
> bool AddBufferToForm(const bool& bClear, const wxString& szName,
> char* buffer, size_t len, CURLFORMcode* outErr);
>
>
>
>
> bool AddFileToForm(const bool& bClear, const wxString& szName,
> const wxString& filename, CURLFORMcode* outErr);
>
> protected:
>
> // change access policy to force the user of the better-readable Upload() method:
> virtual wxCurlThreadError StartTransfer()
> { return Post(); }
>
> virtual void *Entry();
>
> wxString m_szName;
> wxString m_szFilepath;
> };
wxcode/components/wxcurl/src/thread.cpp
Code: Select all
> // ---------------------
> // wxCurlFormPostThread
> // ---------------------
>
>
> wxCurlThreadError wxCurlFormPostThread::Post()
> {
> wxCHECK_MSG(!IsAlive(), wxCTE_NO_RESOURCE, wxS("Cannot use this function after the tranfer has begun"));
>
> // create & run this thread
> wxCurlThreadError ret;
> if ((ret=Create(wxCURL_THREAD_STACK_SIZE)) != wxCTE_NO_ERROR)
> return ret;
> if ((ret=Run()) != wxCTE_NO_ERROR)
> return ret;
>
> return wxCTE_NO_ERROR;
> }
>
> wxCurlThreadError wxCurlFormPostThread::Post(const wxString &url)
> {
> wxCurlThreadError ret;
>
> if ((ret=SetURL(url)) != wxCTE_NO_ERROR)
> return ret;
>
> return Post();
> }
>
> void *wxCurlFormPostThread::Entry()
> {
> if (!m_pCurl || !m_pCurl->IsOk())
> return NULL;
>
> // NOTE: the TestDestroy() function will still be called in this thread
> // context by the m_output's OnSysWrite function which in turn is
> // called from libcurl whenever some new data arrives
> if (m_pCurl->IsVerbose())
> wxLogDebug(wxS("wxCurlFormPostThread - uploading to %s"), m_url.c_str());
> switch (m_protocol)
> {
> case wxCP_HTTP:
> {
>
> wxCurlHTTP *http=wx_static_cast(wxCurlHTTP*, m_pCurl);
> return (void*)http->Post(m_url.c_str());
> }
> default:
> wxLogDebug("wxCurlFormPostThread - unknown protocol");
> }
>
> return NULL;
> }
>
>
> bool wxCurlFormPostThread::AddForm(const bool& bClear, const wxString& szName,
> struct curl_forms* pForms, CURLFORMcode* outErr)
> {
> wxCurlHTTP *http=wx_static_cast(wxCurlHTTP*, m_pCurl);
> return http->AddForm(bClear, szName, pForms, outErr);
> }
>
> bool wxCurlFormPostThread::AddBufferToForm(const bool& bClear, const wxString& szName,
> char* buffer, size_t len, CURLFORMcode* outErr)
> {
>
> wxCurlHTTP *http=wx_static_cast(wxCurlHTTP*, m_pCurl);
> return http->AddBufferToForm(bClear, szName, buffer, len, outErr);
>
> }
>
>
>
> bool wxCurlFormPostThread::AddFileToForm(const bool& bClear, const wxString& szName,
> const wxString& filename, CURLFORMcode* outErr)
> {
> wxCurlHTTP *http=wx_static_cast(wxCurlHTTP*, m_pCurl);
> return http->AddFileToForm(bClear, szName, filename,outErr);
>
> }
I also made an wxCurlHTTP::AddFileToForm function for the wxCurlHTTP class. It isn't essential since you can use the wxCurlHTTP::AddForm function to create the parameters yourself, but I thought that it complemented the wxCurlHTTTP::AddBufferToForm function nicely
wxcode/components/wxcurl/src/http.cpp
Code: Select all
> bool wxCurlHTTP::AddFileToForm(const bool& bClear, const wxString& szName,
> const wxString& filename, CURLFORMcode* outErr)
> {
> if(bClear)
> ResetPostData();
>
> CURLFORMcode res = CURL_FORMADD_OK;
>
> res = curl_formadd(&m_pPostHead, &m_pPostTail,
> CURLFORM_COPYNAME,(const char*)szName.ToAscii(),
> CURLFORM_FILE, (const char*)filename.ToAscii(),
> CURLFORM_END);
>
> if (outErr != NULL)
> *outErr = res; // sometimes you want to/need to see what's going on
>
> return (res == CURL_FORMADD_OK);
> }
Code: Select all
44c44,45
<
---
> bool AddFileToForm(const bool& bClear, const wxString& szName,
> const wxString& filename, CURLFORMcode* outErr=NULL);
For anyone working on this
Here's a reference for using cURL forms in libcurl http://curl.haxx.se/libcurl/c/curl_formadd.html.
Here's an example of usage of the wxCurlFormPostThread class
Code: Select all
int threadid=generate_thread_id();
wxCurlFormPostThread *pthread=new wxCurlFormPostThread(parent, threadid);
// set download params
wxCurlThreadError ret=pthread->SetURL(url);
wxASSERT(ret==wxCTE_NO_ERROR);
pthread->GetCurlSession()->SetVerbose(true);
pthread->GetCurlSession()->SetUsername(..);
pthread->GetCurlSession()->SetPassword(..);
pthread->GetCurlSession()->UseProxy(..);
pthread->GetCurlSession()->SetProxyHost(..);
pthread->GetCurlSession()->SetProxyUsername(..);
pthread->GetCurlSession()->SetProxyPassword(..);
pthread->GetCurlSession()->SetProxyPort(..);
CURLFORMcode err;
char cstring[1024];
// assuming you want UTF-8, change the wxConv* parameter as needed
strncpy(cstring, (const char*)"Buffer contents", 1023);
pthread->AddBufferToForm(false,"HTTPFormName",cstring,strlen(cstring),&err);
pthread->AddFileToForm(false,"HTTPFormFileName","filename.txt",&err);
pthread->Post();//hopefully wxCTE_NO_ERROR
Connect(threadid, wxCURL_END_PERFORM_EVENT,
wxCurlEndPerformEventHandler(yourEventHandler));
-Colin