#include "wx/hashmap.h"
#include "wx/protocol/protocol.h"
+#include "wx/buffer.h"
class WXDLLIMPEXP_NET wxHTTP : public wxProtocol
{
int GetResponse() const { return m_http_response; }
void SetHeader(const wxString& header, const wxString& h_data);
- void SetPostBuffer(const wxString& post_buf);
+ bool SetPostText(const wxString& contentType,
+ const wxString& data,
+ const wxMBConv& conv = wxConvUTF8);
+ bool SetPostBuffer(const wxString& contentType, const wxMemoryBuffer& data);
void SetProxyMode(bool on);
/* Cookies */
wxString GetCookie(const wxString& cookie) const;
bool HasCookies() const { return m_cookies.size() > 0; }
+ // Use the other SetPostBuffer() overload or SetPostText() instead.
+ wxDEPRECATED(void SetPostBuffer(const wxString& post_buf));
+
protected:
enum wxHTTP_Req
{
bool m_read,
m_proxy_mode;
wxSockAddress *m_addr;
- wxString m_post_buf;
+ wxMemoryBuffer m_postBuffer;
+ wxString m_contentType;
int m_http_response;
DECLARE_DYNAMIC_CLASS(wxHTTP)
bool HasCookies() const;
/**
- Set the data to be posted to the server.
+ Set the binary data to be posted to the server.
- If a non-empty string is passed to this method, the next request will
- be an HTTP @c POST instead of the default HTTP @c GET and the data from
- @a post_buf will be posted as the body of this request.
+ If a non-empty buffer is passed to this method, the next request will
+ be an HTTP @c POST instead of the default HTTP @c GET and the given @a
+ data will be posted as the body of this request.
+
+ For textual data a more convenient SetPostText() can be used instead.
+
+ @param contentType
+ The value of HTTP "Content-Type" header, e.g. "image/png".
+ @param data
+ The data to post.
+ @return
+ @true if any data was passed in or @false if the buffer was empty.
+
+ @since 2.9.4
+ */
+ bool SetPostBuffer(const wxString& contentType, const wxMemoryBuffer& data);
+
+ /**
+ Set the text to be posted to the server.
+
+ After a successful call to this method, the request will use HTTP @c
+ POST instead of the default @c GET when it's executed.
+
+ Use SetPostBuffer() if you need to post non-textual data.
+
+ @param contentType
+ The value of HTTP "Content-Type" header, e.g. "text/html;
+ charset=UTF-8".
+ @param data
+ The data to post.
+ @param conv
+ The conversion to use to convert @a data contents to a byte stream.
+ Its value should be consistent with the charset parameter specified
+ in @a contentType.
+ @return
+ @true if string was non-empty and was successfully converted using
+ the given @a conv or @false otherwise (in this case this request
+ won't be @c POST'ed correctly).
+
+ @since 2.9.4
*/
- void SetPostBuffer(const wxString& post_buf);
+ bool SetPostText(const wxString& contentType,
+ const wxString& data,
+ const wxMBConv& conv = wxConvUTF8);
};
m_addr = NULL;
m_read = false;
m_proxy_mode = false;
- m_post_buf = wxEmptyString;
m_http_response = 0;
SetNotify(wxSOCKET_LOST_FLAG);
void wxHTTP::SetPostBuffer(const wxString& post_buf)
{
- m_post_buf = post_buf;
+ // Use To8BitData() for backwards compatibility in this deprecated method.
+ // The new code should use the other overload or SetPostText() and specify
+ // the encoding to use for the text explicitly.
+ wxScopedCharBuffer scb = post_buf.To8BitData();
+ if ( scb.length() )
+ {
+ m_postBuffer.Clear();
+ m_postBuffer.AppendData(scb.data(), scb.length());
+ }
+}
+
+bool
+wxHTTP::SetPostBuffer(const wxString& contentType,
+ const wxMemoryBuffer& data)
+{
+ m_postBuffer = data;
+ m_contentType = contentType;
+
+ return !m_postBuffer.IsEmpty();
+}
+
+bool
+wxHTTP::SetPostText(const wxString& contentType,
+ const wxString& data,
+ const wxMBConv& conv)
+{
+ wxScopedCharBuffer scb = data.mb_str(conv);
+ if ( !scb.length() )
+ return false;
+
+ m_postBuffer.Clear();
+ m_postBuffer.AppendData(scb.data(), scb.length());
+ m_contentType = contentType;
+
+ return true;
}
void wxHTTP::SendHeaders()
case wxHTTP_POST:
request = wxT("POST");
- if ( GetHeader( wxT("Content-Length") ).empty() )
- SetHeader( wxT("Content-Length"), wxString::Format( wxT("%lu"), (unsigned long)m_post_buf.Len() ) );
+ // Content length must be correct, so always set, possibly
+ // overriding the value set explicitly by a previous call to
+ // SetHeader("Content-Length").
+ if ( !m_postBuffer.IsEmpty() )
+ {
+ wxString len;
+ len << m_postBuffer.GetDataLen();
+
+ SetHeader(wxS("Content-Length"), len);
+ }
+
+ // However if the user had explicitly set the content type, don't
+ // override it with the content type passed to SetPostText().
+ if ( !m_contentType.empty() && GetContentType().empty() )
+ SetHeader(wxS("Content-Type"), m_contentType);
break;
default:
Write("\r\n", 2);
if ( req == wxHTTP_POST ) {
- // Post data can be arbitrary binary data when the "binary" content
- // transfer encoding is used so don't assume it's ASCII only or
- // NUL-terminated.
- {
- const wxScopedCharBuffer buf(m_post_buf.To8BitData());
- Write(buf, buf.length());
- } // delete the buffer before modifying the string it points to, it
- // wouldn't really be a problem here even if we didn't do this
- // because we won't use this buffer again but this will avoid any
- // nasty surprises in the future if this code changes
-
- m_post_buf = wxEmptyString;
+ if ( !m_postBuffer.IsEmpty() )
+ Write(m_postBuffer.GetData(), m_postBuffer.GetDataLen());
+
+ m_postBuffer.Clear();
}
wxString tmp_str;
return NULL;
#endif
- if (!BuildRequest(path, m_post_buf.empty() ? wxHTTP_GET : wxHTTP_POST))
+ if (!BuildRequest(path, m_postBuffer.IsEmpty() ? wxHTTP_GET : wxHTTP_POST))
return NULL;
inp_stream = new wxHTTPStream(this);