diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl
index 00e8232608..b27840a1fd 100644
--- a/build/bakefiles/files.bkl
+++ b/build/bakefiles/files.bkl
@@ -309,6 +309,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
src/msw/gsocket.c
+ src/msw/urlmsw.cpp
wx/msw/gsockmsw.h
diff --git a/docs/changes.txt b/docs/changes.txt
index 93bda7d04d..c203cedc2d 100644
--- a/docs/changes.txt
+++ b/docs/changes.txt
@@ -34,6 +34,7 @@ INCOMPATIBLE CHANGES SINCE 2.4.x
- wxTabView::GetLayers() changed return type from wxList& to wxTabLayerList&
(when WXWIN_COMPATIBILITY_2_4 == 0)
- wxID_SEPARATOR (id used for the menu separators) value changed from -1 to -2
+- wxGetNumberFromUser() is now in separate wx/numdlg.h, not wx/textdlg.h
DEPRECATED METHODS SINCE 2.4.x
@@ -146,6 +147,7 @@ wxMSW:
wxEVT_COMMAND_COMBOBOX_SELECTED changed the selection
- wxFileDialog now returns correct filter index for multiple-file dialogs
- added wxTextCtrl::HitTest()
+- experimental wxURL implementation using WinInet functions (Hajo Kirchhoff)
wxGTK:
diff --git a/include/wx/msw/setup0.h b/include/wx/msw/setup0.h
index 1efd582ebe..c094148dd7 100644
--- a/include/wx/msw/setup0.h
+++ b/include/wx/msw/setup0.h
@@ -435,6 +435,16 @@
// Define this to use wxURL class.
#define wxUSE_URL 1
+// Define this to use native platform url and protocol support.
+// Currently valid only for MS-Windows.
+// Note: if you set this to 1, you can open ftp/http/gopher sites
+// and obtain a valid input stream for these sites
+// even when you set wxUSE_PROTOCOL_FTP/HTTP to 0.
+// Doing so reduces the code size.
+//
+// This code is experimental and subject to change.
+#define wxUSE_URL_NATIVE 0
+
// Support for regular expression matching via wxRegEx class: enable this to
// use POSIX regular expressions in your code. You need to compile regex
// library from src/regex to use it under Windows.
diff --git a/include/wx/url.h b/include/wx/url.h
index dc220b8a5f..59d8428060 100644
--- a/include/wx/url.h
+++ b/include/wx/url.h
@@ -37,6 +37,17 @@ typedef enum {
wxURL_PROTOERR
} wxURLError;
+#if wxUSE_URL_NATIVE
+class WXDLLIMPEXP_NET wxURL;
+
+class WXDLLIMPEXP_NET wxURLNativeImp : public wxObject
+{
+public:
+ virtual ~wxURLNativeImp() { }
+ virtual wxInputStream *GetInputStream(wxURL *owner) = 0;
+};
+#endif // wxUSE_URL_NATIVE
+
class WXDLLIMPEXP_NET wxURL : public wxObject
{
public:
@@ -72,6 +83,14 @@ protected:
wxHTTP *m_proxy;
#endif // wxUSE_SOCKETS
+#if wxUSE_URL_NATIVE
+ friend class wxURLNativeImp;
+ // pointer to a native URL implementation object
+ wxURLNativeImp *m_nativeImp;
+ // Creates on the heap and returns a native
+ // implementation object for the current platform.
+ static wxURLNativeImp *CreateNativeImpObject();
+#endif
wxProtoInfo *m_protoinfo;
wxProtocol *m_protocol;
diff --git a/src/common/url.cpp b/src/common/url.cpp
index e265e0c5f3..6c0da6ee29 100644
--- a/src/common/url.cpp
+++ b/src/common/url.cpp
@@ -61,6 +61,9 @@ wxURL::wxURL(const wxString& url)
m_protocol = NULL;
m_error = wxURL_NOERR;
m_url = url;
+#if wxUSE_URL_NATIVE
+ m_nativeImp = CreateNativeImpObject();
+#endif
#if wxUSE_SOCKETS
if ( ms_useDefaultProxy && !ms_proxyDefault )
@@ -157,10 +160,13 @@ void wxURL::CleanData()
wxURL::~wxURL()
{
- CleanData();
+ CleanData();
#if wxUSE_SOCKETS
- if (m_proxy && m_proxy != ms_proxyDefault)
- delete m_proxy;
+ if (m_proxy && m_proxy != ms_proxyDefault)
+ delete m_proxy;
+#endif
+#if wxUSE_URL_NATIVE
+ delete m_nativeImp;
#endif
}
@@ -285,6 +291,19 @@ wxInputStream *wxURL::GetInputStream()
m_protocol->SetPassword(m_password);
}
+#if wxUSE_URL_NATIVE
+ // give the native implementation to return a better stream
+ // such as the native WinINet functionality under MS-Windows
+ if (m_nativeImp)
+ {
+ wxInputStream *rc;
+ rc = m_nativeImp->GetInputStream(this);
+ if (rc != 0)
+ return rc;
+ }
+ // else use the standard behaviour
+#endif // wxUSE_URL_NATIVE
+
#if wxUSE_SOCKETS
wxIPV4address addr;
diff --git a/src/msw/urlmsw.cpp b/src/msw/urlmsw.cpp
new file mode 100644
index 0000000000..404da29892
--- /dev/null
+++ b/src/msw/urlmsw.cpp
@@ -0,0 +1,233 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: msw/urlmsw.cpp
+// Purpose: MS-Windows native URL support based on WinINet
+// Author: Hajo Kirchhoff
+// Modified by:
+// Created: 06/11/2003
+// RCS-ID: $Id$
+// Copyright: (c) 2003 Hajo Kirchhoff
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+#if wxUSE_URL_NATIVE
+
+#if !wxUSE_PROTOCOL_HTTP
+#include
+
+// empty http protocol replacement (for now)
+// so that wxUSE_URL_NATIVE can be used with
+// wxSOCKETS==0 and wxUSE_PROTOCOL_HTTP==0
+class wxHTTPDummyProto : public wxProtocol
+{
+public:
+ wxHTTPDummyProto() : wxProtocol() { }
+
+ wxProtocolError GetError() { return m_error; }
+
+ virtual bool Abort() { return TRUE; }
+
+ wxInputStream *GetInputStream(const wxString& WXUNUSED(path))
+ {
+ return 0; // input stream is returned by wxURLNativeImp
+ }
+
+protected:
+ wxProtocolError m_error;
+
+ DECLARE_DYNAMIC_CLASS_NO_COPY(wxHTTPDummyProto)
+ DECLARE_PROTOCOL(wxHTTPDummyProto)
+};
+
+// the only "reason for being" for this class is to tell
+// wxURL that there is someone dealing with the http protocol
+IMPLEMENT_DYNAMIC_CLASS(wxHTTPDummyProto, wxProtocol)
+IMPLEMENT_PROTOCOL(wxHTTPDummyProto, wxT("http"), NULL, FALSE)
+USE_PROTOCOL(wxHTTPDummyProto)
+
+#endif // !wxUSE_PROTOCOL_HTTP
+
+
+#ifdef __VISUALC__ // be conservative about this pragma
+ // tell the linker to include wininet.lib automatically
+ #pragma comment(lib, "wininet.lib")
+#endif
+
+#include "wx/string.h"
+#include "wx/list.h"
+#include "wx/utils.h"
+#include "wx/module.h"
+#include "wx/url.h"
+
+#include
+#include
+#include
+
+// this class needn't be exported
+class wxWinINetURL:public wxURLNativeImp
+{
+public:
+ wxInputStream *GetInputStream(wxURL *owner);
+
+protected:
+ // return the WinINet session handle
+ static HINTERNET GetSessionHandle();
+};
+
+HINTERNET wxWinINetURL::GetSessionHandle()
+{
+ // this struct ensures that the session is opened when the
+ // first call to GetSessionHandle is made
+ // it also ensures that the session is closed when the program
+ // terminates
+ static struct INetSession
+ {
+ INetSession()
+ {
+ DWORD rc = InternetAttemptConnect(0);
+
+ m_handle = InternetOpen
+ (
+ wxVERSION_STRING,
+ INTERNET_OPEN_TYPE_PRECONFIG,
+ NULL,
+ NULL,
+ rc == ERROR_SUCCESS ? 0 : INTERNET_FLAG_OFFLINE
+ );
+ }
+
+ ~INetSession()
+ {
+ InternetCloseHandle(m_handle);
+ }
+
+ HINTERNET m_handle;
+ } session;
+
+ return session.m_handle;
+}
+
+// this class needn't be exported
+class /*WXDLLIMPEXP_NET */ wxWinINetInputStream : public wxInputStream
+{
+public:
+ wxWinINetInputStream(HINTERNET hFile=0);
+ ~wxWinINetInputStream();
+
+ void Attach(HINTERNET hFile);
+
+ off_t SeekI( off_t WXUNUSED(pos), wxSeekMode WXUNUSED(mode) )
+ { return -1; }
+ off_t TellI() const
+ { return -1; }
+
+protected:
+ void SetError(wxStreamError err) { m_lasterror=err; }
+ HINTERNET m_hFile;
+ size_t OnSysRead(void *buffer, size_t bufsize);
+
+ DECLARE_NO_COPY_CLASS(wxWinINetInputStream)
+};
+
+size_t wxWinINetInputStream::OnSysRead(void *buffer, size_t bufsize)
+{
+ DWORD bytesread = 0;
+ if ( !InternetReadFile(m_hFile, buffer, bufsize, &bytesread) )
+ {
+ DWORD lError = ::GetLastError();
+ if ( lError != ERROR_SUCCESS )
+ SetError(wxSTREAM_READ_ERROR);
+
+ DWORD iError, bLength;
+ InternetGetLastResponseInfo(&iError, NULL, &bLength);
+ if ( bLength > 0 )
+ {
+ wxString errorString;
+ InternetGetLastResponseInfo
+ (
+ &iError,
+ wxStringBuffer(errorString, bLength),
+ &bLength
+ );
+
+ wxLogError(wxT("Read failed with error %d: %s"),
+ iError, errorString);
+ }
+ }
+
+ if ( bytesread == 0 )
+ {
+ SetError(wxSTREAM_EOF);
+ }
+
+ return bytesread;
+}
+
+wxWinINetInputStream::wxWinINetInputStream(HINTERNET hFile)
+ : m_hFile(hFile)
+{
+}
+
+void wxWinINetInputStream::Attach(HINTERNET newHFile)
+{
+ wxCHECK_RET(m_hFile==NULL,
+ wxT("cannot attach new stream when stream already exists"));
+ m_hFile=newHFile;
+ SetError(m_hFile!=NULL ? wxSTREAM_NO_ERROR : wxSTREAM_READ_ERROR);
+}
+
+wxWinINetInputStream::~wxWinINetInputStream()
+{
+ if ( m_hFile )
+ {
+ InternetCloseHandle(m_hFile);
+ m_hFile=0;
+ }
+}
+
+wxURLNativeImp *wxURL::CreateNativeImpObject()
+{
+ return new wxWinINetURL;
+}
+
+wxInputStream *wxWinINetURL::GetInputStream(wxURL *owner)
+{
+ DWORD service;
+ if ( owner->GetProtocolName() == wxT("http") )
+ {
+ service = INTERNET_SERVICE_HTTP;
+ }
+ else if ( owner->GetProtocolName() == wxT("ftp") )
+ {
+ service = INTERNET_SERVICE_FTP;
+ }
+ else
+ {
+ // unknown protocol. Let wxURL try another method.
+ return 0;
+ }
+
+ wxWinINetInputStream *newStream = new wxWinINetInputStream;
+ HINTERNET newStreamHandle = InternetOpenUrl
+ (
+ GetSessionHandle(),
+ owner->GetURL(),
+ NULL,
+ 0,
+ INTERNET_FLAG_KEEP_CONNECTION |
+ INTERNET_FLAG_PASSIVE,
+ (DWORD_PTR)newStream
+ );
+ newStream->Attach(newStreamHandle);
+
+ return newStream;
+}
+
+#endif // wxUSE_URL_NATIVE
+