~ubuntu-dev/wxwidgets2.6/upstream-debian

« back to all changes in this revision

Viewing changes to src/common/url.cpp

  • Committer: Daniel T Chen
  • Date: 2006-06-26 10:15:11 UTC
  • Revision ID: crimsun@ubuntu.com-20060626101511-a4436cec4c6d9b35
ImportĀ DebianĀ 2.6.3.2.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/////////////////////////////////////////////////////////////////////////////
 
2
// Name:        url.cpp
 
3
// Purpose:     URL parser
 
4
// Author:      Guilhem Lavaux
 
5
// Modified by:
 
6
// Created:     20/07/1997
 
7
// RCS-ID:      $Id: url.cpp,v 1.54 2005/07/28 21:52:50 VZ Exp $
 
8
// Copyright:   (c) 1997, 1998 Guilhem Lavaux
 
9
// Licence:     wxWindows licence
 
10
/////////////////////////////////////////////////////////////////////////////
 
11
 
 
12
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
 
13
#pragma implementation "url.h"
 
14
#endif
 
15
 
 
16
// For compilers that support precompilation, includes "wx.h".
 
17
#include "wx/wxprec.h"
 
18
 
 
19
#ifdef __BORLANDC__
 
20
#pragma hdrstop
 
21
#endif
 
22
 
 
23
#if wxUSE_URL
 
24
 
 
25
#include "wx/string.h"
 
26
#include "wx/list.h"
 
27
#include "wx/utils.h"
 
28
#include "wx/module.h"
 
29
#include "wx/url.h"
 
30
 
 
31
#include <string.h>
 
32
#include <ctype.h>
 
33
 
 
34
IMPLEMENT_CLASS(wxProtoInfo, wxObject)
 
35
IMPLEMENT_CLASS(wxURL, wxURI)
 
36
 
 
37
// Protocols list
 
38
wxProtoInfo *wxURL::ms_protocols = NULL;
 
39
 
 
40
// Enforce linking of protocol classes:
 
41
USE_PROTOCOL(wxFileProto)
 
42
 
 
43
#if wxUSE_PROTOCOL_HTTP
 
44
USE_PROTOCOL(wxHTTP)
 
45
 
 
46
    wxHTTP *wxURL::ms_proxyDefault = NULL;
 
47
    bool wxURL::ms_useDefaultProxy = false;
 
48
#endif
 
49
 
 
50
#if wxUSE_PROTOCOL_FTP
 
51
USE_PROTOCOL(wxFTP)
 
52
#endif
 
53
 
 
54
// --------------------------------------------------------------
 
55
//
 
56
//                          wxURL
 
57
//
 
58
// --------------------------------------------------------------
 
59
 
 
60
// --------------------------------------------------------------
 
61
// Construction
 
62
// --------------------------------------------------------------
 
63
 
 
64
wxURL::wxURL(const wxString& url) : wxURI(url)
 
65
{
 
66
    Init(url);
 
67
    ParseURL();
 
68
}
 
69
 
 
70
wxURL::wxURL(const wxURI& url) : wxURI(url)
 
71
{
 
72
    Init(url.BuildURI());
 
73
    ParseURL();
 
74
}
 
75
 
 
76
void wxURL::Init(const wxString& url)
 
77
{
 
78
    m_protocol = NULL;
 
79
    m_error = wxURL_NOERR;
 
80
    m_url = url;
 
81
#if wxUSE_URL_NATIVE
 
82
    m_nativeImp = CreateNativeImpObject();
 
83
#endif
 
84
 
 
85
#if wxUSE_PROTOCOL_HTTP
 
86
    if ( ms_useDefaultProxy && !ms_proxyDefault )
 
87
    {
 
88
        SetDefaultProxy( wxGetenv(wxT("HTTP_PROXY")) );
 
89
 
 
90
        if ( !ms_proxyDefault )
 
91
        {
 
92
            // don't try again
 
93
            ms_useDefaultProxy = false;
 
94
        }
 
95
    }
 
96
 
 
97
    m_useProxy = ms_proxyDefault != NULL;
 
98
    m_proxy = ms_proxyDefault;
 
99
#endif // wxUSE_PROTOCOL_HTTP
 
100
 
 
101
}
 
