home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / common / filesys.cpp < prev    next >
C/C++ Source or Header  |  2002-12-16  |  16KB  |  570 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        filesys.cpp
  3. // Purpose:     wxFileSystem class - interface for opening files
  4. // Author:      Vaclav Slavik
  5. // Copyright:   (c) 1999 Vaclav Slavik
  6. // CVS-ID:      $Id: filesys.cpp,v 1.36.2.5 2002/12/16 00:10:27 VS Exp $
  7. // Licence:     wxWindows Licence
  8. /////////////////////////////////////////////////////////////////////////////
  9.  
  10. #ifdef __GNUG__
  11. #pragma implementation "filesys.h"
  12. #endif
  13.  
  14. #include "wx/wxprec.h"
  15.  
  16. #ifdef __BORLANDC__
  17. #pragma hdrstop
  18. #endif
  19.  
  20.  
  21. #if wxUSE_FILESYSTEM
  22.  
  23. #include "wx/wfstream.h"
  24. #include "wx/module.h"
  25. #include "wx/filesys.h"
  26. #include "wx/mimetype.h"
  27. #include "wx/filename.h"
  28. #include "wx/log.h"
  29.  
  30.  
  31.  
  32. //--------------------------------------------------------------------------------
  33. // wxFileSystemHandler
  34. //--------------------------------------------------------------------------------
  35.  
  36. IMPLEMENT_ABSTRACT_CLASS(wxFileSystemHandler, wxObject)
  37.  
  38.  
  39. #if wxUSE_MIMETYPE
  40. static wxFileTypeInfo *gs_FSMimeFallbacks = NULL;
  41. #endif
  42.  
  43. wxString wxFileSystemHandler::GetMimeTypeFromExt(const wxString& location)
  44. {
  45.     wxString ext, mime;
  46.     wxString loc = GetRightLocation(location);
  47.     char c;
  48.     int l = loc.Length(), l2;
  49.  
  50.     l2 = l;
  51.     for (int i = l-1; i >= 0; i--)
  52.     {
  53.         c = loc[(unsigned int) i];
  54.         if ( c == wxT('#') )
  55.             l2 = i + 1;
  56.         if ( c == wxT('.') )
  57.         {
  58.             ext = loc.Right(l2-i-1);
  59.             break;
  60.         }
  61.         if ( (c == wxT('/')) || (c == wxT('\\')) || (c == wxT(':')) )
  62.             return wxEmptyString;
  63.     }
  64.  
  65. #if wxUSE_MIMETYPE
  66.     static bool s_MinimalMimeEnsured = FALSE;
  67.     if (!s_MinimalMimeEnsured) {
  68.         wxTheMimeTypesManager->AddFallbacks(gs_FSMimeFallbacks);
  69.         s_MinimalMimeEnsured = TRUE;
  70.     }
  71.  
  72.     wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(ext);
  73.     if ( !ft || !ft -> GetMimeType(&mime) )
  74.     {
  75.         mime = wxEmptyString;
  76.     }
  77.  
  78.     delete ft;
  79.  
  80.     return mime;
  81. #else
  82.     if ( ext.IsSameAs(wxT("htm"), FALSE) || ext.IsSameAs(_T("html"), FALSE) )
  83.         return wxT("text/html");
  84.     if ( ext.IsSameAs(wxT("jpg"), FALSE) || ext.IsSameAs(_T("jpeg"), FALSE) )
  85.         return wxT("image/jpeg");
  86.     if ( ext.IsSameAs(wxT("gif"), FALSE) )
  87.         return wxT("image/gif");
  88.     if ( ext.IsSameAs(wxT("png"), FALSE) )
  89.         return wxT("image/png");
  90.     if ( ext.IsSameAs(wxT("bmp"), FALSE) )
  91.         return wxT("image/bmp");
  92.     return wxEmptyString;
  93. #endif
  94. }
  95.  
  96.  
  97.  
  98. wxString wxFileSystemHandler::GetProtocol(const wxString& location) const
  99. {
  100.     wxString s = wxEmptyString;
  101.     int i, l = location.Length();
  102.     bool fnd;
  103.  
  104.     fnd = FALSE;
  105.     for (i = l-1; (i >= 0) && ((location[i] != wxT('#')) || (!fnd)); i--) {
  106.         if ((location[i] == wxT(':')) && (i != 1 /*win: C:\path*/)) fnd = TRUE;
  107.     }
  108.     if (!fnd) return wxT("file");
  109.     for (++i; (i < l) && (location[i] != wxT(':')); i++) s << location[i];
  110.     return s;
  111. }
  112.  
  113.  
  114. wxString wxFileSystemHandler::GetLeftLocation(const wxString& location) const
  115. {
  116.     int i;
  117.     bool fnd;
  118.  
  119.     fnd = FALSE;
  120.     for (i = location.Length()-1; i >= 0; i--) {
  121.         if ((location[i] == wxT(':')) && (i != 1 /*win: C:\path*/)) fnd = TRUE;
  122.         else if (fnd && (location[i] == wxT('#'))) return location.Left(i);
  123.     }
  124.     return wxEmptyString;
  125. }
  126.  
  127. wxString wxFileSystemHandler::GetRightLocation(const wxString& location) const
  128. {
  129.     int i, l = location.Length();
  130.     int l2 = l + 1;
  131.  
  132.     for (i = l-1; 
  133.          (i >= 0) && 
  134.          ((location[i] != wxT(':')) || (i == 1) || (location[i-2] == wxT(':')));
  135.          i--)
  136.     {
  137.         if (location[i] == wxT('#')) l2 = i + 1;
  138.     }
  139.     if (i == 0) return wxEmptyString;
  140.     else return location.Mid(i + 1, l2 - i - 2);
  141. }
  142.  
  143. wxString wxFileSystemHandler::GetAnchor(const wxString& location) const
  144. {
  145.     char c;
  146.     int l = location.Length();
  147.  
  148.     for (int i = l-1; i >= 0; i--) {
  149.         c = location[i];
  150.         if (c == wxT('#')) return location.Right(l-i-1);
  151.         else if ((c == wxT('.')) || (c == wxT('/')) || (c == wxT('\\')) || (c == wxT(':'))) return wxEmptyString;
  152.     }
  153.     return wxEmptyString;
  154. }
  155.  
  156.  
  157. wxString wxFileSystemHandler::FindFirst(const wxString& WXUNUSED(spec),
  158.                                         int WXUNUSED(flags))
  159. {
  160.     return wxEmptyString;
  161. }
  162.  
  163. wxString wxFileSystemHandler::FindNext()
  164. {
  165.     return wxEmptyString;
  166. }
  167.  
  168. //--------------------------------------------------------------------------------
  169. // wxLocalFSHandler
  170. //--------------------------------------------------------------------------------
  171.  
  172.  
  173. wxString wxLocalFSHandler::ms_root;
  174.  
  175. bool wxLocalFSHandler::CanOpen(const wxString& location)
  176. {
  177.     return GetProtocol(location) == wxT("file");
  178. }
  179.  
  180. wxFSFile* wxLocalFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString& location)
  181. {
  182.     // location has Unix path separators
  183.     wxString right = GetRightLocation(location);
  184.     wxFileName fn = wxFileSystem::URLToFileName(right);
  185.     wxString fullpath = ms_root + fn.GetFullPath();
  186.  
  187.     if (!wxFileExists(fullpath))
  188.         return (wxFSFile*) NULL;
  189.  
  190.     return new wxFSFile(new wxFFileInputStream(fullpath),
  191.                         right,
  192.                         GetMimeTypeFromExt(location),
  193.                         GetAnchor(location),
  194.                         wxDateTime(wxFileModificationTime(fullpath)));
  195. }
  196.  
  197. wxString wxLocalFSHandler::FindFirst(const wxString& spec, int flags)
  198. {
  199.     wxFileName fn = wxFileSystem::URLToFileName(GetRightLocation(spec));
  200.     return wxFindFirstFile(ms_root + fn.GetFullPath(), flags);
  201. }
  202.  
  203. wxString wxLocalFSHandler::FindNext()
  204. {
  205.     return wxFindNextFile();
  206. }
  207.  
  208.  
  209.  
  210. //-----------------------------------------------------------------------------
  211. // wxFileSystem
  212. //-----------------------------------------------------------------------------
  213.  
  214. IMPLEMENT_DYNAMIC_CLASS(wxFileSystem, wxObject)
  215. IMPLEMENT_ABSTRACT_CLASS(wxFSFile, wxObject)
  216.  
  217.  
  218. wxList wxFileSystem::m_Handlers;
  219.  
  220.  
  221. static wxString MakeCorrectPath(const wxString& path)
  222. {
  223.     wxString p(path);
  224.     wxString r;
  225.     int i, j, cnt;
  226.  
  227.     cnt = p.Length();
  228.     for (i = 0; i < cnt; i++)
  229.       if (p.GetChar(i) == wxT('\\')) p.GetWritableChar(i) = wxT('/'); // Want to be windows-safe
  230.  
  231.     if (p.Left(2) == wxT("./")) { p = p.Mid(2); cnt -= 2; }
  232.  
  233.     if (cnt < 3) return p;
  234.  
  235.     r << p.GetChar(0) << p.GetChar(1);
  236.  
  237.     // skip trailing ../.., if any
  238.     for (i = 2; i < cnt && (p.GetChar(i) == wxT('/') || p.GetChar(i) == wxT('.')); i++) r << p.GetChar(i);
  239.  
  240.     // remove back references: translate dir1/../dir2 to dir2
  241.     for (; i < cnt; i++)
  242.     {
  243.         r << p.GetChar(i);
  244.         if (p.GetChar(i) == wxT('/') && p.GetChar(i-1) == wxT('.') && p.GetChar(i-2) == wxT('.'))
  245.         {
  246.             for (j = r.Length() - 2; j >= 0 && r.GetChar(j) != wxT('/') && r.GetChar(j) != wxT(':'); j--) {}
  247.             if (j >= 0 && r.GetChar(j) != wxT(':'))
  248.             {
  249.                 for (j = j - 1; j >= 0 && r.GetChar(j) != wxT('/') && r.GetChar(j) != wxT(':'); j--) {}
  250.                 r.Remove(j + 1);
  251.             }
  252.         }
  253.     }
  254.  
  255.     for (; i < cnt; i++) r << p.GetChar(i);
  256.  
  257.     return r;
  258. }
  259.  
  260.  
  261. void wxFileSystem::ChangePathTo(const wxString& location, bool is_dir)
  262. {
  263.     int i, pathpos = -1;
  264.  
  265.     m_Path = MakeCorrectPath(location);
  266.  
  267.     if (is_dir)
  268.     {
  269.         if (m_Path.Length() > 0 && m_Path.Last() != wxT('/') && m_Path.Last() != wxT(':'))
  270.             m_Path << wxT('/');
  271.     }
  272.  
  273.     else
  274.     {
  275.         for (i = m_Path.Length()-1; i >= 0; i--)
  276.         {
  277.             if (m_Path[(unsigned int) i] == wxT('/'))
  278.             {
  279.                 if ((i > 1) && (m_Path[(unsigned int) (i-1)] == wxT('/')) && (m_Path[(unsigned int) (i-2)] == wxT(':')))
  280.                 {
  281.                     i -= 2;
  282.                     continue;
  283.                 }
  284.                 else
  285.                 {
  286.                     pathpos = i;
  287.                     break;
  288.                 }
  289.             }
  290.             else if (m_Path[(unsigned int) i] == wxT(':')) {
  291.                 pathpos = i;
  292.                 break;
  293.             }
  294.         }
  295.         if (pathpos == -1)
  296.         {
  297.             for (i = 0; i < (int) m_Path.Length(); i++)
  298.             {
  299.                 if (m_Path[(unsigned int) i] == wxT(':'))
  300.                 {
  301.                     m_Path.Remove(i+1);
  302.                     break;
  303.                 }
  304.             }
  305.             if (i == (int) m_Path.Length())
  306.                 m_Path = wxEmptyString;
  307.         }
  308.         else
  309.         {
  310.             m_Path.Remove(pathpos+1);
  311.         }
  312.     }
  313. }
  314.  
  315.  
  316.  
  317. wxFSFile* wxFileSystem::OpenFile(const wxString& location)
  318. {
  319.     wxString loc = MakeCorrectPath(location);
  320.     unsigned i, ln;
  321.     char meta;
  322.     wxFSFile *s = NULL;
  323.     wxNode *node;
  324.  
  325.     ln = loc.Length();
  326.     meta = 0;
  327.     for (i = 0; i < ln; i++)
  328.     {
  329.         switch (loc[i])
  330.         {
  331.             case wxT('/') : case wxT(':') : case wxT('#') :
  332.                 meta = loc[i];
  333.                 break;
  334.         }
  335.         if (meta != 0) break;
  336.     }
  337.     m_LastName = wxEmptyString;
  338.  
  339.     // try relative paths first :
  340.     if (meta != wxT(':'))
  341.     {
  342.         node = m_Handlers.GetFirst();
  343.         while (node)
  344.         {
  345.             wxFileSystemHandler *h = (wxFileSystemHandler*) node -> GetData();
  346.             if (h->CanOpen(m_Path + loc))
  347.             {
  348.                 s = h->OpenFile(*this, m_Path + loc);
  349.                 if (s) { m_LastName = m_Path + loc; break; }
  350.             }
  351.             node = node->GetNext();
  352.         }
  353.     }
  354.  
  355.     // if failed, try absolute paths :
  356.     if (s == NULL)
  357.     {
  358.         node = m_Handlers.GetFirst();
  359.         while (node)
  360.         {
  361.             wxFileSystemHandler *h = (wxFileSystemHandler*) node->GetData();
  362.             if (h->CanOpen(loc))
  363.             {
  364.                 s = h->OpenFile(*this, loc);
  365.                 if (s) { m_LastName = loc; break; }
  366.             }
  367.             node = node->GetNext();
  368.         }
  369.     }
  370.     return (s);
  371. }
  372.  
  373.  
  374.  
  375. wxString wxFileSystem::FindFirst(const wxString& spec, int flags)
  376. {
  377.     wxNode *node;
  378.     wxString spec2(spec);
  379.  
  380.     m_FindFileHandler = NULL;
  381.  
  382.     for (int i = spec2.Length()-1; i >= 0; i--)
  383.         if (spec2[(unsigned int) i] == wxT('\\')) spec2.GetWritableChar(i) = wxT('/'); // Want to be windows-safe
  384.  
  385.     node = m_Handlers.GetFirst();
  386.     while (node)
  387.     {
  388.         m_FindFileHandler = (wxFileSystemHandler*) node -> GetData();
  389.         if (m_FindFileHandler -> CanOpen(m_Path + spec2))
  390.             return m_FindFileHandler -> FindFirst(m_Path + spec2, flags);
  391.         node = node->GetNext();
  392.     }
  393.  
  394.     node = m_Handlers.GetFirst();
  395.     while (node)
  396.     {
  397.         m_FindFileHandler = (wxFileSystemHandler*) node -> GetData();
  398.         if (m_FindFileHandler -> CanOpen(spec2))
  399.             return m_FindFileHandler -> FindFirst(spec2, flags);
  400.         node = node->GetNext();
  401.     }
  402.  
  403.     return wxEmptyString;
  404. }
  405.  
  406.  
  407.  
  408. wxString wxFileSystem::FindNext()
  409. {
  410.     if (m_FindFileHandler == NULL) return wxEmptyString;
  411.     else return m_FindFileHandler -> FindNext();
  412. }
  413.  
  414.  
  415.  
  416. void wxFileSystem::AddHandler(wxFileSystemHandler *handler)
  417. {
  418.     m_Handlers.Append(handler);
  419. }
  420.  
  421.  
  422. void wxFileSystem::CleanUpHandlers()
  423. {
  424.     m_Handlers.DeleteContents(TRUE);
  425.     m_Handlers.Clear();
  426. }
  427.  
  428. const static wxString g_unixPathString(wxT("/"));
  429. const static wxString g_nativePathString(wxFILE_SEP_PATH);
  430.  
  431. // Returns the native path for a file URL
  432. wxFileName wxFileSystem::URLToFileName(const wxString& url)
  433. {
  434.     wxString path = url;
  435.  
  436.     if ( path.Find(wxT("file://")) == 0 )
  437.     {
  438.         path = path.Mid(7);
  439.     }
  440.     else if ( path.Find(wxT("file:")) == 0 )
  441.     {
  442.         path = path.Mid(5);
  443.     }
  444.     // Remove preceding double slash on Mac Classic
  445. #if defined(__WXMAC__) && !defined(__UNIX__)
  446.     else if ( path.Find(wxT("//")) == 0 )
  447.         path = path.Mid(2);
  448. #endif
  449.     
  450.     path.Replace(wxT("%25"), wxT("%"));
  451.     path.Replace(wxT("%3A"), wxT(":"));
  452.  
  453. #ifdef __WXMSW__
  454.     // file urls either start with a forward slash (local harddisk),
  455.     // otherwise they have a servername/sharename notation,
  456.     // which only exists on msw and corresponds to a unc
  457.     if ( path[0u] == wxT('/') && path [1u] != wxT('/'))
  458.     {
  459.         path = path.Mid(1);
  460.     }
  461.     else if ( (url.Find(wxT("file://")) == 0) &&
  462.               (path.Find(wxT('/')) != wxNOT_FOUND) &&
  463.               (path.Length() > 1) && (path[1u] != wxT(':')) )
  464.     {
  465.         path = wxT("//") + path;
  466.     }
  467. #endif
  468.  
  469.     path.Replace(g_unixPathString, g_nativePathString);
  470.  
  471.     return wxFileName(path, wxPATH_NATIVE);
  472. }
  473.  
  474. // Returns the file URL for a native path
  475. wxString wxFileSystem::FileNameToURL(const wxFileName& filename)
  476. {
  477.     wxFileName fn = filename;
  478.     fn.Normalize(wxPATH_NORM_DOTS | wxPATH_NORM_TILDE | wxPATH_NORM_ABSOLUTE);
  479.     wxString url = fn.GetFullPath(wxPATH_NATIVE);
  480.  
  481. #ifndef __UNIX__
  482.     // unc notation, wxMSW
  483.     if ( url.Find(wxT("\\\\")) == 0 ) 
  484.     {
  485.         url = url.Mid(2);
  486.     }
  487.     else
  488.     {
  489.         url = wxT("/") + url;
  490. #ifdef __WXMAC__
  491.         url = wxT("/") + url;
  492. #endif
  493.  
  494.     }
  495. #endif
  496.  
  497.     url.Replace(g_nativePathString, g_unixPathString);
  498.     url.Replace(wxT("%"), wxT("%25"));
  499.     url.Replace(wxT(":"), wxT("%3A"));
  500.     url = wxT("file:") + url;
  501.     return url;
  502. }
  503.  
  504.  
  505. ///// Module:
  506.  
  507. class wxFileSystemModule : public wxModule
  508. {
  509.     DECLARE_DYNAMIC_CLASS(wxFileSystemModule)
  510.  
  511.     public:
  512.         virtual bool OnInit()
  513.         {
  514.             wxFileSystem::AddHandler(new wxLocalFSHandler);
  515.  
  516.         #if wxUSE_MIMETYPE
  517.             gs_FSMimeFallbacks = new wxFileTypeInfo[6];
  518.             gs_FSMimeFallbacks[0] =
  519.             wxFileTypeInfo(_T("image/jpeg"),
  520.                            _T(""),
  521.                            _T(""),
  522.                            _T("JPEG image (from fallback)"),
  523.                            _T("jpg"), _T("jpeg"), NULL);
  524.             gs_FSMimeFallbacks[1] =
  525.             wxFileTypeInfo(_T("image/gif"),
  526.                            _T(""),
  527.                            _T(""),
  528.                            _T("GIF image (from fallback)"),
  529.                            _T("gif"), NULL);
  530.             gs_FSMimeFallbacks[2] =
  531.             wxFileTypeInfo(_T("image/png"),
  532.                            _T(""),
  533.                            _T(""),
  534.                            _T("PNG image (from fallback)"),
  535.                            _T("png"), NULL);
  536.             gs_FSMimeFallbacks[3] =
  537.             wxFileTypeInfo(_T("image/bmp"),
  538.                            _T(""),
  539.                            _T(""),
  540.                            _T("windows bitmap image (from fallback)"),
  541.                            _T("bmp"), NULL);
  542.             gs_FSMimeFallbacks[4] =
  543.             wxFileTypeInfo(_T("text/html"),
  544.                            _T(""),
  545.                            _T(""),
  546.                            _T("HTML document (from fallback)"),
  547.                            _T("htm"), _T("html"), NULL);
  548.             gs_FSMimeFallbacks[5] =
  549.             // must terminate the table with this!
  550.             wxFileTypeInfo();
  551.         #endif
  552.             return TRUE;
  553.         }
  554.         virtual void OnExit()
  555.         {
  556.         #if wxUSE_MIMETYPE
  557.             delete [] gs_FSMimeFallbacks;
  558.         #endif
  559.             wxFileSystem::CleanUpHandlers();
  560.         }
  561. };
  562.  
  563. IMPLEMENT_DYNAMIC_CLASS(wxFileSystemModule, wxModule)
  564.  
  565. #endif
  566.   // wxUSE_FILESYSTEM
  567.  
  568.  
  569.  
  570.