Added form POSTing and HTTP error code handling to Webternet (bug 3530, r=pred).
Added form POSTing and HTTP error code handling to Webternet (
bug 3530, r=pred).
1.1 --- a/extensions/curl/curlapi.cpp Sun Feb 01 17:50:44 2009 -0500
1.2 +++ b/extensions/curl/curlapi.cpp Sun Feb 01 19:56:24 2009 -0500
1.3 @@ -2,6 +2,32 @@
1.4
1.5 Webternet g_webternet;
1.6
1.7 +WebForm::WebForm() : first(NULL), last(NULL), lastError(CURL_FORMADD_OK)
1.8 +{
1.9 +}
1.10 +
1.11 +bool WebForm::AddString(const char *name, const char *data)
1.12 +{
1.13 + lastError = curl_formadd(&first,
1.14 + &last,
1.15 + CURLFORM_COPYNAME,
1.16 + name,
1.17 + CURLFORM_COPYCONTENTS,
1.18 + data,
1.19 + CURLFORM_END);
1.20 + return lastError == CURL_FORMADD_OK;
1.21 +}
1.22 +
1.23 +curl_httppost *WebForm::GetFormData()
1.24 +{
1.25 + return first;
1.26 +}
1.27 +
1.28 +WebForm::~WebForm()
1.29 +{
1.30 + curl_formfree(first);
1.31 +}
1.32 +
1.33 WebTransfer *WebTransfer::CreateWebSession()
1.34 {
1.35 CURL *curl;
1.36 @@ -46,6 +72,12 @@
1.37 return lastError == 0;
1.38 }
1.39
1.40 +bool WebTransfer::SetFailOnHTTPError(bool fail)
1.41 +{
1.42 + lastError = curl_easy_setopt(curl, CURLOPT_FAILONERROR, fail ? 1 : 0);
1.43 + return lastError == 0;
1.44 +}
1.45 +
1.46 static size_t curl_write_to_sm(void *ptr, size_t bytes, size_t nmemb, void *stream)
1.47 {
1.48 void **userdata = (void **)stream;
1.49 @@ -81,6 +113,12 @@
1.50 return false;
1.51 }
1.52
1.53 + lastError = curl_easy_setopt(curl, CURLOPT_HTTPPOST, NULL);
1.54 + if (lastError)
1.55 + {
1.56 + return false;
1.57 + }
1.58 +
1.59 lastError = curl_easy_setopt(curl, CURLOPT_URL, url);
1.60 if (lastError)
1.61 {
1.62 @@ -92,6 +130,46 @@
1.63 return (lastError == 0);
1.64 }
1.65
1.66 +bool WebTransfer::PostAndDownload(const char *url,
1.67 + IWebForm *form,
1.68 + ITransferHandler *handler,
1.69 + void *data)
1.70 +{
1.71 + WebForm *realform = (WebForm*)form;
1.72 +
1.73 + lastError = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_to_sm);
1.74 + if (lastError)
1.75 + {
1.76 + return false;
1.77 + }
1.78 +
1.79 + void *userdata[3];
1.80 + userdata[0] = this;
1.81 + userdata[1] = handler;
1.82 + userdata[2] = data;
1.83 + lastError = curl_easy_setopt(curl, CURLOPT_WRITEDATA, userdata);
1.84 + if (lastError)
1.85 + {
1.86 + return false;
1.87 + }
1.88 +
1.89 + lastError = curl_easy_setopt(curl, CURLOPT_HTTPPOST, realform->GetFormData());
1.90 + if (lastError)
1.91 + {
1.92 + return false;
1.93 + }
1.94 +
1.95 + lastError = curl_easy_setopt(curl, CURLOPT_URL, url);
1.96 + if (lastError)
1.97 + {
1.98 + return false;
1.99 + }
1.100 +
1.101 + lastError = curl_easy_perform(curl);
1.102 +
1.103 + return (lastError == 0);
1.104 +}
1.105 +
1.106 WebTransfer::~WebTransfer()
1.107 {
1.108 curl_easy_cleanup(curl);
1.109 @@ -112,3 +190,7 @@
1.110 return WebTransfer::CreateWebSession();
1.111 }
1.112
1.113 +IWebForm *Webternet::CreateForm()
1.114 +{
1.115 + return new WebForm();
1.116 +}
2.1 --- a/extensions/curl/curlapi.h Sun Feb 01 17:50:44 2009 -0500
2.2 +++ b/extensions/curl/curlapi.h Sun Feb 01 19:56:24 2009 -0500
2.3 @@ -37,6 +37,21 @@
2.4
2.5 using namespace SourceMod;
2.6
2.7 +class WebForm : public IWebForm
2.8 +{
2.9 +public:
2.10 + WebForm();
2.11 + ~WebForm();
2.12 +public:
2.13 + bool AddString(const char *name, const char *data);
2.14 +public:
2.15 + curl_httppost *GetFormData();
2.16 +private:
2.17 + curl_httppost *first;
2.18 + curl_httppost *last;
2.19 + CURLFORMcode lastError;
2.20 +};
2.21 +
2.22 class WebTransfer : public IWebTransfer
2.23 {
2.24 public:
2.25 @@ -48,6 +63,11 @@
2.26 int LastErrorCode();
2.27 bool SetHeaderReturn(bool recv_hdr);
2.28 bool Download(const char *url, ITransferHandler *handler, void *data);
2.29 + bool SetFailOnHTTPError(bool fail);
2.30 + bool PostAndDownload(const char *url,
2.31 + IWebForm *form,
2.32 + ITransferHandler *handler,
2.33 + void *data);
2.34 private:
2.35 CURL *curl;
2.36 char errorBuffer[CURL_ERROR_SIZE];
2.37 @@ -61,6 +81,7 @@
2.38 const char *GetInterfaceName();
2.39 public:
2.40 IWebTransfer *CreateSession();
2.41 + IWebForm *CreateForm();
2.42 };
2.43
2.44 extern Webternet g_webternet;
3.1 --- a/public/extensions/IWebternet.h Sun Feb 01 17:50:44 2009 -0500
3.2 +++ b/public/extensions/IWebternet.h Sun Feb 01 19:56:24 2009 -0500
3.3 @@ -40,7 +40,7 @@
3.4 */
3.5
3.6 #define SMINTERFACE_WEBTERNET_NAME "IWebternet"
3.7 -#define SMINTERFACE_WEBTERNET_VERSION 1
3.8 +#define SMINTERFACE_WEBTERNET_VERSION 3
3.9
3.10 namespace SourceMod
3.11 {
3.12 @@ -57,6 +57,31 @@
3.13 class IWebternet;
3.14
3.15 /**
3.16 + * @brief Form for POSTing data.
3.17 + */
3.18 + class IWebForm
3.19 + {
3.20 + public:
3.21 + /**
3.22 + * @brief Free with delete.
3.23 + */
3.24 + virtual ~IWebForm()
3.25 + {
3.26 + }
3.27 + public:
3.28 + /**
3.29 + * @brief Adds raw data to the form.
3.30 + *
3.31 + * All data is copied locally and may go out of scope.
3.32 + *
3.33 + * @param name Field name (null terminated).
3.34 + * @param data Field data (null terminated).
3.35 + * @return True on success, false on failure.
3.36 + */
3.37 + virtual bool AddString(const char *name, const char *data) = 0;
3.38 + };
3.39 +
3.40 + /**
3.41 * @brief Transfer handler interface.
3.42 */
3.43 class ITransferHandler
3.44 @@ -139,6 +164,30 @@
3.45 * @return True on success, false on failure.
3.46 */
3.47 virtual bool Download(const char *url, ITransferHandler *handler, void *data) = 0;
3.48 +
3.49 + /**
3.50 + * @brief Downloads a URL with POST options.
3.51 + *
3.52 + * @param url URL to download.
3.53 + * @param form Form to read POST info from.
3.54 + * @param handler Handler object.
3.55 + * @param userdata User data pointer.
3.56 + * @return True on success, false on failure.
3.57 + */
3.58 + virtual bool PostAndDownload(const char *url,
3.59 + IWebForm *form,
3.60 + ITransferHandler *handler,
3.61 + void *data) = 0;
3.62 +
3.63 + /**
3.64 + * @brief Sets whether an HTTP failure (>= 400) returns false from Download().
3.65 + *
3.66 + * Note: defaults to false.
3.67 + *
3.68 + * @param fail True to fail, false otherwise.
3.69 + * @return True on success, false otherwise.
3.70 + */
3.71 + virtual bool SetFailOnHTTPError(bool fail) = 0;
3.72 };
3.73
3.74 /**
3.75 @@ -156,6 +205,13 @@
3.76 * @return Object, or NULL on failure.
3.77 */
3.78 virtual IWebTransfer *CreateSession() = 0;
3.79 +
3.80 + /**
3.81 + * @brief Creates a form for building POST data.
3.82 + *
3.83 + * @return New form, or NULL on failure.
3.84 + */
3.85 + virtual IWebForm *CreateForm() = 0;
3.86 };
3.87 }
3.88