102
 
 
103
// --------------------------------------------------------------
 
104
// Assignment
 
105
// --------------------------------------------------------------
 
106
 
 
107
wxURL& wxURL::operator = (const wxURI& url)
 
108
{
 
109
    wxURI::operator = (url);
 
110
    Init(url.BuildURI());
 
111
    ParseURL();
 
112
    return *this;
 
113
}
 
114
wxURL& wxURL::operator = (const wxString& url)
 
115
{
 
116
    wxURI::operator = (url);
 
117
    Init(url);
 
118
    ParseURL();
 
119
    return *this;
 
120
}
 
121
 
 
122
// --------------------------------------------------------------
 
123
// ParseURL
 
124
//
 
125
// Builds the URL and takes care of the old protocol stuff
 
126
// --------------------------------------------------------------
 
127
 
 
128
bool wxURL::ParseURL()
 
129
{
 
130
    // If the URL was already parsed (m_protocol != NULL), pass this section.
 
131
    if (!m_protocol)
 
132
    {
 
133
        // Clean up
 
134
        CleanData();
 
135
 
 
136
        // Make sure we have a protocol/scheme
 
137
        if (!HasScheme())
 
138
        {
 
139
            m_error = wxURL_SNTXERR;
 
140
            return false;
 
141
        }
 
142
 
 
143
        // Find and create the protocol object
 
144
        if (!FetchProtocol())
 
145
        {
 
146
            m_error = wxURL_NOPROTO;
 
147
            return false;
 
148
        }
 
149
 
 
150
        // Do we need a host name ?
 
151
        if (m_protoinfo->m_needhost)
 
152
        {
 
153
            //  Make sure we have one, then
 
154
            if (!HasServer())
 
155
            {
 
156
                m_error = wxURL_SNTXERR;
 
157
                return false;
 
158
            }
 
159
        }
 
160
    }
 
161
 
 
162
#if wxUSE_PROTOCOL_HTTP
 
163
    if (m_useProxy)
 
164
    {
 
165
        // Third, we rebuild the URL.
 
166
        m_url = m_scheme + wxT(":");
 
167
        if (m_protoinfo->m_needhost)
 
168
            m_url = m_url + wxT("//") + m_server;
 
169
 
 
170
        // We initialize specific variables.
 
171
        m_protocol = m_proxy; // FIXME: we should clone the protocol
 
172
    }
 
173
#endif // wxUSE_PROTOCOL_HTTP
 
174
 
 
175
    m_error = wxURL_NOERR;
 
176
    return true;
 
177
}
 
178
 
 
179
// --------------------------------------------------------------
 
180
// Destruction/Cleanup
 
181
// --------------------------------------------------------------
 
182
 
 
183
void wxURL::CleanData()
 
184
{
 
185
#if wxUSE_PROTOCOL_HTTP
 
186
    if (!m_useProxy)
 
187
#endif // wxUSE_PROTOCOL_HTTP
 
188
        delete m_protocol;
 
189
}
 
190
 
 
191
wxURL::~wxURL()
 
192
{
 
193
    CleanData();
 
194
#if wxUSE_PROTOCOL_HTTP
 
195
    if (m_proxy && m_proxy != ms_proxyDefault)
 
196
        delete m_proxy;
 
197
#endif // wxUSE_PROTOCOL_HTTP
 
198
#if wxUSE_URL_NATIVE
 
199
    delete m_nativeImp;
 
200
#endif
 
201
}
 
202
 
 
203
// --------------------------------------------------------------
 
204
// FetchProtocol
 
