Added form POSTing and HTTP error code handling to Webternet (bug 3530, r=pred).
This commit is contained in:
		
							parent
							
								
									7b6dcfce87
								
							
						
					
					
						commit
						0cf5f4ae2a
					
				| @ -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(); | ||||||
|  | } | ||||||
|  | |||||||
| @ -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; | ||||||
|  | |||||||
| @ -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; | ||||||
| 	}; | 	}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user