1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     HTTP protocol 
   4 // Author:      Guilhem Lavaux 
   6 // Created:     August 1997 
   8 // Copyright:   (c) 1997, 1998 Guilhem Lavaux 
   9 // Licence:     wxWindows license 
  10 ///////////////////////////////////////////////////////////////////////////// 
  13   #pragma implementation "http.h" 
  16 // For compilers that support precompilation, includes "wx.h". 
  17 #include "wx/wxprec.h" 
  27 #include "wx/string.h" 
  28 #include "wx/tokenzr.h" 
  29 #include "wx/socket.h" 
  30 #include "wx/protocol/protocol.h" 
  32 #include "wx/protocol/http.h" 
  33 #include "wx/sckstrm.h" 
  35 #if !USE_SHARED_LIBRARY 
  36 IMPLEMENT_DYNAMIC_CLASS(wxHTTP
, wxProtocol
) 
  37 IMPLEMENT_PROTOCOL(wxHTTP
, _T("http"), _T("80"), TRUE
) 
  40 #define HTTP_BSIZE 2048 
  44     m_headers(wxKEY_STRING
) 
  54   // wxString isn't a wxObject 
  55   wxNode 
*node 
= m_headers
.First(); 
  59     string 
= (wxString 
*)node
->Data(); 
  65 wxString 
wxHTTP::GetContentType() 
  67   return GetHeader(_T("Content-Type")); 
  70 void wxHTTP::SetHeader(const wxString
& header
, const wxString
& h_data
) 
  77   wxNode 
*node 
= m_headers
.Find(header
); 
  80     m_headers
.Append(header
, (wxObject 
*)(new wxString(h_data
))); 
  82     wxString 
*str 
= (wxString 
*)node
->Data(); 
  87 wxString 
wxHTTP::GetHeader(const wxString
& header
) 
  89   wxNode 
*node 
= m_headers
.Find(header
); 
  93   return *((wxString 
*)node
->Data()); 
  96 void wxHTTP::SendHeaders() 
  98   wxNode 
*head 
= m_headers
.First(); 
 102     wxString 
*str 
= (wxString 
*)head
->Data(); 
 105     buf
.Printf(_T("%s: %s\n\r"), head
->GetKeyString(), str
->GetData()); 
 107     const wxWX2MBbuf cbuf 
= buf
.mb_str(); 
 108     Write(cbuf
, strlen(cbuf
)); 
 114 bool wxHTTP::ParseHeaders() 
 117   wxStringTokenizer tokenzr
; 
 123     m_error 
= GetLine(this, line
); 
 124     if (m_error 
!= wxPROTO_NOERR
) 
 127     if (line
.Length() == 0) 
 130     tokenzr
.SetString(line
, " :\t\n\r"); 
 131     if (!tokenzr
.HasMoreTokens()) 
 134     wxString left_str 
= tokenzr
.GetNextToken(); 
 135     wxString 
*str 
= new wxString(tokenzr
.GetNextToken()); 
 137     m_headers
.Append(left_str
, (wxObject 
*) str
); 
 142 bool wxHTTP::Connect(const wxString
& host
) 
 152   m_addr 
= addr 
= new wxIPV4address(); 
 154   if (!addr
->Hostname(host
)) { 
 157     m_error 
= wxPROTO_NETERR
; 
 161   if (!addr
->Service(_T("http"))) 
 167 bool wxHTTP::Connect(wxSockAddress
& addr
, bool WXUNUSED(wait
)) 
 169   struct sockaddr 
*raw_addr
; 
 172   m_addr 
= (wxSockAddress 
*)(addr
.GetClassInfo()->CreateObject()); 
 174   addr
.Build(raw_addr
, len
); 
 175   m_addr
->Disassemble(raw_addr
, len
); 
 180 bool wxHTTP::BuildRequest(const wxString
& path
, wxHTTP_Req req
) 
 183   wxCharBuffer 
buf(""); 
 184   const wxWX2MBbuf pathbuf
; 
 199   tmp_str 
= wxURL::ConvertToValidURI(path
); 
 200   wxSprintf(buf
, _T("%s %s\n\r"), tmp_buf
, tmp_str
.GetData()); 
 201   pathbuf 
= wxConvLibc
.cWX2MB(buf
); 
 202   Write(pathbuf
, strlen(pathbuf
)); 
 206   m_error 
= GetLine(this, tmp_str
); 
 207   if (m_error 
!= wxPROTO_NOERR
) { 
 212   if (!tmp_str
.Contains(_T("HTTP/"))) { 
 213     // TODO: support HTTP v0.9 which can have no header. 
 214     SetHeader(_T("Content-Length"), _T("-1")); 
 215     SetHeader(_T("Content-Type"), _T("none/none")); 
 220   wxStringTokenizer 
token(tmp_str
,_T(' ')); 
 225   tmp_str2 
= token
.NextToken(); 
 227   switch (wxAtoi(tmp_str2
)) { 
 231     m_error 
= wxPROTO_NOFILE
; 
 236   ret_value 
= ParseHeaders(); 
 241 class wxHTTPStream 
: public wxSocketInputStream 
{ 
 246   wxHTTPStream(wxHTTP 
*http
) : wxSocketInputStream(*http
), m_http(http
) {} 
 247   size_t StreamSize() const { return m_httpsize
; } 
 248   virtual ~wxHTTPStream(void) { m_http
->Abort(); } 
 251 bool wxHTTP::Abort(void) 
 253   return wxSocketClient::Close(); 
 256 wxInputStream 
*wxHTTP::GetInputStream(const wxString
& path
) 
 258   wxHTTPStream 
*inp_stream 
= new wxHTTPStream(this); 
 260   if (!m_addr 
|| m_connected
) { 
 261     m_error 
= wxPROTO_CONNERR
; 
 265   if (!wxProtocol::Connect(*m_addr
)) 
 268   if (!BuildRequest(path
, wxHTTP_GET
)) 
 271   wxPrintf(_T("Len = %s\n"), WXSTRINGCAST 
GetHeader(_T("Content-Length"))); 
 272   if (!GetHeader(_T("Content-Length")).IsEmpty()) 
 273     inp_stream
->m_httpsize 
= wxAtoi(WXSTRINGCAST 
GetHeader(_T("Content-Length")));