205
// --------------------------------------------------------------
 
206
 
 
207
bool wxURL::FetchProtocol()
 
208
{
 
209
    wxProtoInfo *info = ms_protocols;
 
210
 
 
211
    while (info)
 
212
    {
 
213
        if (m_scheme == info->m_protoname)
 
214
        {
 
215
            if (m_port.IsNull())
 
216
                m_port = info->m_servname;
 
217
            m_protoinfo = info;
 
218
            m_protocol = (wxProtocol *)m_protoinfo->m_cinfo->CreateObject();
 
219
            return true;
 
220
        }
 
221
        info = info->next;
 
222
    }
 
223
    return false;
 
224
}
 
225
 
 
226
// --------------------------------------------------------------
 
227
// GetInputStream
 
228
// --------------------------------------------------------------
 
229
 
 
230
wxInputStream *wxURL::GetInputStream()
 
231
{
 
232
    if (!m_protocol)
 
233
    {
 
234
        m_error = wxURL_NOPROTO;
 
235
        return NULL;
 
236
    }
 
237
 
 
238
    m_error = wxURL_NOERR;
 
239
    if (HasUserInfo())
 
240
    {
 
241
        size_t dwPasswordPos = m_userinfo.find(':');
 
242
 
 
243
        if (dwPasswordPos == wxString::npos)
 
244
            m_protocol->SetUser(m_userinfo);
 
245
        else
 
246
        {
 
247
            m_protocol->SetUser(m_userinfo(0, dwPasswordPos));
 
248
            m_protocol->SetPassword(m_userinfo(dwPasswordPos+1, m_userinfo.length() + 1));
 
249
        }
 
250
    }
 
251
 
 
252
#if wxUSE_URL_NATIVE
 
253
    // give the native implementation to return a better stream
 
254
    // such as the native WinINet functionality under MS-Windows
 
255
    if (m_nativeImp)
 
256
    {
 
257
        wxInputStream *rc;
 
258
        rc = m_nativeImp->GetInputStream(this);
 
259
        if (rc != 0)
 
260
            return rc;
 
261
    }
 
262
    // else use the standard behaviour
 
263
#endif // wxUSE_URL_NATIVE
 
264
 
 
265
#if wxUSE_SOCKETS
 
266
    wxIPV4address addr;
 
267
 
 
268
    // m_protoinfo is NULL when we use a proxy
 
269
    if (!m_useProxy && m_protoinfo->m_needhost)
 
270
    {
 
271
        if (!addr.Hostname(m_server))
 
272
        {
 
273
            m_error = wxURL_NOHOST;
 
274
            return NULL;
 
275
        }
 
276
 
 
277
        addr.Service(m_port);
 
278
 
 
279
        if (!m_protocol->Connect(addr, true)) // Watcom needs the 2nd arg for some reason
 
280
        {
 
281
            m_error = wxURL_CONNERR;
 
282
            return NULL;
 
283
        }
 
284
    }
 
285
#endif
 
286
 
 
287
    wxString fullPath;
 
288
 
 
289
    // When we use a proxy, we have to pass the whole URL to it.
 
290
    if (m_useProxy)
 
291
        fullPath += m_url;
 
292
 
 
293
    if(m_path.empty())
 
294
        fullPath += wxT("/");
 
295
    else
 
296
        fullPath += m_path;
 
297
 
 
298
    if (HasQuery())
 
299
        fullPath += wxT("?") + m_query;
 
300
 
 
301
    if (HasFragment())
 
302
        fullPath += wxT("#") + m_fragment;
 
303
 
 
304
    wxInputStream *the_i_stream = m_protocol->GetInputStream(fullPath);
 
305
 
 
306
    if (!the_i_stream)
 
307
    {
 
308
        m_error = wxURL_PROTOERR;
 
309
        return NULL;
 
310
    }
 
311
 
 
312
    return the_i_stream;
 
313
}
 
