Move URL<->filename conversion functions to wxFileName

This ensures that they are always available and can be used in
wxLaunchDefaultBrowser() in all build variants, whereas before this
function didn't handle file:// URLs correctly when the library was built
with wxUSE_FILESYSTEM==0.

Closes https://github.com/wxWidgets/wxWidgets/pull/1469

Closes #10414.
This commit is contained in:
oneeyeman1
2019-08-24 00:49:25 -05:00
committed by Vadim Zeitlin
parent 5e7b515349
commit 14bcf09924
8 changed files with 133 additions and 100 deletions

View File

@@ -258,6 +258,11 @@ public:
// values // values
bool SetPermissions(int permissions); bool SetPermissions(int permissions);
// Returns the native path for a file URL
static wxFileName URLToFileName(const wxString& url);
// Returns the file URL for a native path
static wxString FileNameToURL(const wxFileName& filename);
// time functions // time functions
#if wxUSE_DATETIME #if wxUSE_DATETIME

View File

@@ -1246,6 +1246,25 @@ public:
*/ */
bool SetPermissions(int permissions); bool SetPermissions(int permissions);
/**
Converts URL into a well-formed filename.
The URL must use the @c file protocol.
If the URL does not use @c file protocol
wxFileName object may not be good or may not exist
@since 3.1.3
*/
static wxFileName URLToFileName(const wxString& url);
/**
Converts wxFileName into an URL.
@see URLToFileName(), wxFileName
@since 3.1.3
*/
static wxString FileNameToURL(const wxFileName& filename);
/** /**
Sets the file creation and last access/modification times (any of the pointers Sets the file creation and last access/modification times (any of the pointers
may be @NULL). may be @NULL).

View File

@@ -93,6 +93,7 @@
#include "wx/dynlib.h" #include "wx/dynlib.h"
#include "wx/dir.h" #include "wx/dir.h"
#include "wx/longlong.h" #include "wx/longlong.h"
#include "wx/uri.h"
#if defined(__WIN32__) && defined(__MINGW32__) #if defined(__WIN32__) && defined(__MINGW32__)
#include "wx/msw/gccpriv.h" #include "wx/msw/gccpriv.h"
@@ -2501,6 +2502,103 @@ bool wxFileName::SetPermissions(int permissions)
return wxChmod(GetFullPath(), permissions) == 0; return wxChmod(GetFullPath(), permissions) == 0;
} }
static const wxString g_unixPathString(wxT("/"));
static const wxString g_nativePathString(wxFILE_SEP_PATH);
// Returns the native path for a file URL
wxFileName wxFileName::URLToFileName(const wxString& url)
{
wxString path = url;
if ( path.Find(wxT("file://")) == 0 )
{
path = path.Mid(7);
}
else if ( path.Find(wxT("file:")) == 0 )
{
path = path.Mid(5);
}
// Remove preceding double slash on Mac Classic
#if defined(__WXMAC__) && !defined(__UNIX__)
else if ( path.Find(wxT("//")) == 0 )
path = path.Mid(2);
#endif
path = wxURI::Unescape(path);
#ifdef __WINDOWS__
// file urls either start with a forward slash (local harddisk),
// otherwise they have a servername/sharename notation,
// which only exists on msw and corresponds to a unc
if ( path.length() > 1 && (path[0u] == wxT('/') && path [1u] != wxT('/')) )
{
path = path.Mid(1);
}
else if ( (url.Find(wxT("file://")) == 0) &&
(path.Find(wxT('/')) != wxNOT_FOUND) &&
(path.length() > 1) && (path[1u] != wxT(':')) )
{
path = wxT("//") + path;
}
#endif
path.Replace(g_unixPathString, g_nativePathString);
return wxFileName(path, wxPATH_NATIVE);
}
// Escapes non-ASCII and others characters in file: URL to be valid URLs
static wxString EscapeFileNameCharsInURL(const char *in)
{
wxString s;
for ( const unsigned char *p = (const unsigned char*)in; *p; ++p )
{
const unsigned char c = *p;
// https://tools.ietf.org/html/rfc1738#section-5
if ( (c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
strchr("/:$-_.+!*'(),", c) ) // Plus '/' and ':'
{
s << c;
}
else
{
s << wxString::Format("%%%02x", c);
}
}
return s;
}
// Returns the file URL for a native path
wxString wxFileName::FileNameToURL(const wxFileName& filename)
{
wxFileName fn = filename;
fn.Normalize(wxPATH_NORM_DOTS | wxPATH_NORM_TILDE | wxPATH_NORM_ABSOLUTE);
wxString url = fn.GetFullPath(wxPATH_NATIVE);
#ifndef __UNIX__
// unc notation, wxMSW
if ( url.Find(wxT("\\\\")) == 0 )
{
url = url.Mid(2);
}
else
{
url = wxT("/") + url;
}
#endif
url.Replace(g_nativePathString, g_unixPathString);
// Do wxURI- and common practice-compatible escaping: encode the string
// into UTF-8, then escape anything non-ASCII:
return wxT("file://") + EscapeFileNameCharsInURL(url.utf8_str());
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// time functions // time functions
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -275,7 +275,7 @@ wxFSFile* wxLocalFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString&
{ {
// location has Unix path separators // location has Unix path separators
wxString right = GetRightLocation(location); wxString right = GetRightLocation(location);
wxFileName fn = wxFileSystem::URLToFileName(right); wxFileName fn = wxFileName::URLToFileName(right);
wxString fullpath = ms_root + fn.GetFullPath(); wxString fullpath = ms_root + fn.GetFullPath();
if (!wxFileExists(fullpath)) if (!wxFileExists(fullpath))
@@ -308,7 +308,7 @@ wxFSFile* wxLocalFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString&
wxString wxLocalFSHandler::FindFirst(const wxString& spec, int flags) wxString wxLocalFSHandler::FindFirst(const wxString& spec, int flags)
{ {
wxFileName fn = wxFileSystem::URLToFileName(GetRightLocation(spec)); wxFileName fn = wxFileName::URLToFileName(GetRightLocation(spec));
const wxString found = wxFindFirstFile(ms_root + fn.GetFullPath(), flags); const wxString found = wxFindFirstFile(ms_root + fn.GetFullPath(), flags);
if ( found.empty() ) if ( found.empty() )
return found; return found;
@@ -645,101 +645,16 @@ void wxFileSystem::CleanUpHandlers()
WX_CLEAR_LIST(wxList, m_Handlers); WX_CLEAR_LIST(wxList, m_Handlers);
} }
static const wxString g_unixPathString(wxT("/"));
static const wxString g_nativePathString(wxFILE_SEP_PATH);
// Returns the native path for a file URL // Returns the native path for a file URL
wxFileName wxFileSystem::URLToFileName(const wxString& url) wxFileName wxFileSystem::URLToFileName(const wxString& url)
{ {
wxString path = url; return wxFileName::URLToFileName( url );
if ( path.Find(wxT("file://")) == 0 )
{
path = path.Mid(7);
}
else if ( path.Find(wxT("file:")) == 0 )
{
path = path.Mid(5);
}
// Remove preceding double slash on Mac Classic
#if defined(__WXMAC__) && !defined(__UNIX__)
else if ( path.Find(wxT("//")) == 0 )
path = path.Mid(2);
#endif
path = wxURI::Unescape(path);
#ifdef __WINDOWS__
// file urls either start with a forward slash (local harddisk),
// otherwise they have a servername/sharename notation,
// which only exists on msw and corresponds to a unc
if ( path.length() > 1 && (path[0u] == wxT('/') && path [1u] != wxT('/')) )
{
path = path.Mid(1);
}
else if ( (url.Find(wxT("file://")) == 0) &&
(path.Find(wxT('/')) != wxNOT_FOUND) &&
(path.length() > 1) && (path[1u] != wxT(':')) )
{
path = wxT("//") + path;
}
#endif
path.Replace(g_unixPathString, g_nativePathString);
return wxFileName(path, wxPATH_NATIVE);
}
// Escapes non-ASCII and others characters in file: URL to be valid URLs
static wxString EscapeFileNameCharsInURL(const char *in)
{
wxString s;
for ( const unsigned char *p = (const unsigned char*)in; *p; ++p )
{
const unsigned char c = *p;
// https://tools.ietf.org/html/rfc1738#section-5
if ( (c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
strchr("/:$-_.+!*'(),", c) ) // Plus '/' and ':'
{
s << c;
}
else
{
s << wxString::Format("%%%02x", c);
}
}
return s;
} }
// Returns the file URL for a native path // Returns the file URL for a native path
wxString wxFileSystem::FileNameToURL(const wxFileName& filename) wxString wxFileSystem::FileNameToURL(const wxFileName& filename)
{ {
wxFileName fn = filename; return wxFileName::FileNameToURL( filename );
fn.Normalize(wxPATH_NORM_DOTS | wxPATH_NORM_TILDE | wxPATH_NORM_ABSOLUTE);
wxString url = fn.GetFullPath(wxPATH_NATIVE);
#ifndef __UNIX__
// unc notation, wxMSW
if ( url.Find(wxT("\\\\")) == 0 )
{
url = url.Mid(2);
}
else
{
url = wxT("/") + url;
}
#endif
url.Replace(g_nativePathString, g_unixPathString);
// Do wxURI- and common practice-compatible escaping: encode the string
// into UTF-8, then escape anything non-ASCII:
return wxT("file://") + EscapeFileNameCharsInURL(url.utf8_str());
} }

View File

@@ -1132,12 +1132,8 @@ static bool DoLaunchDefaultBrowserHelper(const wxString& url, int flags)
if ( params.scheme == "file" ) if ( params.scheme == "file" )
{ {
// TODO: extract URLToFileName() to some always compiled in
// function
#if wxUSE_FILESYSTEM
// for same reason as above, remove the scheme from the URL // for same reason as above, remove the scheme from the URL
params.path = wxFileSystem::URLToFileName(url).GetFullPath(); params.path = wxFileName::URLToFileName(url).GetFullPath();
#endif // wxUSE_FILESYSTEM
} }
} }

View File

@@ -1360,7 +1360,7 @@ void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt)
if(m_historyEnabled && !m_historyLoadingFromList && if(m_historyEnabled && !m_historyLoadingFromList &&
(url == GetCurrentURL() || (url == GetCurrentURL() ||
(GetCurrentURL().substr(0, 4) == "file" && (GetCurrentURL().substr(0, 4) == "file" &&
wxFileSystem::URLToFileName(GetCurrentURL()).GetFullPath() == url))) wxFileName::URLToFileName(GetCurrentURL()).GetFullPath() == url)))
{ {
//If we are not at the end of the list, then erase everything //If we are not at the end of the list, then erase everything
//between us and the end before adding the new page //between us and the end before adding the new page

View File

@@ -246,7 +246,7 @@ void FileFunctionsTestCase::DoFindFile(const wxString& filePath)
// Check if file can be found (method 2). // Check if file can be found (method 2).
wxFileSystem fs; wxFileSystem fs;
wxString furl = fs.FindFirst(filePath, wxFILE); wxString furl = fs.FindFirst(filePath, wxFILE);
wxFileName fname = wxFileSystem::URLToFileName(furl); wxFileName fname = wxFileName::URLToFileName(furl);
foundFile = fname.GetFullPath(); foundFile = fname.GetFullPath();
CPPUNIT_ASSERT_MESSAGE( msg, foundFile == filePath ); CPPUNIT_ASSERT_MESSAGE( msg, foundFile == filePath );
@@ -271,10 +271,10 @@ void FileFunctionsTestCase::FindFileNext()
// Check using method 2. // Check using method 2.
wxFileSystem fs; wxFileSystem fs;
wxString furl = fs.FindFirst(fileMask, wxFILE); wxString furl = fs.FindFirst(fileMask, wxFILE);
fn1 = wxFileSystem::URLToFileName(furl); fn1 = wxFileName::URLToFileName(furl);
foundFile1 = fn1.GetFullPath(); foundFile1 = fn1.GetFullPath();
furl = fs.FindNext(); furl = fs.FindNext();
fn2 = wxFileSystem::URLToFileName(furl); fn2 = wxFileName::URLToFileName(furl);
foundFile2 = fn2.GetFullPath(); foundFile2 = fn2.GetFullPath();
// Full names must be different. // Full names must be different.
CPPUNIT_ASSERT( fn1.GetFullPath() != fn2.GetFullPath() ); CPPUNIT_ASSERT( fn1.GetFullPath() != fn2.GetFullPath() );

View File

@@ -180,7 +180,7 @@ void FileSystemTestCase::FileNameToUrlConversion()
wxString url1 = wxFileSystem::FileNameToURL(fn1); wxString url1 = wxFileSystem::FileNameToURL(fn1);
CPPUNIT_ASSERT_EQUAL( d.expected, url1 ); CPPUNIT_ASSERT_EQUAL( d.expected, url1 );
CPPUNIT_ASSERT( fn1.SameAs(wxFileSystem::URLToFileName(url1)) ); CPPUNIT_ASSERT( fn1.SameAs(wxFileName::URLToFileName(url1)) );
} }
} }
@@ -196,7 +196,7 @@ void FileSystemTestCase::UnicodeFileNameToUrlConversion()
wxString url = wxFileSystem::FileNameToURL(filename); wxString url = wxFileSystem::FileNameToURL(filename);
CPPUNIT_ASSERT( filename.SameAs(wxFileSystem::URLToFileName(url)) ); CPPUNIT_ASSERT( filename.SameAs(wxFileName::URLToFileName(url)) );
} }
#endif // wxUSE_FILESYSTEM #endif // wxUSE_FILESYSTEM