#include "wx/mimetype.h"
#include "wx/filename.h"
#include "wx/tokenzr.h"
-#include "wx/fileback.h"
+#include "wx/uri.h"
+#include "wx/private/fileback.h"
+// ----------------------------------------------------------------------------
+// wxFSFile
+// ----------------------------------------------------------------------------
-//--------------------------------------------------------------------------------
+const wxString& wxFSFile::GetMimeType() const
+{
+ if ( m_MimeType.empty() && !m_Location.empty() )
+ {
+ wxConstCast(this, wxFSFile)->m_MimeType =
+ wxFileSystemHandler::GetMimeTypeFromExt(m_Location);
+ }
+
+ return m_MimeType;
+}
+
+// ----------------------------------------------------------------------------
// wxFileSystemHandler
-//--------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
IMPLEMENT_ABSTRACT_CLASS(wxFileSystemHandler, wxObject)
+/* static */
wxString wxFileSystemHandler::GetMimeTypeFromExt(const wxString& location)
{
wxString ext, mime;
wxEmptyString,
wxEmptyString,
_T("JPEG image (from fallback)"),
- _T("jpg"), _T("jpeg"), _T("JPG"), _T("JPEG"), NULL),
+ _T("jpg"), _T("jpeg"), _T("JPG"), _T("JPEG"), wxNullPtr),
wxFileTypeInfo(_T("image/gif"),
wxEmptyString,
wxEmptyString,
_T("GIF image (from fallback)"),
- _T("gif"), _T("GIF"), NULL),
+ _T("gif"), _T("GIF"), wxNullPtr),
wxFileTypeInfo(_T("image/png"),
wxEmptyString,
wxEmptyString,
_T("PNG image (from fallback)"),
- _T("png"), _T("PNG"), NULL),
+ _T("png"), _T("PNG"), wxNullPtr),
wxFileTypeInfo(_T("image/bmp"),
wxEmptyString,
wxEmptyString,
_T("windows bitmap image (from fallback)"),
- _T("bmp"), _T("BMP"), NULL),
+ _T("bmp"), _T("BMP"), wxNullPtr),
wxFileTypeInfo(_T("text/html"),
wxEmptyString,
wxEmptyString,
_T("HTML document (from fallback)"),
- _T("htm"), _T("html"), _T("HTM"), _T("HTML"), NULL),
+ _T("htm"), _T("html"), _T("HTM"), _T("HTML"), wxNullPtr),
// must terminate the table with this!
wxFileTypeInfo()
};
-wxString wxFileSystemHandler::GetProtocol(const wxString& location) const
+/* static */
+wxString wxFileSystemHandler::GetProtocol(const wxString& location)
{
wxString s = wxEmptyString;
int i, l = location.length();
}
-wxString wxFileSystemHandler::GetLeftLocation(const wxString& location) const
+/* static */
+wxString wxFileSystemHandler::GetLeftLocation(const wxString& location)
{
int i;
bool fnd = false;
return wxEmptyString;
}
-wxString wxFileSystemHandler::GetRightLocation(const wxString& location) const
+/* static */
+wxString wxFileSystemHandler::GetRightLocation(const wxString& location)
{
int i, l = location.length();
int l2 = l + 1;
else return location.Mid(i + 1, l2 - i - 2);
}
-wxString wxFileSystemHandler::GetAnchor(const wxString& location) const
+/* static */
+wxString wxFileSystemHandler::GetAnchor(const wxString& location)
{
wxChar c;
int l = location.length();
// we need to check whether we can really read from this file, otherwise
// wxFSFile is not going to work
-#if wxUSE_FILE
- wxFileInputStream *is = new wxFileInputStream(fullpath);
-#elif wxUSE_FFILE
+#if wxUSE_FFILE
wxFFileInputStream *is = new wxFFileInputStream(fullpath);
+#elif wxUSE_FILE
+ wxFileInputStream *is = new wxFileInputStream(fullpath);
#else
#error One of wxUSE_FILE or wxUSE_FFILE must be set to 1 for wxFSHandler to work
#endif
return new wxFSFile(is,
right,
- GetMimeTypeFromExt(location),
+ wxEmptyString,
GetAnchor(location)
#if wxUSE_DATETIME
,wxDateTime(wxFileModificationTime(fullpath))
wxList wxFileSystem::m_Handlers;
+wxFileSystem::~wxFileSystem()
+{
+ WX_CLEAR_HASH_MAP(wxFSHandlerHash, m_LocalHandlers)
+}
+
+
static wxString MakeCorrectPath(const wxString& path)
{
wxString p(path);
+wxFileSystemHandler *wxFileSystem::MakeLocal(wxFileSystemHandler *h)
+{
+ wxClassInfo *classinfo = h->GetClassInfo();
+
+ if (classinfo->IsDynamic())
+ {
+ wxFileSystemHandler*& local = m_LocalHandlers[classinfo];
+ if (!local)
+ local = (wxFileSystemHandler*)classinfo->CreateObject();
+ return local;
+ }
+ else
+ {
+ return h;
+ }
+}
+
+
+
wxFSFile* wxFileSystem::OpenFile(const wxString& location, int flags)
{
+ if ((flags & wxFS_READ) == 0)
+ return NULL;
+
wxString loc = MakeCorrectPath(location);
unsigned i, ln;
wxChar meta;
meta = 0;
for (i = 0; i < ln; i++)
{
- switch (loc[i])
+ switch ( loc[i].GetValue() )
{
case wxT('/') : case wxT(':') : case wxT('#') :
meta = loc[i];
wxFileSystemHandler *h = (wxFileSystemHandler*) node -> GetData();
if (h->CanOpen(m_Path + loc))
{
- s = h->OpenFile(*this, m_Path + loc);
+ s = MakeLocal(h)->OpenFile(*this, m_Path + loc);
if (s) { m_LastName = m_Path + loc; break; }
}
node = node->GetNext();
wxFileSystemHandler *h = (wxFileSystemHandler*) node->GetData();
if (h->CanOpen(loc))
{
- s = h->OpenFile(*this, loc);
+ s = MakeLocal(h)->OpenFile(*this, loc);
if (s) { m_LastName = loc; break; }
}
node = node->GetNext();
node = m_Handlers.GetFirst();
while (node)
{
- m_FindFileHandler = (wxFileSystemHandler*) node -> GetData();
- if (m_FindFileHandler -> CanOpen(m_Path + spec2))
+ wxFileSystemHandler *h = (wxFileSystemHandler*) node -> GetData();
+ if (h -> CanOpen(m_Path + spec2))
+ {
+ m_FindFileHandler = MakeLocal(h);
return m_FindFileHandler -> FindFirst(m_Path + spec2, flags);
+ }
node = node->GetNext();
}
node = m_Handlers.GetFirst();
while (node)
{
- m_FindFileHandler = (wxFileSystemHandler*) node -> GetData();
- if (m_FindFileHandler -> CanOpen(spec2))
+ wxFileSystemHandler *h = (wxFileSystemHandler*) node -> GetData();
+ if (h -> CanOpen(spec2))
+ {
+ m_FindFileHandler = MakeLocal(h);
return m_FindFileHandler -> FindFirst(spec2, flags);
+ }
node = node->GetNext();
}
}
bool wxFileSystem::FindFileInPath(wxString *pStr,
- const wxChar *path,
- const wxChar *basename)
+ const wxString& path,
+ const wxString& basename)
{
// we assume that it's not empty
- wxCHECK_MSG( !wxIsEmpty(basename), false,
+ wxCHECK_MSG( !basename.empty(), false,
_T("empty file name in wxFileSystem::FindFileInPath"));
+ wxString name;
// skip path separator in the beginning of the file name if present
- if ( wxIsPathSeparator(*basename) )
- basename++;
+ if ( wxIsPathSeparator(basename[0u]) )
+ name = basename.substr(1);
+ else
+ name = basename;
wxStringTokenizer tokenizer(path, wxPATH_SEP);
while ( tokenizer.HasMoreTokens() )
wxString strFile = tokenizer.GetNextToken();
if ( !wxEndsWithPathSeparator(strFile) )
strFile += wxFILE_SEP_PATH;
- strFile += basename;
+ strFile += name;
wxFSFile *file = OpenFile(strFile);
if ( file )
path = path.Mid(2);
#endif
- path.Replace(wxT("%25"), wxT("%"));
- path.Replace(wxT("%3A"), wxT(":"));
+ path = wxURI::Unescape(path);
#ifdef __WXMSW__
// file urls either start with a forward slash (local harddisk),
#endif
url.Replace(g_nativePathString, g_unixPathString);
- url.Replace(wxT("%"), wxT("%25"));
+ url.Replace(wxT("%"), wxT("%25")); // '%'s must be replaced first!
+ url.Replace(wxT("#"), wxT("%23"));
+
+ // notice that all colons *must* be encoded in the paths used by
+ // wxFileSystem even though this makes URLs produced by this method
+ // unusable with IE under Windows as it requires "file:///c:/foo.bar" and
+ // doesn't accept "file:///c%3a/foo.bar" -- but then we never made any
+ // guarantees about general suitability of the strings returned by this
+ // method, they must work with wxFileSystem only and not encoding the colon
+ // breaks handling of "http://wherever/whatever.zip#zip:filename.ext" URLs
+ // so we really can't do this without heavy changes to the parsing code
+ // here, in particular in GetRightLocation()
url.Replace(wxT(":"), wxT("%3A"));
url = wxT("file:") + url;
return url;