]> git.saurik.com Git - wxWidgets.git/commitdiff
Add SetPostBuffer(wxMemoryBuffer) and SetPostText() to wxHTTP.
authorVadim Zeitlin <vadim@wxwidgets.org>
Fri, 20 Jan 2012 12:22:25 +0000 (12:22 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Fri, 20 Jan 2012 12:22:25 +0000 (12:22 +0000)
This allows to post binary data or text data in e.g. UTF-8 encoding (which is
by far the most common case) easily.

Deprecate the existing SetPostBuffer(wxString) as it didn't explicitly specify
the encoding to use for the data to be posted.

Closes #13870.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@70408 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/changes.txt
include/wx/protocol/http.h
interface/wx/protocol/http.h
src/common/http.cpp

index 37f7217676116fb88de2e290c2b6b7dfd552baff..e3370e520fb44bee396763c6fa749902cbdab846 100644 (file)
@@ -452,6 +452,7 @@ All:
 
 - Added wxLogFormatter to allow customizing wxLog output (Sébastien Gallou).
 - Added "%z" support to wxDateTime::Format() and Parse() (Armel Asselin).
+- Add wxHTTP::SetPostBuffer(wxMemoryBuffer) and SetPostText() (Eran Ifrah).
 
 All (GUI):
 
index 8d3308b7f7de61a2ba10360d10dd3027605fd470..476df9189abcbd38f16b9691b1d2897e5bedcf1e 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "wx/hashmap.h"
 #include "wx/protocol/protocol.h"
+#include "wx/buffer.h"
 
 class WXDLLIMPEXP_NET wxHTTP : public wxProtocol
 {
@@ -36,13 +37,19 @@ public:
     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
     {
@@ -80,7 +87,8 @@ protected:
     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)
index 54ffb4582136ad031fc507643ef76d1537373ba6..fd72c127a5d0a4978c8a354bb9a4e3a8a927808f 100644 (file)
@@ -110,12 +110,51 @@ public:
     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);
 };
 
index e238364ece6c0d5fa72ac3609bae3f44ad5247e5..49f08f6dfb55e5702cc261a4ec06f376da5b1eae 100644 (file)
@@ -48,7 +48,6 @@ wxHTTP::wxHTTP()
     m_addr = NULL;
     m_read = false;
     m_proxy_mode = false;
-    m_post_buf = wxEmptyString;
     m_http_response = 0;
 
     SetNotify(wxSOCKET_LOST_FLAG);
@@ -193,7 +192,41 @@ wxString wxHTTP::GenerateAuthString(const wxString& user, const wxString& pass)
 
 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()
@@ -312,8 +345,21 @@ bool wxHTTP::BuildRequest(const wxString& path, wxHTTP_Req req)
 
         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:
@@ -346,18 +392,10 @@ bool wxHTTP::BuildRequest(const wxString& path, wxHTTP_Req req)
     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;
@@ -483,7 +521,7 @@ wxInputStream *wxHTTP::GetInputStream(const wxString& path)
         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);