/[pcsx2_0.9.7]/trunk/3rdparty/wxWidgets/src/common/http.cpp
ViewVC logotype

Annotation of /trunk/3rdparty/wxWidgets/src/common/http.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (hide annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (10 years, 4 months ago) by william
File size: 10338 byte(s)
committing r3113 initial commit again...
1 william 31 /////////////////////////////////////////////////////////////////////////////
2     // Name: src/common/http.cpp
3     // Purpose: HTTP protocol
4     // Author: Guilhem Lavaux
5     // Modified by: Simo Virokannas (authentication, Dec 2005)
6     // Created: August 1997
7     // RCS-ID: $Id: http.cpp 44660 2007-03-07 23:07:17Z VZ $
8     // Copyright: (c) 1997, 1998 Guilhem Lavaux
9     // Licence: wxWindows licence
10     /////////////////////////////////////////////////////////////////////////////
11    
12     // For compilers that support precompilation, includes "wx.h".
13     #include "wx/wxprec.h"
14    
15     #ifdef __BORLANDC__
16     #pragma hdrstop
17     #endif
18    
19     #if wxUSE_PROTOCOL_HTTP
20    
21     #include <stdio.h>
22     #include <stdlib.h>
23    
24     #ifndef WX_PRECOMP
25     #include "wx/string.h"
26     #include "wx/app.h"
27     #endif
28    
29     #include "wx/tokenzr.h"
30     #include "wx/socket.h"
31     #include "wx/protocol/protocol.h"
32     #include "wx/url.h"
33     #include "wx/protocol/http.h"
34     #include "wx/sckstrm.h"
35    
36     IMPLEMENT_DYNAMIC_CLASS(wxHTTP, wxProtocol)
37     IMPLEMENT_PROTOCOL(wxHTTP, wxT("http"), wxT("80"), true)
38    
39     wxHTTP::wxHTTP()
40     : wxProtocol()
41     {
42     m_addr = NULL;
43     m_read = false;
44     m_proxy_mode = false;
45     m_post_buf = wxEmptyString;
46     m_http_response = 0;
47    
48     SetNotify(wxSOCKET_LOST_FLAG);
49     }
50    
51     wxHTTP::~wxHTTP()
52     {
53     ClearHeaders();
54    
55     delete m_addr;
56     }
57    
58     void wxHTTP::ClearHeaders()
59     {
60     m_headers.clear();
61     }
62    
63     wxString wxHTTP::GetContentType()
64     {
65     return GetHeader(wxT("Content-Type"));
66     }
67    
68     void wxHTTP::SetProxyMode(bool on)
69     {
70     m_proxy_mode = on;
71     }
72    
73     wxHTTP::wxHeaderIterator wxHTTP::FindHeader(const wxString& header)
74     {
75     wxHeaderIterator it = m_headers.begin();
76     for ( wxHeaderIterator en = m_headers.end(); it != en; ++it )
77     {
78     if ( wxStricmp(it->first, header) == 0 )
79     break;
80     }
81    
82     return it;
83     }
84    
85     wxHTTP::wxHeaderConstIterator wxHTTP::FindHeader(const wxString& header) const
86     {
87     wxHeaderConstIterator it = m_headers.begin();
88     for ( wxHeaderConstIterator en = m_headers.end(); it != en; ++it )
89     {
90     if ( wxStricmp(it->first, header) == 0 )
91     break;
92     }
93    
94     return it;
95     }
96    
97     void wxHTTP::SetHeader(const wxString& header, const wxString& h_data)
98     {
99     if (m_read) {
100     ClearHeaders();
101     m_read = false;
102     }
103    
104     wxHeaderIterator it = FindHeader(header);
105     if (it != m_headers.end())
106     it->second = h_data;
107     else
108     m_headers[header] = h_data;
109     }
110    
111     wxString wxHTTP::GetHeader(const wxString& header) const
112     {
113     wxHeaderConstIterator it = FindHeader(header);
114    
115     return it == m_headers.end() ? wxGetEmptyString() : it->second;
116     }
117    
118     wxString wxHTTP::GenerateAuthString(const wxString& user, const wxString& pass) const
119     {
120     static const char *base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
121    
122     wxString buf;
123     wxString toencode;
124    
125     buf.Printf(wxT("Basic "));
126    
127     toencode.Printf(wxT("%s:%s"),user.c_str(),pass.c_str());
128    
129     size_t len = toencode.length();
130     const wxChar *from = toencode.c_str();
131     while (len >= 3) { // encode full blocks first
132     buf << wxString::Format(wxT("%c%c"), base64[(from[0] >> 2) & 0x3f], base64[((from[0] << 4) & 0x30) | ((from[1] >> 4) & 0xf)]);
133     buf << wxString::Format(wxT("%c%c"), base64[((from[1] << 2) & 0x3c) | ((from[2] >> 6) & 0x3)], base64[from[2] & 0x3f]);
134     from += 3;
135     len -= 3;
136     }
137     if (len > 0) { // pad the remaining characters
138     buf << wxString::Format(wxT("%c"), base64[(from[0] >> 2) & 0x3f]);
139     if (len == 1) {
140     buf << wxString::Format(wxT("%c="), base64[(from[0] << 4) & 0x30]);
141     } else {
142     buf << wxString::Format(wxT("%c%c"), base64[((from[0] << 4) & 0x30) | ((from[1] >> 4) & 0xf)], base64[(from[1] << 2) & 0x3c]);
143     }
144     buf << wxString::Format(wxT("="));
145     }
146    
147     return buf;
148     }
149    
150     void wxHTTP::SetPostBuffer(const wxString& post_buf)
151     {
152     m_post_buf = post_buf;
153     }
154    
155     void wxHTTP::SendHeaders()
156     {
157     typedef wxStringToStringHashMap::iterator iterator;
158     wxString buf;
159    
160     for (iterator it = m_headers.begin(), en = m_headers.end(); it != en; ++it )
161     {
162     buf.Printf(wxT("%s: %s\r\n"), it->first.c_str(), it->second.c_str());
163    
164     const wxWX2MBbuf cbuf = buf.mb_str();
165     Write(cbuf, strlen(cbuf));
166     }
167     }
168    
169     bool wxHTTP::ParseHeaders()
170     {
171     wxString line;
172     wxStringTokenizer tokenzr;
173    
174     ClearHeaders();
175     m_read = true;
176    
177     for ( ;; )
178     {
179     m_perr = ReadLine(this, line);
180     if (m_perr != wxPROTO_NOERR)
181     return false;
182    
183     if (line.length() == 0)
184     break;
185    
186     wxString left_str = line.BeforeFirst(':');
187     m_headers[left_str] = line.AfterFirst(':').Strip(wxString::both);
188     }
189     return true;
190     }
191    
192     bool wxHTTP::Connect(const wxString& host, unsigned short port)
193     {
194     wxIPV4address *addr;
195    
196     if (m_addr) {
197     delete m_addr;
198     m_addr = NULL;
199     Close();
200     }
201    
202     m_addr = addr = new wxIPV4address();
203    
204     if (!addr->Hostname(host)) {
205     delete m_addr;
206     m_addr = NULL;
207     m_perr = wxPROTO_NETERR;
208     return false;
209     }
210    
211     if ( port )
212     addr->Service(port);
213     else if (!addr->Service(wxT("http")))
214     addr->Service(80);
215    
216     SetHeader(wxT("Host"), host);
217    
218     return true;
219     }
220    
221     bool wxHTTP::Connect(wxSockAddress& addr, bool WXUNUSED(wait))
222     {
223     if (m_addr) {
224     delete m_addr;
225     Close();
226     }
227    
228     m_addr = addr.Clone();
229    
230     wxIPV4address *ipv4addr = wxDynamicCast(&addr, wxIPV4address);
231     if (ipv4addr)
232     SetHeader(wxT("Host"), ipv4addr->OrigHostname());
233    
234     return true;
235     }
236    
237     bool wxHTTP::BuildRequest(const wxString& path, wxHTTP_Req req)
238     {
239     const wxChar *request;
240    
241     switch (req)
242     {
243     case wxHTTP_GET:
244     request = wxT("GET");
245     break;
246    
247     case wxHTTP_POST:
248     request = wxT("POST");
249     if ( GetHeader( wxT("Content-Length") ).IsNull() )
250     SetHeader( wxT("Content-Length"), wxString::Format( wxT("%lu"), (unsigned long)m_post_buf.Len() ) );
251     break;
252    
253     default:
254     return false;
255     }
256    
257     m_http_response = 0;
258    
259     // If there is no User-Agent defined, define it.
260     if (GetHeader(wxT("User-Agent")).IsNull())
261     SetHeader(wxT("User-Agent"), wxT("wxWidgets 2.x"));
262    
263     // Send authentication information
264     if (!m_username.empty() || !m_password.empty()) {
265     SetHeader(wxT("Authorization"), GenerateAuthString(m_username, m_password));
266     }
267    
268     SaveState();
269    
270     // we may use non blocking sockets only if we can dispatch events from them
271     SetFlags( wxIsMainThread() && wxApp::IsMainLoopRunning() ? wxSOCKET_NONE
272     : wxSOCKET_BLOCK );
273     Notify(false);
274    
275     wxString buf;
276     buf.Printf(wxT("%s %s HTTP/1.0\r\n"), request, path.c_str());
277     const wxWX2MBbuf pathbuf = wxConvLocal.cWX2MB(buf);
278     Write(pathbuf, strlen(wxMBSTRINGCAST pathbuf));
279     SendHeaders();
280     Write("\r\n", 2);
281    
282     if ( req == wxHTTP_POST ) {
283     Write(m_post_buf.mbc_str(), m_post_buf.Len());
284     m_post_buf = wxEmptyString;
285     }
286    
287     wxString tmp_str;
288     m_perr = ReadLine(this, tmp_str);
289     if (m_perr != wxPROTO_NOERR) {
290     RestoreState();
291     return false;
292     }
293    
294     if (!tmp_str.Contains(wxT("HTTP/"))) {
295     // TODO: support HTTP v0.9 which can have no header.
296     // FIXME: tmp_str is not put back in the in-queue of the socket.
297     SetHeader(wxT("Content-Length"), wxT("-1"));
298     SetHeader(wxT("Content-Type"), wxT("none/none"));
299     RestoreState();
300     return true;
301     }
302    
303     wxStringTokenizer token(tmp_str,wxT(' '));
304     wxString tmp_str2;
305     bool ret_value;
306    
307     token.NextToken();
308     tmp_str2 = token.NextToken();
309    
310     m_http_response = wxAtoi(tmp_str2);
311    
312     switch (tmp_str2[0u])
313     {
314     case wxT('1'):
315     /* INFORMATION / SUCCESS */
316     break;
317    
318     case wxT('2'):
319     /* SUCCESS */
320     break;
321    
322     case wxT('3'):
323     /* REDIRECTION */
324     break;
325    
326     default:
327     m_perr = wxPROTO_NOFILE;
328     RestoreState();
329     return false;
330     }
331    
332     ret_value = ParseHeaders();
333     RestoreState();
334     return ret_value;
335     }
336    
337     class wxHTTPStream : public wxSocketInputStream
338     {
339     public:
340     wxHTTP *m_http;
341     size_t m_httpsize;
342     unsigned long m_read_bytes;
343    
344     wxHTTPStream(wxHTTP *http) : wxSocketInputStream(*http), m_http(http) {}
345     size_t GetSize() const { return m_httpsize; }
346     virtual ~wxHTTPStream(void) { m_http->Abort(); }
347    
348     protected:
349     size_t OnSysRead(void *buffer, size_t bufsize);
350    
351     DECLARE_NO_COPY_CLASS(wxHTTPStream)
352     };
353    
354     size_t wxHTTPStream::OnSysRead(void *buffer, size_t bufsize)
355     {
356     if (m_httpsize > 0 && m_read_bytes >= m_httpsize)
357     {
358     m_lasterror = wxSTREAM_EOF;
359     return 0;
360     }
361    
362     size_t ret = wxSocketInputStream::OnSysRead(buffer, bufsize);
363     m_read_bytes += ret;
364    
365     if (m_httpsize==(size_t)-1 && m_lasterror == wxSTREAM_READ_ERROR )
366     {
367     // if m_httpsize is (size_t) -1 this means read until connection closed
368     // which is equivalent to getting a READ_ERROR, for clients however this
369     // must be translated into EOF, as it is the expected way of signalling
370     // end end of the content
371     m_lasterror = wxSTREAM_EOF ;
372     }
373    
374     return ret;
375     }
376    
377     bool wxHTTP::Abort(void)
378     {
379     return wxSocketClient::Close();
380     }
381    
382     wxInputStream *wxHTTP::GetInputStream(const wxString& path)
383     {
384     wxHTTPStream *inp_stream;
385    
386     wxString new_path;
387    
388     m_perr = wxPROTO_CONNERR;
389     if (!m_addr)
390     return NULL;
391    
392     // We set m_connected back to false so wxSocketBase will know what to do.
393     #ifdef __WXMAC__
394     wxSocketClient::Connect(*m_addr , false );
395     wxSocketClient::WaitOnConnect(10);
396    
397     if (!wxSocketClient::IsConnected())
398     return NULL;
399     #else
400     if (!wxProtocol::Connect(*m_addr))
401     return NULL;
402     #endif
403    
404     if (!BuildRequest(path, m_post_buf.empty() ? wxHTTP_GET : wxHTTP_POST))
405     return NULL;
406    
407     inp_stream = new wxHTTPStream(this);
408    
409     if (!GetHeader(wxT("Content-Length")).empty())
410     inp_stream->m_httpsize = wxAtoi(WXSTRINGCAST GetHeader(wxT("Content-Length")));
411     else
412     inp_stream->m_httpsize = (size_t)-1;
413    
414     inp_stream->m_read_bytes = 0;
415    
416     Notify(false);
417     SetFlags(wxSOCKET_BLOCK | wxSOCKET_WAITALL);
418    
419     return inp_stream;
420     }
421    
422     #endif // wxUSE_PROTOCOL_HTTP

  ViewVC Help
Powered by ViewVC 1.1.22