HTTP Client data container for form(multipart/form-data)

Dependencies:   mbed EthernetInterface HTTPClient mbed-rtos

Revision:
0:fcd577a3925b
Child:
1:77c616a1ab54
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPPoster.cpp	Thu May 31 10:32:39 2012 +0000
@@ -0,0 +1,184 @@
+
+/*
+Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
+ 
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+ 
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+ 
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "HTTPPoster.h"
+//#define __DEBUG
+//#include "mydbg.h"
+#include "dbg/dbg.h"
+
+///HTTP Client data container for form(multipart/form-data)
+HTTPPoster::HTTPPoster()
+{
+    DBG("\n");
+    m_cur = 0;
+    m_seq = 0;
+    m_send_len = 0;
+    m_fp = NULL;
+    m_post_data.clear();
+    m_buf.clear();
+    m_boundary = "----mbedHTTPClientPoster";
+    m_ContentType = "multipart/form-data; boundary="; 
+    m_ContentType += m_boundary;
+}
+
+HTTPPoster::~HTTPPoster()
+{
+    DBG("m_post_data.size()=%d\n", m_post_data.size());
+    if (m_fp) {
+        fclose(m_fp);
+        m_fp = NULL;
+    }
+}
+
+bool HTTPPoster::addFile(const char* name, const char* path)
+{
+    DBG("%p name=%s path=%s\n", this, name, path);
+    struct stpost data;
+
+    m_fp = fopen(path, "rb");
+    if (m_fp == NULL) {
+        return false;
+    }
+    fseek(m_fp, 0, SEEK_END);
+    data.length = ftell(m_fp);
+    fclose(m_fp);
+
+    string head = "Content-Disposition: form-data; name=\"";
+    head += name;
+    head += "\"; filename=\"";
+    head += path; 
+    head += "\"";
+
+    data.head = head;
+    data.value = path;
+    data.file = true;
+    m_post_data.push_back(data);
+    return true;
+}
+
+bool HTTPPoster::add(const char* name, const char* value)
+{
+    DBG("%p name=%s value=%s\n", this, name, value);
+    struct stpost data;
+
+    string head = "Content-Disposition: form-data; name=\"";
+    head += name;
+    head += "\"";
+
+    data.head = head;
+    data.value = value;
+    data.length = strlen(value);    
+    data.file = false;
+    m_post_data.push_back(data);
+    return true;
+}
+
+int HTTPPoster::read(char* buf, int len)
+{
+    //DBG("buf=%p len=%d\n", buf, len);
+    int c;
+    switch(m_seq) {
+        case 0:
+            if (m_cur >= m_post_data.size()) {
+                m_buf += "--";
+                m_buf += m_boundary;
+                m_buf += "--\r\n";
+                m_seq = 4; // done
+            } else {
+                m_buf += "--";
+                m_buf += m_boundary;
+                m_buf += "\r\n";
+                m_seq++;
+            }
+            break;
+        case 1:
+            m_buf += m_post_data[m_cur].head;
+            m_buf += "\r\n\r\n";
+            if (m_post_data[m_cur].file) {
+                m_fp = fopen(m_post_data[m_cur].value.c_str(), "rb");
+            }
+            m_pos = 0;
+            m_seq++;
+            break;
+        case 2:
+            for(int i = 0; i < len; i++) {
+                if (m_buf.size() >= len) {
+                    break;
+                }
+                if (m_pos >= m_post_data[m_cur].length) {
+                    m_seq++;
+                    break;
+                }
+                if (m_post_data[m_cur].file) {
+                    c = fgetc(m_fp);
+                } else {
+                    c = m_post_data[m_cur].value[m_pos];
+                }
+                m_buf += (char)c;
+                m_pos++;
+            }
+            break;            
+        case 3:
+            m_buf += "\r\n";
+            if (m_fp) {
+                fclose(m_fp);
+                m_fp = NULL;
+            }
+            m_cur++;
+            m_seq = 0;
+            break;
+        default: // done
+            break;
+    }
+    int len2 = m_buf.size();
+    if (len2 > len) {
+        len2 = len;
+    }
+    memcpy(buf, m_buf.data(), len2);
+    m_buf.erase(0, len2);
+    m_send_len += len2;
+    DBG("m_len=%d m_send_len=%d len=%d len2=%d\n", m_len, m_send_len, len, len2);
+    //DBG_HEX((uint8_t*)buf, len2);
+    return len2;
+}
+
+string HTTPPoster::getDataType() //Internet media type for Content-Type header
+{
+    DBG("%s\n", m_ContentType.c_str());
+    return m_ContentType;
+}
+
+int HTTPPoster::getDataLen() //For Content-Length header
+{
+    m_len = 0;
+    for(int i = 0; i < m_post_data.size(); i++) {
+        m_len += 2 + strlen(m_boundary) + 2;      // "--" boundary CRLF
+        m_len += m_post_data[i].head.size() + 2; // Content-Disposition: ... CRLF
+        m_len += 2;                               // CRLF  
+        m_len += m_post_data[i].length;           // value / file body
+        m_len += 2;                               // CRLF
+        DBG("%d m_len=%d\n", i, m_len);
+    }
+    m_len += 2 + strlen(m_boundary) + 2 + 2;   // "--" boundary "--" CRLF
+    return m_len;
+}