314
 
 
315
#if wxUSE_PROTOCOL_HTTP
 
316
void wxURL::SetDefaultProxy(const wxString& url_proxy)
 
317
{
 
318
    if ( !url_proxy )
 
319
    {
 
320
        if ( ms_proxyDefault )
 
321
        {
 
322
            ms_proxyDefault->Close();
 
323
            delete ms_proxyDefault;
 
324
            ms_proxyDefault = NULL;
 
325
        }
 
326
    }
 
327
    else
 
328
    {
 
329
        wxString tmp_str = url_proxy;
 
330
        int pos = tmp_str.Find(wxT(':'));
 
331
        if (pos == wxNOT_FOUND)
 
332
            return;
 
333
 
 
334
        wxString hostname = tmp_str(0, pos),
 
335
        port = tmp_str(pos+1, tmp_str.Length()-pos);
 
336
        wxIPV4address addr;
 
337
 
 
338
        if (!addr.Hostname(hostname))
 
339
            return;
 
340
        if (!addr.Service(port))
 
341
            return;
 
342
 
 
343
        if (ms_proxyDefault)
 
344
            // Finally, when all is right, we connect the new proxy.
 
345
            ms_proxyDefault->Close();
 
346
        else
 
347
            ms_proxyDefault = new wxHTTP();
 
348
        ms_proxyDefault->Connect(addr, true); // Watcom needs the 2nd arg for some reason
 
349
    }
 
350
}
 
351
 
 
352
void wxURL::SetProxy(const wxString& url_proxy)
 
353
{
 
354
    if ( !url_proxy )
 
355
    {
 
356
        if ( m_proxy && m_proxy != ms_proxyDefault )
 
357
        {
 
358
            m_proxy->Close();
 
359
            delete m_proxy;
 
360
        }
 
361
 
 
362
        m_useProxy = false;
 
363
    }
 
364
    else
 
365
    {
 
366
        wxString tmp_str;
 
367
        wxString hostname, port;
 
368
        int pos;
 
369
        wxIPV4address addr;
 
370
 
 
371
        tmp_str = url_proxy;
 
372
        pos = tmp_str.Find(wxT(':'));
 
373
        // This is an invalid proxy name.
 
374
        if (pos == wxNOT_FOUND)
 
375
            return;
 
376
 
 
377
        hostname = tmp_str(0, pos);
 
378
        port = tmp_str(pos+1, tmp_str.Length()-pos);
 
379
 
 
380
        addr.Hostname(hostname);
 
381
        addr.Service(port);
 
382
 
 
383
        // Finally, create the whole stuff.
 
384
        if (m_proxy && m_proxy != ms_proxyDefault)
 
385
            delete m_proxy;
 
386
        m_proxy = new wxHTTP();
 
387
        m_proxy->Connect(addr, true); // Watcom needs the 2nd arg for some reason
 
388
 
 
389
        CleanData();
 
390
        // Reparse url.
 
391
        m_useProxy = true;
 
392
        ParseURL();
 
393
    }
 
394
}
 
395
#endif // wxUSE_PROTOCOL_HTTP
 
396
 
 
397
// ----------------------------------------------------------------------
 
398
// wxURLModule
 
399
//
 
400
// A module which deletes the default proxy if we created it
 
401
// ----------------------------------------------------------------------
 
402
 
 
403
#if wxUSE_SOCKETS
 
404
 
 
405
class wxURLModule : public wxModule
 
406
{
 
407
public:
 
408
    virtual bool OnInit();
 
409
    virtual void OnExit();
 
410
 
 
411
private:
 
412
    DECLARE_DYNAMIC_CLASS(wxURLModule)
 
413
};
 
414
 
 
415
IMPLEMENT_DYNAMIC_CLASS(wxURLModule, wxModule)
 
416
 
 
417
bool wxURLModule::OnInit()
 
