Fix wxXmlResource::Load() with HTTP URLs

Make the code in this function work even with wxFileSystemHandlers that
don't implement FindFirst() at all: we can, and should, still try
loading the passed in path with them, rather than not doing anything at
all.

This makes Load() works with HTTP URLs again, as it apparently used to
do a long time ago, but didn't do any more.

Add a unit test, even if only a semi-manual one, to try to help with
this not getting broken again (ideal would be to launch our own HTTP
server inside the test, but this is a bit more complicated).

Closes #19109.
This commit is contained in:
Vadim Zeitlin
2021-03-22 16:14:31 +01:00
parent 71eff92873
commit 9e96ff972b
2 changed files with 48 additions and 5 deletions

View File

@@ -343,7 +343,8 @@ bool wxXmlResource::Load(const wxString& filemask_)
{ {
wxString filemask = ConvertFileNameToURL(filemask_); wxString filemask = ConvertFileNameToURL(filemask_);
bool allOK = true; bool allOK = true,
anyOK = false;
#if wxUSE_FILESYSTEM #if wxUSE_FILESYSTEM
wxFileSystem fsys; wxFileSystem fsys;
@@ -356,33 +357,47 @@ bool wxXmlResource::Load(const wxString& filemask_)
wxString fnd = wxXmlFindFirst; wxString fnd = wxXmlFindFirst;
if ( fnd.empty() ) if ( fnd.empty() )
{ {
wxLogError(_("Cannot load resources from '%s'."), filemask); // Some file system handlers (e.g. wxInternetFSHandler) just don't
return false; // implement FindFirst() at all, try using the original path as is.
fnd = filemask;
} }
while (!fnd.empty()) while (!fnd.empty())
{ {
bool thisOK = true;
#if wxUSE_FILESYSTEM #if wxUSE_FILESYSTEM
if ( IsArchive(fnd) ) if ( IsArchive(fnd) )
{ {
if ( !Load(fnd + wxT("#zip:*.xrc")) ) if ( !Load(fnd + wxT("#zip:*.xrc")) )
allOK = false; thisOK = false;
} }
else // a single resource URL else // a single resource URL
#endif // wxUSE_FILESYSTEM #endif // wxUSE_FILESYSTEM
{ {
wxXmlDocument * const doc = DoLoadFile(fnd); wxXmlDocument * const doc = DoLoadFile(fnd);
if ( !doc ) if ( !doc )
allOK = false; thisOK = false;
else else
Data().push_back(new wxXmlResourceDataRecord(fnd, doc)); Data().push_back(new wxXmlResourceDataRecord(fnd, doc));
} }
if ( thisOK )
anyOK = true;
else
allOK = false;
fnd = wxXmlFindNext; fnd = wxXmlFindNext;
} }
# undef wxXmlFindFirst # undef wxXmlFindFirst
# undef wxXmlFindNext # undef wxXmlFindNext
if ( !anyOK )
{
wxLogError(_("Cannot load resources from '%s'."), filemask);
return false;
}
return allOK; return allOK;
} }

View File

@@ -19,6 +19,7 @@
#if wxUSE_XRC #if wxUSE_XRC
#include "wx/fs_inet.h"
#include "wx/xml/xml.h" #include "wx/xml/xml.h"
#include "wx/sstream.h" #include "wx/sstream.h"
#include "wx/wfstream.h" #include "wx/wfstream.h"
@@ -204,4 +205,31 @@ TEST_CASE_METHOD(XrcTestCase, "XRC::IDRanges", "[xrc]")
} }
} }
// This test is disabled by default as it requires the environment variable
// below to be defined to point to a HTTP URL with the file to load.
//
// Use something like "python3 -m http.server samples/xrc/rc" and set
// WX_TEST_XRC_URL to http://localhost/menu.xrc to run this test.
TEST_CASE_METHOD(XrcTestCase, "XRC::LoadURL", "[xrc][.]")
{
wxString url;
REQUIRE( wxGetEnv("WX_TEST_XRC_URL", &url) );
// Ensure that loading from HTTP URLs is supported.
struct InetHandler : wxInternetFSHandler
{
InetHandler()
{
wxFileSystem::AddHandler(this);
}
~InetHandler()
{
wxFileSystem::RemoveHandler(this);
}
} inetHandler;
CHECK( wxXmlResource::Get()->Load(url) );
}
#endif // wxUSE_XRC #endif // wxUSE_XRC