]> git.tdb.fi Git - libs/net.git/blobdiff - source/message.cpp
Initial revision
[libs/net.git] / source / message.cpp
diff --git a/source/message.cpp b/source/message.cpp
new file mode 100644 (file)
index 0000000..a8851fa
--- /dev/null
@@ -0,0 +1,113 @@
+/* $Id$
+
+This file is part of libmsphttp
+Copyright © 2008  Mikkosoft Productions, Mikko Rasa
+Distributed under the LGPL
+*/
+
+#include <cstdlib>
+#include <msp/strings/formatter.h>
+#include <msp/strings/utils.h>
+#include "message.h"
+
+using namespace std;
+
+#include <iostream>
+
+namespace Msp {
+namespace Http {
+
+void Message::set_header(const string &hdr, const string &val)
+{
+       headers[tolower(hdr)]=val;
+}
+
+const string &Message::get_header(const string &hdr) const
+{
+       HeaderMap::const_iterator i=headers.find(hdr);
+       if(i==headers.end())
+               throw KeyError(format("Header %s is not defined", hdr));
+
+       return i->second;
+}
+
+void Message::add_data(const string &d)
+{
+       data+=d;
+       if(headers.count("content-type")==0)
+               set_header("content-type", "text/plain");
+       set_header("content-length", lexical_cast(data.size()));
+}
+
+unsigned Message::parse_data(const string &d)
+{
+       if(complete)
+               return 0;
+
+       HeaderMap::const_iterator i=headers.find("content-length");
+       if(i!=headers.end())
+       {
+               unsigned needed=lexical_cast<unsigned>(i->second)-data.size();
+               unsigned len=min(needed, d.size());
+               
+               data.append(d, 0, len);
+
+               if(len==needed)
+                       complete=true;
+               
+               return len;
+       }
+
+       i=headers.find("transfer-encoding");
+       if(i!=headers.end() && strcasecmp(i->second, "chunked")==0)
+       {
+               unsigned pos=0;
+               while(!complete && pos<d.size())
+               {
+                       if(chunk_length==0)
+                       {
+                               unsigned lf=d.find('\n', pos);
+                               if(lf==string::npos)
+                                       return pos;
+                               // XXX strtoul
+                               chunk_length=strtoul(strip(d.substr(pos, lf-pos)).c_str(), 0, 16);
+                               if(chunk_length==0)
+                                       complete=true;
+                               pos=lf+1;
+                       }
+                       else
+                       {
+                               unsigned len=min(chunk_length, d.size()-pos);
+                               data.append(d, pos, len);
+                               chunk_length-=len;
+                               if((pos=d.find('\n', pos+len))!=string::npos)
+                                       ++pos;
+                       }
+               }
+
+               return pos;
+       }
+
+       return 0;
+}
+
+Message::Message():
+       http_version(0x11),
+       chunk_length(0),
+       complete(false)
+{ }
+
+string Message::str_common() const
+{
+       string result;
+
+       for(HeaderMap::const_iterator i=headers.begin(); i!=headers.end(); ++i)
+               result+=format("%s: %s\r\n", i->first, i->second);
+       result+="\r\n";
+       result+=data;
+
+       return result;
+}
+
+} // namespace Http
+} // namespace Msp