418
{
 
419
#if wxUSE_PROTOCOL_HTTP
 
420
    // env var HTTP_PROXY contains the address of the default proxy to use if
 
421
    // set, but don't try to create this proxy right now because it will slow
 
422
    // down the program startup (especially if there is no DNS server
 
423
    // available, in which case it may take up to 1 minute)
 
424
 
 
425
    if ( wxGetenv(_T("HTTP_PROXY")) )
 
426
    {
 
427
        wxURL::ms_useDefaultProxy = true;
 
428
    }
 
429
#endif // wxUSE_PROTOCOL_HTTP
 
430
    return true;
 
431
}
 
432
 
 
433
void wxURLModule::OnExit()
 
434
{
 
435
#if wxUSE_PROTOCOL_HTTP
 
436
    delete wxURL::ms_proxyDefault;
 
437
    wxURL::ms_proxyDefault = NULL;
 
438
#endif // wxUSE_PROTOCOL_HTTP
 
439
}
 
440
 
 
441
#endif // wxUSE_SOCKETS
 
442
 
 
443
// ---------------------------------------------------------------------------
 
444
//
 
445
//                        wxURL Compatibility
 
446
//
 
447
// ---------------------------------------------------------------------------
 
448
 
 
449
#if WXWIN_COMPATIBILITY_2_4
 
450
 
 
451
#include "wx/url.h"
 
452
 
 
453
wxString wxURL::GetProtocolName() const
 
454
{
 
455
    return m_scheme;
 
456
}
 
457
 
 
458
wxString wxURL::GetHostName() const
 
459
{
 
460
    return m_server;
 
461
}
 
462
 
 
463
wxString wxURL::GetPath() const
 
464
{
 
465
    return m_path;
 
466
}
 
467
 
 
468
//Note that this old code really doesn't convert to a URI that well and looks
 
469
//more like a dirty hack than anything else...
 
470
 
 
471
wxString wxURL::ConvertToValidURI(const wxString& uri, const wxChar* delims)
 
472
{
 
473
  wxString out_str;
 
474
  wxString hexa_code;
 
475
  size_t i;
 
476
 
 
477
  for (i = 0; i < uri.Len(); i++)
 
478
  {
 
479
    wxChar c = uri.GetChar(i);
 
480
 
 
481
    if (c == wxT(' '))
 
482
    {
 
483
      // GRG, Apr/2000: changed to "%20" instead of '+'
 
484
 
 
485
      out_str += wxT("%20");
 
486
    }
 
487
    else
 
488
    {
 
489
      // GRG, Apr/2000: modified according to the URI definition (RFC 2396)
 
490
      //
 
491
      // - Alphanumeric characters are never escaped
 
492
      // - Unreserved marks are never escaped
 
493
      // - Delimiters must be escaped if they appear within a component
 
494
      //     but not if they are used to separate components. Here we have
 
495
      //     no clear way to distinguish between these two cases, so they
 
496
      //     are escaped unless they are passed in the 'delims' parameter
 
497
      //     (allowed delimiters).
 
498
 
 
499
      static const wxChar marks[] = wxT("-_.!~*()'");
 
500
 
 
501
      if ( !wxIsalnum(c) && !wxStrchr(marks, c) && !wxStrchr(delims, c) )
 
502
      {
 
503
        hexa_code.Printf(wxT("%%%02X"), c);
 
504
        out_str += hexa_code;
 
505
      }
 
506
      else
 
507
      {
 
508
        out_str += c;
 
509
      }
 
510
    }
 
511
  }
 
512
 
 
513
  return out_str;
 
514
}
 
515
 
 
516
wxString wxURL::ConvertFromURI(const wxString& uri)
 
517
{
 
518
    return wxURI::Unescape(uri);
 
519
}
 
520
 
 
521
#endif //WXWIN_COMPATIBILITY_2_4
 
522
 
 
523
#endif // wxUSE_URL