Added form POSTing and HTTP error code handling to Webternet (bug 3530, r=pred).

This commit is contained in:
David Anderson 2009-02-01 19:56:24 -05:00
parent 7b6dcfce87
commit 0cf5f4ae2a
3 changed files with 160 additions and 1 deletions

View File

@ -2,6 +2,32 @@
Webternet g_webternet; Webternet g_webternet;
WebForm::WebForm() : first(NULL), last(NULL), lastError(CURL_FORMADD_OK)
{
}
bool WebForm::AddString(const char *name, const char *data)
{
lastError = curl_formadd(&first,
&last,
CURLFORM_COPYNAME,
name,
CURLFORM_COPYCONTENTS,
data,
CURLFORM_END);
return lastError == CURL_FORMADD_OK;
}
curl_httppost *WebForm::GetFormData()
{
return first;
}
WebForm::~WebForm()
{
curl_formfree(first);
}
WebTransfer *WebTransfer::CreateWebSession() WebTransfer *WebTransfer::CreateWebSession()
{ {
CURL *curl; CURL *curl;
@ -46,6 +72,12 @@ bool WebTransfer::SetHeaderReturn(bool recv_hdr)
return lastError == 0; return lastError == 0;
} }
bool WebTransfer::SetFailOnHTTPError(bool fail)
{
lastError = curl_easy_setopt(curl, CURLOPT_FAILONERROR, fail ? 1 : 0);
return lastError == 0;
}
static size_t curl_write_to_sm(void *ptr, size_t bytes, size_t nmemb, void *stream) static size_t curl_write_to_sm(void *ptr, size_t bytes, size_t nmemb, void *stream)
{ {
void **userdata = (void **)stream; void **userdata = (void **)stream;
@ -81,6 +113,52 @@ bool WebTransfer::Download(const char *url, ITransferHandler *handler, void *dat
return false; return false;
} }
lastError = curl_easy_setopt(curl, CURLOPT_HTTPPOST, NULL);
if (lastError)
{
return false;
}
lastError = curl_easy_setopt(curl, CURLOPT_URL, url);
if (lastError)
{
return false;
}
lastError = curl_easy_perform(curl);
return (lastError == 0);
}
bool WebTransfer::PostAndDownload(const char *url,
IWebForm *form,
ITransferHandler *handler,
void *data)
{
WebForm *realform = (WebForm*)form;
lastError = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_to_sm);
if (lastError)
{
return false;
}
void *userdata[3];
userdata[0] = this;
userdata[1] = handler;
userdata[2] = data;
lastError = curl_easy_setopt(curl, CURLOPT_WRITEDATA, userdata);
if (lastError)
{
return false;
}
lastError = curl_easy_setopt(curl, CURLOPT_HTTPPOST, realform->GetFormData());
if (lastError)
{
return false;
}
lastError = curl_easy_setopt(curl, CURLOPT_URL, url); lastError = curl_easy_setopt(curl, CURLOPT_URL, url);
if (lastError) if (lastError)
{ {
@ -112,3 +190,7 @@ IWebTransfer *Webternet::CreateSession()
return WebTransfer::CreateWebSession(); return WebTransfer::CreateWebSession();
} }
IWebForm *Webternet::CreateForm()
{
return new WebForm();
}

View File

@ -37,6 +37,21 @@
using namespace SourceMod; using namespace SourceMod;
class WebForm : public IWebForm
{
public:
WebForm();
~WebForm();
public:
bool AddString(const char *name, const char *data);
public:
curl_httppost *GetFormData();
private:
curl_httppost *first;
curl_httppost *last;
CURLFORMcode lastError;
};
class WebTransfer : public IWebTransfer class WebTransfer : public IWebTransfer
{ {
public: public:
@ -48,6 +63,11 @@ public:
int LastErrorCode(); int LastErrorCode();
bool SetHeaderReturn(bool recv_hdr); bool SetHeaderReturn(bool recv_hdr);
bool Download(const char *url, ITransferHandler *handler, void *data); bool Download(const char *url, ITransferHandler *handler, void *data);
bool SetFailOnHTTPError(bool fail);
bool PostAndDownload(const char *url,
IWebForm *form,
ITransferHandler *handler,
void *data);
private: private:
CURL *curl; CURL *curl;
char errorBuffer[CURL_ERROR_SIZE]; char errorBuffer[CURL_ERROR_SIZE];
@ -61,6 +81,7 @@ public:
const char *GetInterfaceName(); const char *GetInterfaceName();
public: public:
IWebTransfer *CreateSession(); IWebTransfer *CreateSession();
IWebForm *CreateForm();
}; };
extern Webternet g_webternet; extern Webternet g_webternet;

View File

@ -40,7 +40,7 @@
*/ */
#define SMINTERFACE_WEBTERNET_NAME "IWebternet" #define SMINTERFACE_WEBTERNET_NAME "IWebternet"
#define SMINTERFACE_WEBTERNET_VERSION 1 #define SMINTERFACE_WEBTERNET_VERSION 3
namespace SourceMod namespace SourceMod
{ {
@ -56,6 +56,31 @@ namespace SourceMod
class IWebTransfer; class IWebTransfer;
class IWebternet; class IWebternet;
/**
* @brief Form for POSTing data.
*/
class IWebForm
{
public:
/**
* @brief Free with delete.
*/
virtual ~IWebForm()
{
}
public:
/**
* @brief Adds raw data to the form.
*
* All data is copied locally and may go out of scope.
*
* @param name Field name (null terminated).
* @param data Field data (null terminated).
* @return True on success, false on failure.
*/
virtual bool AddString(const char *name, const char *data) = 0;
};
/** /**
* @brief Transfer handler interface. * @brief Transfer handler interface.
*/ */
@ -139,6 +164,30 @@ namespace SourceMod
* @return True on success, false on failure. * @return True on success, false on failure.
*/ */
virtual bool Download(const char *url, ITransferHandler *handler, void *data) = 0; virtual bool Download(const char *url, ITransferHandler *handler, void *data) = 0;
/**
* @brief Downloads a URL with POST options.
*
* @param url URL to download.
* @param form Form to read POST info from.
* @param handler Handler object.
* @param userdata User data pointer.
* @return True on success, false on failure.
*/
virtual bool PostAndDownload(const char *url,
IWebForm *form,
ITransferHandler *handler,
void *data) = 0;
/**
* @brief Sets whether an HTTP failure (>= 400) returns false from Download().
*
* Note: defaults to false.
*
* @param fail True to fail, false otherwise.
* @return True on success, false otherwise.
*/
virtual bool SetFailOnHTTPError(bool fail) = 0;
}; };
/** /**
@ -156,6 +205,13 @@ namespace SourceMod
* @return Object, or NULL on failure. * @return Object, or NULL on failure.
*/ */
virtual IWebTransfer *CreateSession() = 0; virtual IWebTransfer *CreateSession() = 0;
/**
* @brief Creates a form for building POST data.
*
* @return New form, or NULL on failure.
*/
virtual IWebForm *CreateForm() = 0;
}; };
} }