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"
31 #include "wx/protocol/http.h"
32 #include "wx/sckstrm.h"
34 #if !USE_SHARED_LIBRARY
35 IMPLEMENT_DYNAMIC_CLASS(wxHTTP
, wxProtocol
)
36 IMPLEMENT_PROTOCOL(wxHTTP
, _T("http"), _T("80"), TRUE
)
39 #define HTTP_BSIZE 2048
43 m_headers(wxKEY_STRING
)
53 // wxString isn't a wxObject
54 wxNode
*node
= m_headers
.First();
58 string
= (wxString
*)node
->Data();
64 wxString
wxHTTP::GetContentType()
66 return GetHeader(_T("Content-Type"));
69 void wxHTTP::SetHeader(const wxString
& header
, const wxString
& h_data
)
76 wxNode
*node
= m_headers
.Find(header
);
79 m_headers
.Append(header
, (wxObject
*)(new wxString(h_data
)));
81 wxString
*str
= (wxString
*)node
->Data();
86 wxString
wxHTTP::GetHeader(const wxString
& header
)
88 wxNode
*node
= m_headers
.Find(header
);
92 return *((wxString
*)node
->Data());
95 void wxHTTP::SendHeaders()
97 wxNode
*head
= m_headers
.First();
101 wxString
*str
= (wxString
*)head
->Data();
104 buf
.Printf(_T("%s: %s\n\r"), head
->GetKeyString(), str
->GetData());
106 const wxWX2MBbuf cbuf
= buf
.mb_str();
107 Write(cbuf
, strlen(cbuf
));
113 bool wxHTTP::ParseHeaders()
116 wxStringTokenizer tokenzr
;
122 m_error
= GetLine(this, line
);
123 if (m_error
!= wxPROTO_NOERR
)
126 if (line
.Length() == 0)
129 tokenzr
.SetString(line
, " :\t\n\r");
130 if (!tokenzr
.HasMoreTokens())
133 wxString left_str
= tokenzr
.GetNextToken();
134 wxString
*str
= new wxString(tokenzr
.GetNextToken());
136 m_headers
.Append(left_str
, (wxObject
*) str
);
141 bool wxHTTP::Connect(const wxString
& host
)
151 m_addr
= addr
= new wxIPV4address();
153 if (!addr
->Hostname(host
)) {
156 m_error
= wxPROTO_NETERR
;
160 if (!addr
->Service(_T("http")))
166 bool wxHTTP::Connect(wxSockAddress
& addr
, bool WXUNUSED(wait
))
168 struct sockaddr
*raw_addr
;
171 m_addr
= (wxSockAddress
*)(addr
.GetClassInfo()->CreateObject());
173 addr
.Build(raw_addr
, len
);
174 m_addr
->Disassemble(raw_addr
, len
);
179 bool wxHTTP::BuildRequest(const wxString
& path
, wxHTTP_Req req
)
182 char buf
[HTTP_BSIZE
];
183 const wxWX2MBbuf pathbuf
= path
.mb_str();
197 sprintf(buf
, "%s %s\n\r", tmp_buf
, (const char*) pathbuf
);
198 Write(buf
, strlen(buf
));
200 sprintf(buf
, "\n\r");
201 Write(buf
, strlen(buf
));
205 m_error
= GetLine(this, tmp_str
);
206 if (m_error
!= wxPROTO_NOERR
) {
211 if (!tmp_str
.Contains(_T("HTTP/"))) {
212 // TODO: support HTTP v0.9 which can have no header.
213 SetHeader(_T("Content-Length"), _T("-1"));
214 SetHeader(_T("Content-Type"), _T("none/none"));
219 wxStringTokenizer
token(tmp_str
,_T(' '));
224 tmp_str2
= token
.NextToken();
226 switch (wxAtoi(tmp_str2
)) {
230 m_error
= wxPROTO_NOFILE
;
235 ret_value
= ParseHeaders();
240 class wxHTTPStream
: public wxSocketInputStream
{
245 wxHTTPStream(wxHTTP
*http
) : wxSocketInputStream(*http
), m_http(http
) {}
246 size_t StreamSize() const { return m_httpsize
; }
247 virtual ~wxHTTPStream(void) { m_http
->Abort(); }
250 bool wxHTTP::Abort(void)
252 return wxSocketClient::Close();
255 wxInputStream
*wxHTTP::GetInputStream(const wxString
& path
)
257 wxHTTPStream
*inp_stream
= new wxHTTPStream(this);
259 if (!m_addr
|| m_connected
) {
260 m_error
= wxPROTO_CONNERR
;
264 if (!wxProtocol::Connect(*m_addr
))
267 if (!BuildRequest(path
, wxHTTP_GET
))
270 wxPrintf(_T("Len = %s\n"), WXSTRINGCAST
GetHeader(_T("Content-Length")));
271 if (!GetHeader(_T("Content-Length")).IsEmpty())
272 inp_stream
->m_httpsize
= wxAtoi(WXSTRINGCAST
GetHeader(_T("Content-Length")));