Logo
~Sockets~
~Examples~
~Contact~


HTTPSocket.cpp

Go to the documentation of this file.
00001 
00005 /*
00006 Copyright (C) 2004-2007  Anders Hedstrom
00007 
00008 This library is made available under the terms of the GNU GPL.
00009 
00010 If you would like to use this library in a closed-source application,
00011 a separate license agreement is available. For information about 
00012 the closed-source license agreement for the C++ sockets library,
00013 please visit http://www.alhem.net/Sockets/license.html and/or
00014 email license@alhem.net.
00015 
00016 This program is free software; you can redistribute it and/or
00017 modify it under the terms of the GNU General Public License
00018 as published by the Free Software Foundation; either version 2
00019 of the License, or (at your option) any later version.
00020 
00021 This program is distributed in the hope that it will be useful,
00022 but WITHOUT ANY WARRANTY; without even the implied warranty of
00023 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024 GNU General Public License for more details.
00025 
00026 You should have received a copy of the GNU General Public License
00027 along with this program; if not, write to the Free Software
00028 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00029 */
00030 #ifdef _WIN32
00031 #pragma warning(disable:4786)
00032 #endif
00033 #include "HTTPSocket.h"
00034 #include <stdarg.h>
00035 #include "Parse.h"
00036 #include "ISocketHandler.h"
00037 
00038 #ifdef SOCKETS_NAMESPACE
00039 namespace SOCKETS_NAMESPACE {
00040 #endif
00041 
00042 
00043 
00044 
00045 HTTPSocket::HTTPSocket(ISocketHandler& h)
00046 :TcpSocket(h)
00047 ,m_first(true)
00048 ,m_header(true)
00049 ,m_http_version("HTTP/1.0")
00050 ,m_request(false)
00051 ,m_response(false)
00052 {
00053         SetLineProtocol();
00054         DisableInputBuffer();
00055 }
00056 
00057 
00058 HTTPSocket::~HTTPSocket()
00059 {
00060 }
00061 
00062 
00063 void HTTPSocket::OnRawData(const char *buf,size_t len)
00064 {
00065         if (!m_header)
00066         {
00067                 OnData(buf, len);
00068         }
00069 }
00070 
00071 
00072 void HTTPSocket::OnLine(const std::string& line)
00073 {
00074         if (m_first)
00075         {
00076                 Parse pa(line);
00077                 std::string str = pa.getword();
00078                 if (str.substr(0,4) == "HTTP") // response
00079                 {
00080                         m_http_version = str;
00081                         m_status = pa.getword();
00082                         m_status_text = pa.getrest();
00083                         m_response = true;
00084                 }
00085                 else // request
00086                 {
00087                         m_method = str;
00088                         m_url = pa.getword();
00089                         size_t spl = m_url.find("?");
00090                         if (spl != std::string::npos)
00091                         {
00092                                 m_uri = m_url.substr(0,spl);
00093                                 m_query_string = m_url.substr(spl + 1);
00094                         }
00095                         else
00096                         {
00097                                 m_uri = m_url;
00098                         }
00099                         m_http_version = pa.getword();
00100                         m_request = true;
00101                 }
00102                 m_first = false;
00103                 OnFirst();
00104                 return;
00105         }
00106         if (!line.size())
00107         {
00108                 SetLineProtocol(false);
00109                 m_header = false;
00110                 OnHeaderComplete();
00111                 return;
00112         }
00113         Parse pa(line,":");
00114         std::string key = pa.getword();
00115         std::string value = pa.getrest();
00116         OnHeader(key,value);
00117         /* If remote end tells us to keep connection alive, and we're operating
00118         in http/1.1 mode (not http/1.0 mode), then we mark the socket to be
00119         retained. */
00120 #ifdef ENABLE_POOL
00121         if (!strcasecmp(key.c_str(), "connection") &&
00122             !strcasecmp(value.c_str(), "keep-alive") )
00123         {
00124                 SetRetain();
00125         }
00126 #endif
00127 }
00128 
00129 
00130 void HTTPSocket::SendResponse()
00131 {
00132         std::string msg;
00133         msg = m_http_version + " " + m_status + " " + m_status_text + "\r\n";
00134         for (string_m::iterator it = m_response_header.begin(); it != m_response_header.end(); it++)
00135         {
00136                 std::string key = (*it).first;
00137                 std::string val = (*it).second;
00138                 msg += key + ": " + val + "\r\n";
00139         }
00140         msg += "\r\n";
00141         Send( msg );
00142 }
00143 
00144 
00145 void HTTPSocket::AddResponseHeader(const std::string& header, const char *format, ...)
00146 {
00147         char slask[5000]; // temporary for vsprintf / vsnprintf
00148         va_list ap;
00149 
00150         va_start(ap, format);
00151 #ifdef _WIN32
00152         vsprintf(slask, format, ap);
00153 #else
00154         vsnprintf(slask, 5000, format, ap);
00155 #endif
00156         va_end(ap);
00157 
00158         m_response_header[header] = slask;
00159 }
00160 
00161 
00162 void HTTPSocket::SendRequest()
00163 {
00164         std::string msg;
00165         msg = m_method + " " + m_url + " " + m_http_version + "\r\n";
00166         for (string_m::iterator it = m_response_header.begin(); it != m_response_header.end(); it++)
00167         {
00168                 std::string key = (*it).first;
00169                 std::string val = (*it).second;
00170                 msg += key + ": " + val + "\r\n";
00171         }
00172         msg += "\r\n";
00173         Send( msg );
00174 }
00175 
00176 
00177 std::string HTTPSocket::MyUseragent()
00178 {
00179         std::string version = "C++Sockets/";
00180 #ifdef _VERSION
00181         version += _VERSION;
00182 #endif
00183         return version;
00184 }
00185 
00186 
00187 void HTTPSocket::Reset()
00188 {
00189         m_first = true;
00190         m_header = true;
00191         m_request = false;
00192         m_response = false;
00193         SetLineProtocol(true);
00194         while (m_response_header.size())
00195         {
00196                 string_m::iterator it = m_response_header.begin();
00197                 m_response_header.erase(it);
00198         }
00199 
00200 }
00201 
00202 
00203 const std::string& HTTPSocket::GetMethod()
00204 {
00205         return m_method;
00206 }
00207 
00208 
00209 void HTTPSocket::SetMethod(const std::string& x)
00210 {
00211         m_method = x;
00212 }
00213 
00214 
00215 const std::string& HTTPSocket::GetUrl()
00216 {
00217         return m_url;
00218 }
00219 
00220 
00221 void HTTPSocket::SetUrl(const std::string& x)
00222 {
00223         m_url = x;
00224 }
00225 
00226 
00227 const std::string& HTTPSocket::GetUri()
00228 {
00229         return m_uri;
00230 }
00231 
00232 
00233 const std::string& HTTPSocket::GetQueryString()
00234 {
00235         return m_query_string;
00236 }
00237 
00238 
00239 const std::string& HTTPSocket::GetHttpVersion()
00240 {
00241         return m_http_version;
00242 }
00243 
00244 
00245 const std::string& HTTPSocket::GetStatus()
00246 {
00247         return m_status;
00248 }
00249 
00250 
00251 const std::string& HTTPSocket::GetStatusText()
00252 {
00253         return m_status_text;
00254 }
00255 
00256 
00257 bool HTTPSocket::IsRequest()
00258 {
00259         return m_request;
00260 }
00261 
00262 
00263 bool HTTPSocket::IsResponse()
00264 {
00265         return m_response;
00266 }
00267 
00268 
00269 void HTTPSocket::SetHttpVersion(const std::string& x)
00270 {
00271         m_http_version = x;
00272 }
00273 
00274 
00275 void HTTPSocket::SetStatus(const std::string& x)
00276 {
00277         m_status = x;
00278 }
00279 
00280 
00281 void HTTPSocket::SetStatusText(const std::string& x)
00282 {
00283         m_status_text = x;
00284 }
00285 
00286 
00287 void HTTPSocket::AddResponseHeader(const std::string& x,const std::string& y)
00288 {
00289         m_response_header[x] = y;
00290 }
00291 
00292 
00293 void HTTPSocket::SetUri(const std::string& x)
00294 {
00295         m_uri = x;
00296 }
00297 
00298 
00299 void HTTPSocket::url_this(const std::string& url_in,std::string& protocol,std::string& host,port_t& port,std::string& url,std::string& file)
00300 {
00301         Parse pa(url_in,"/");
00302         protocol = pa.getword(); // http
00303         if (!strcasecmp(protocol.c_str(), "https:"))
00304         {
00305 #ifdef HAVE_OPENSSL
00306                 EnableSSL();
00307 #else
00308                 Handler().LogError(this, "url_this", -1, "SSL not available", LOG_LEVEL_WARNING);
00309 #endif
00310                 port = 443;
00311         }
00312         else
00313         {
00314                 port = 80;
00315         }
00316         host = pa.getword();
00317         if (strstr(host.c_str(),":"))
00318         {
00319                 Parse pa(host,":");
00320                 pa.getword(host);
00321                 port = static_cast<port_t>(pa.getvalue());
00322         }
00323         url = "/" + pa.getrest();
00324         {
00325                 Parse pa(url,"/");
00326                 std::string tmp = pa.getword();
00327                 while (tmp.size())
00328                 {
00329                         file = tmp;
00330                         tmp = pa.getword();
00331                 }
00332         }
00333 } // url_this
00334 
00335 
00336 #ifdef SOCKETS_NAMESPACE
00337 }
00338 #endif
00339 
Page, code, and content Copyright (C) 2007 by Anders Hedström
Generated for C++ Sockets by  doxygen 1.4.4