Added form POSTing and HTTP error code handling to Webternet (bug 3530, r=pred).
authorDavid Anderson <dvander@alliedmods.net>
Sun Feb 01 19:56:24 2009 -0500 (2009-02-01)
changeset 2554ce7f3b1b0529
parent 2553 6b5a76adefd9
child 2555 ce70871a404b
Added form POSTing and HTTP error code handling to Webternet (bug 3530, r=pred).
extensions/curl/curlapi.cpp
extensions/curl/curlapi.h
public/extensions/IWebternet.h
     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