NetServices Stack source

Dependents:   HelloWorld ServoInterfaceBoardExample1 4180_Lab4

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HTTPMap.cpp Source File

HTTPMap.cpp

00001 
00002 /*
00003 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
00004  
00005 Permission is hereby granted, free of charge, to any person obtaining a copy
00006 of this software and associated documentation files (the "Software"), to deal
00007 in the Software without restriction, including without limitation the rights
00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00009 copies of the Software, and to permit persons to whom the Software is
00010 furnished to do so, subject to the following conditions:
00011  
00012 The above copyright notice and this permission notice shall be included in
00013 all copies or substantial portions of the Software.
00014  
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00018 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00020 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00021 THE SOFTWARE.
00022 */
00023 
00024 #include "HTTPMap.h"
00025 #include "../../util/url.h"
00026 
00027 //#define __DEBUG
00028 #include "dbg/dbg.h"
00029 
00030 HTTPMap::HTTPMap(const string& keyValueSep /*= "="*/, const string& pairSep /*= "&"*/) : 
00031 HTTPData(), Dictionary(), m_buf(), m_len(0), m_chunked(false), m_keyValueSep(keyValueSep), m_pairSep(pairSep)
00032 {
00033 
00034 }
00035 
00036 HTTPMap::~HTTPMap()
00037 {
00038 
00039 }
00040 
00041 void HTTPMap::clear()
00042 {
00043   m_buf.clear();
00044 }
00045 
00046 int HTTPMap::read(char* buf, int len)
00047 {
00048   memcpy( (void*)buf, (void*)m_buf.data(), len );
00049   m_buf.erase(0, len); //Erase these chars
00050   return len;
00051 }
00052 
00053 int HTTPMap::write(const char* buf, int len)
00054 {
00055   m_buf.append( buf, len );
00056   if( ( m_chunked && !len ) || 
00057   ( !m_chunked && ( m_buf.length() >= m_len ) ) ) //Last chunk or EOF
00058   {
00059     parseString();
00060   }
00061   return len;
00062 }
00063   
00064 string HTTPMap::getDataType() //Internet media type for Content-Type header
00065 {
00066   return "application/x-www-form-urlencoded";
00067 }
00068 
00069 void HTTPMap::setDataType(const string& type) //Internet media type from Content-Type header
00070 {
00071   //Do not really care here
00072 }
00073   
00074 int HTTPMap::getDataLen() //For Content-Length header
00075 {
00076   //This will be called before any read occurs, so let's generate our string object
00077   //Generate string
00078   generateString();
00079   return m_len;
00080 }
00081 
00082 bool HTTPMap::getIsChunked() //For Transfer-Encoding header
00083 {
00084   return false; //We don't want to chunk this
00085 }
00086 
00087 void HTTPMap::setIsChunked(bool chunked) //From Transfer-Encoding header
00088 {
00089   m_chunked = chunked;
00090 }
00091 
00092 void HTTPMap::setDataLen(int len) //From Content-Length header, or if the transfer is chunked, next chunk length
00093 {
00094   m_len += len; //Useful so that we can parse string when last byte is written if not chunked
00095   m_buf.reserve( m_len );
00096 }
00097 
00098 void HTTPMap::generateString()
00099 {
00100   Dictionary::iterator it;
00101   bool first = true;
00102   while( !Dictionary::empty() )
00103   {
00104     if(!first)
00105     {
00106       m_buf.append( m_pairSep );
00107     }
00108     else
00109     {
00110       first = false;
00111     }
00112     it = Dictionary::begin();
00113     m_buf.append( Url::encode( (*it).first ) );
00114     m_buf.append( m_keyValueSep );
00115     m_buf.append( Url::encode( (*it).second ) );
00116     Dictionary::erase(it); //Free memory as we process data
00117   }
00118   m_len = m_buf.length();
00119   DBG("\r\nData [len %d]:\r\n%s\r\n", m_len, m_buf.c_str());
00120 }
00121 
00122 void HTTPMap::parseString()
00123 {
00124   string key;
00125   string value;
00126   
00127   int pos = 0;
00128   
00129   int key_pos;
00130   int key_len;
00131   
00132   int value_pos;
00133   int value_len;
00134   
00135   bool eof = false;
00136   while(!eof)
00137   {
00138     key_pos = pos;
00139     value_pos = m_buf.find(m_keyValueSep, pos);
00140     if(value_pos < 0)
00141     {
00142       //Parse error, break
00143       break;
00144     }
00145     
00146     key_len = value_pos - key_pos;
00147     
00148     value_pos+= m_keyValueSep.length();
00149     
00150     pos = m_buf.find( m_pairSep, value_pos );
00151     if(pos < 0) //Not found
00152     {
00153       pos = m_buf.length();
00154       eof = true;
00155     }
00156     
00157     value_len = pos - value_pos;
00158     
00159     pos += m_pairSep.length();
00160     
00161     //Append elenent
00162     Dictionary::operator[]( Url::decode( m_buf.substr(key_pos, key_len) ) ) = Url::decode( m_buf.substr(value_pos, value_len) );
00163   }
00164   
00165   m_buf.clear(); //Free data
00166   
00167 }