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
)
49 SetNotify(GSOCK_LOST_FLAG
);
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_perr
= GetLine(this, line
);
124 if (m_perr
!= 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_perr
= wxPROTO_NETERR
;
161 if (!addr
->Service(_T("http")))
167 bool wxHTTP::Connect(wxSockAddress
& addr
, bool WXUNUSED(wait
))
175 m_addr
= (wxSockAddress
*) addr
.Clone();
179 bool wxHTTP::BuildRequest(const wxString
& path
, wxHTTP_Req req
)
182 wxChar buf
[200]; // 200 is arbitrary.
184 wxWX2MBbuf
pathbuf((size_t)200);
186 const wxWX2MBbuf pathbuf
;
202 tmp_str
= wxURL::ConvertToValidURI(path
);
203 wxSprintf(buf
, _T("%s %s HTTP/1.0\n\r"), tmp_buf
, tmp_str
.GetData());
204 pathbuf
= wxConvLibc
.cWX2MB(buf
);
205 Write(pathbuf
, strlen(MBSTRINGCAST pathbuf
));
209 m_perr
= GetLine(this, tmp_str
);
210 if (m_perr
!= wxPROTO_NOERR
) {
215 if (!tmp_str
.Contains(_T("HTTP/"))) {
216 // TODO: support HTTP v0.9 which can have no header.
217 SetHeader(_T("Content-Length"), _T("-1"));
218 SetHeader(_T("Content-Type"), _T("none/none"));
223 wxStringTokenizer
token(tmp_str
,_T(' '));
228 tmp_str2
= token
.NextToken();
230 switch (wxAtoi(tmp_str2
)) {
234 m_perr
= wxPROTO_NOFILE
;
239 ret_value
= ParseHeaders();
244 class wxHTTPStream
: public wxSocketInputStream
{
248 unsigned long m_read_bytes
;
250 wxHTTPStream(wxHTTP
*http
) : wxSocketInputStream(*http
), m_http(http
) {}
251 size_t StreamSize() const { return m_httpsize
; }
252 virtual ~wxHTTPStream(void) { m_http
->Abort(); }
255 size_t OnSysRead(void *buffer
, size_t bufsize
);
258 size_t wxHTTPStream::OnSysRead(void *buffer
, size_t bufsize
)
262 if (m_httpsize
> 0 && m_read_bytes
>= m_httpsize
)
265 ret
= wxSocketInputStream::OnSysRead(buffer
, bufsize
);
271 bool wxHTTP::Abort(void)
273 return wxSocketClient::Close();
276 wxInputStream
*wxHTTP::GetInputStream(const wxString
& path
)
278 wxHTTPStream
*inp_stream
= new wxHTTPStream(this);
280 if (!m_addr
|| m_connected
) {
281 m_perr
= wxPROTO_CONNERR
;
285 if (!wxProtocol::Connect(*m_addr
))
288 if (!BuildRequest(path
, wxHTTP_GET
))
291 if (!GetHeader(_T("Content-Length")).IsEmpty())
292 inp_stream
->m_httpsize
= wxAtoi(WXSTRINGCAST
GetHeader(_T("Content-Length")));
294 inp_stream
->m_httpsize
= (size_t)-1;
296 inp_stream
->m_read_bytes
= 0;