]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/filesys.cpp
swap all characters instead of just the last one in a loop in wxMBConv_iconv::ToWChar()
[wxWidgets.git] / src / common / filesys.cpp
index 57fc6e3712e92e001da5e259d84a77f10a6eba5d..71dc13788b64e584e8970e1a8ceadd764827c200 100644 (file)
 #include "wx/mimetype.h"
 #include "wx/filename.h"
 #include "wx/tokenzr.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;
@@ -68,27 +85,27 @@ wxString wxFileSystemHandler::GetMimeTypeFromExt(const wxString& location)
                            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()
         };
@@ -122,7 +139,8 @@ wxString wxFileSystemHandler::GetMimeTypeFromExt(const wxString& location)
 
 
 
-wxString wxFileSystemHandler::GetProtocol(const wxString& location) const
+/* static */
+wxString wxFileSystemHandler::GetProtocol(const wxString& location)
 {
     wxString s = wxEmptyString;
     int i, l = location.length();
@@ -137,7 +155,8 @@ wxString wxFileSystemHandler::GetProtocol(const wxString& location) const
 }
 
 
-wxString wxFileSystemHandler::GetLeftLocation(const wxString& location) const
+/* static */
+wxString wxFileSystemHandler::GetLeftLocation(const wxString& location)
 {
     int i;
     bool fnd = false;
@@ -149,7 +168,8 @@ wxString wxFileSystemHandler::GetLeftLocation(const wxString& location) const
     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;
@@ -165,7 +185,8 @@ wxString wxFileSystemHandler::GetRightLocation(const wxString& location) const
     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();
@@ -214,10 +235,10 @@ wxFSFile* wxLocalFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString&
 
     // 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
@@ -229,7 +250,7 @@ wxFSFile* wxLocalFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString&
 
     return new wxFSFile(is,
                         right,
-                        GetMimeTypeFromExt(location),
+                        wxEmptyString,
                         GetAnchor(location)
 #if wxUSE_DATETIME
                         ,wxDateTime(wxFileModificationTime(fullpath))
@@ -261,6 +282,12 @@ IMPLEMENT_ABSTRACT_CLASS(wxFSFile, wxObject)
 wxList wxFileSystem::m_Handlers;
 
 
+wxFileSystem::~wxFileSystem()
+{
+    WX_CLEAR_HASH_MAP(wxFSHandlerHash, m_LocalHandlers)
+}
+
+
 static wxString MakeCorrectPath(const wxString& path)
 {
     wxString p(path);
@@ -357,8 +384,30 @@ void wxFileSystem::ChangePathTo(const wxString& location, bool is_dir)
 
 
 
-wxFSFile* wxFileSystem::OpenFile(const wxString& location)
+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;
@@ -369,7 +418,7 @@ wxFSFile* wxFileSystem::OpenFile(const wxString& location)
     meta = 0;
     for (i = 0; i < ln; i++)
     {
-        switch (loc[i])
+        switch ( loc[i].GetValue() )
         {
             case wxT('/') : case wxT(':') : case wxT('#') :
                 meta = loc[i];
@@ -388,7 +437,7 @@ wxFSFile* wxFileSystem::OpenFile(const wxString& location)
             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();
@@ -404,12 +453,21 @@ wxFSFile* wxFileSystem::OpenFile(const wxString& location)
             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();
         }
     }
+
+    if (s && (flags & wxFS_SEEKABLE) != 0 && !s->GetStream()->IsSeekable())
+    {
+        wxBackedInputStream *stream;
+        stream = new wxBackedInputStream(s->DetachStream());
+        stream->FindLength();
+        s->SetStream(stream);
+    }
+
     return (s);
 }
 
@@ -428,18 +486,24 @@ wxString wxFileSystem::FindFirst(const wxString& spec, int flags)
     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();
     }
 
@@ -455,16 +519,19 @@ wxString wxFileSystem::FindNext()
 }
 
 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() )
@@ -472,7 +539,7 @@ bool wxFileSystem::FindFileInPath(wxString *pStr,
         wxString strFile = tokenizer.GetNextToken();
         if ( !wxEndsWithPathSeparator(strFile) )
             strFile += wxFILE_SEP_PATH;
-        strFile += basename;
+        strFile += name;
 
         wxFSFile *file = OpenFile(strFile);
         if ( file )
@@ -547,8 +614,7 @@ wxFileName wxFileSystem::URLToFileName(const wxString& url)
         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),
@@ -595,7 +661,18 @@ wxString wxFileSystem::FileNameToURL(const wxFileName& filename)
 #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;