]>
git.saurik.com Git - wxWidgets.git/blob - src/common/filesys.cpp
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxFileSystem class - interface for opening files
4 // Author: Vaclav Slavik
5 // Copyright: (c) 1999 Vaclav Slavik
7 // Licence: wxWindows Licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "filesys.h"
14 #include "wx/wxprec.h"
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"
32 //--------------------------------------------------------------------------------
33 // wxFileSystemHandler
34 //--------------------------------------------------------------------------------
36 IMPLEMENT_ABSTRACT_CLASS(wxFileSystemHandler
, wxObject
)
40 static wxFileTypeInfo
*gs_FSMimeFallbacks
= NULL
;
43 wxString
wxFileSystemHandler::GetMimeTypeFromExt(const wxString
& location
)
46 wxString loc
= GetRightLocation(location
);
48 int l
= loc
.Length(), l2
;
51 for (int i
= l
-1; i
>= 0; i
--)
53 c
= loc
[(unsigned int) i
];
58 ext
= loc
.Right(l2
-i
-1);
61 if ( (c
== wxT('/')) || (c
== wxT('\\')) || (c
== wxT(':')) )
66 static bool s_MinimalMimeEnsured
= FALSE
;
67 if (!s_MinimalMimeEnsured
) {
68 wxTheMimeTypesManager
->AddFallbacks(gs_FSMimeFallbacks
);
69 s_MinimalMimeEnsured
= TRUE
;
72 wxFileType
*ft
= wxTheMimeTypesManager
->GetFileTypeFromExtension(ext
);
73 if ( !ft
|| !ft
-> GetMimeType(&mime
) )
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");
98 wxString
wxFileSystemHandler::GetProtocol(const wxString
& location
) const
100 wxString s
= wxEmptyString
;
101 int i
, l
= location
.Length();
105 for (i
= l
-1; (i
>= 0) && ((location
[i
] != wxT('#')) || (!fnd
)); i
--) {
106 if ((location
[i
] == wxT(':')) && (i
!= 1 /*win: C:\path*/)) fnd
= TRUE
;
108 if (!fnd
) return wxT("file");
109 for (++i
; (i
< l
) && (location
[i
] != wxT(':')); i
++) s
<< location
[i
];
114 wxString
wxFileSystemHandler::GetLeftLocation(const wxString
& location
) const
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
);
124 return wxEmptyString
;
127 wxString
wxFileSystemHandler::GetRightLocation(const wxString
& location
) const
129 int i
, l
= location
.Length();
134 ((location
[i
] != wxT(':')) || (i
== 1) || (location
[i
-2] == wxT(':')));
137 if (location
[i
] == wxT('#')) l2
= i
+ 1;
139 if (i
== 0) return wxEmptyString
;
140 else return location
.Mid(i
+ 1, l2
- i
- 2);
143 wxString
wxFileSystemHandler::GetAnchor(const wxString
& location
) const
146 int l
= location
.Length();
148 for (int i
= l
-1; i
>= 0; i
--) {
150 if (c
== wxT('#')) return location
.Right(l
-i
-1);
151 else if ((c
== wxT('.')) || (c
== wxT('/')) || (c
== wxT('\\')) || (c
== wxT(':'))) return wxEmptyString
;
153 return wxEmptyString
;
157 wxString
wxFileSystemHandler::FindFirst(const wxString
& WXUNUSED(spec
),
160 return wxEmptyString
;
163 wxString
wxFileSystemHandler::FindNext()
165 return wxEmptyString
;
168 //--------------------------------------------------------------------------------
170 //--------------------------------------------------------------------------------
173 wxString
wxLocalFSHandler::ms_root
;
175 bool wxLocalFSHandler::CanOpen(const wxString
& location
)
177 return GetProtocol(location
) == wxT("file");
180 wxFSFile
* wxLocalFSHandler::OpenFile(wxFileSystem
& WXUNUSED(fs
), const wxString
& location
)
182 // location has Unix path separators
183 wxString right
= GetRightLocation(location
);
184 wxFileName fn
= wxFileSystem::URLToFileName(right
);
185 wxString fullpath
= ms_root
+ fn
.GetFullPath();
187 if (!wxFileExists(fullpath
))
188 return (wxFSFile
*) NULL
;
190 return new wxFSFile(new wxFFileInputStream(fullpath
),
192 GetMimeTypeFromExt(location
),
195 ,wxDateTime(wxFileModificationTime(fullpath
))
196 #endif // wxUSE_DATETIME
200 wxString
wxLocalFSHandler::FindFirst(const wxString
& spec
, int flags
)
202 wxFileName fn
= wxFileSystem::URLToFileName(GetRightLocation(spec
));
203 return wxFindFirstFile(ms_root
+ fn
.GetFullPath(), flags
);
206 wxString
wxLocalFSHandler::FindNext()
208 return wxFindNextFile();
213 //-----------------------------------------------------------------------------
215 //-----------------------------------------------------------------------------
217 IMPLEMENT_DYNAMIC_CLASS(wxFileSystem
, wxObject
)
218 IMPLEMENT_ABSTRACT_CLASS(wxFSFile
, wxObject
)
221 wxList
wxFileSystem::m_Handlers
;
224 static wxString
MakeCorrectPath(const wxString
& path
)
231 for (i
= 0; i
< cnt
; i
++)
232 if (p
.GetChar(i
) == wxT('\\')) p
.GetWritableChar(i
) = wxT('/'); // Want to be windows-safe
234 if (p
.Left(2) == wxT("./")) { p
= p
.Mid(2); cnt
-= 2; }
236 if (cnt
< 3) return p
;
238 r
<< p
.GetChar(0) << p
.GetChar(1);
240 // skip trailing ../.., if any
241 for (i
= 2; i
< cnt
&& (p
.GetChar(i
) == wxT('/') || p
.GetChar(i
) == wxT('.')); i
++) r
<< p
.GetChar(i
);
243 // remove back references: translate dir1/../dir2 to dir2
247 if (p
.GetChar(i
) == wxT('/') && p
.GetChar(i
-1) == wxT('.') && p
.GetChar(i
-2) == wxT('.'))
249 for (j
= r
.Length() - 2; j
>= 0 && r
.GetChar(j
) != wxT('/') && r
.GetChar(j
) != wxT(':'); j
--) {}
250 if (j
>= 0 && r
.GetChar(j
) != wxT(':'))
252 for (j
= j
- 1; j
>= 0 && r
.GetChar(j
) != wxT('/') && r
.GetChar(j
) != wxT(':'); j
--) {}
258 for (; i
< cnt
; i
++) r
<< p
.GetChar(i
);
264 void wxFileSystem::ChangePathTo(const wxString
& location
, bool is_dir
)
268 m_Path
= MakeCorrectPath(location
);
272 if (m_Path
.Length() > 0 && m_Path
.Last() != wxT('/') && m_Path
.Last() != wxT(':'))
278 for (i
= m_Path
.Length()-1; i
>= 0; i
--)
280 if (m_Path
[(unsigned int) i
] == wxT('/'))
282 if ((i
> 1) && (m_Path
[(unsigned int) (i
-1)] == wxT('/')) && (m_Path
[(unsigned int) (i
-2)] == wxT(':')))
293 else if (m_Path
[(unsigned int) i
] == wxT(':')) {
300 for (i
= 0; i
< (int) m_Path
.Length(); i
++)
302 if (m_Path
[(unsigned int) i
] == wxT(':'))
308 if (i
== (int) m_Path
.Length())
309 m_Path
= wxEmptyString
;
313 m_Path
.Remove(pathpos
+1);
320 wxFSFile
* wxFileSystem::OpenFile(const wxString
& location
)
322 wxString loc
= MakeCorrectPath(location
);
330 for (i
= 0; i
< ln
; i
++)
334 case wxT('/') : case wxT(':') : case wxT('#') :
338 if (meta
!= 0) break;
340 m_LastName
= wxEmptyString
;
342 // try relative paths first :
343 if (meta
!= wxT(':'))
345 node
= m_Handlers
.GetFirst();
348 wxFileSystemHandler
*h
= (wxFileSystemHandler
*) node
-> GetData();
349 if (h
->CanOpen(m_Path
+ loc
))
351 s
= h
->OpenFile(*this, m_Path
+ loc
);
352 if (s
) { m_LastName
= m_Path
+ loc
; break; }
354 node
= node
->GetNext();
358 // if failed, try absolute paths :
361 node
= m_Handlers
.GetFirst();
364 wxFileSystemHandler
*h
= (wxFileSystemHandler
*) node
->GetData();
367 s
= h
->OpenFile(*this, loc
);
368 if (s
) { m_LastName
= loc
; break; }
370 node
= node
->GetNext();
378 wxString
wxFileSystem::FindFirst(const wxString
& spec
, int flags
)
381 wxString
spec2(spec
);
383 m_FindFileHandler
= NULL
;
385 for (int i
= spec2
.Length()-1; i
>= 0; i
--)
386 if (spec2
[(unsigned int) i
] == wxT('\\')) spec2
.GetWritableChar(i
) = wxT('/'); // Want to be windows-safe
388 node
= m_Handlers
.GetFirst();
391 m_FindFileHandler
= (wxFileSystemHandler
*) node
-> GetData();
392 if (m_FindFileHandler
-> CanOpen(m_Path
+ spec2
))
393 return m_FindFileHandler
-> FindFirst(m_Path
+ spec2
, flags
);
394 node
= node
->GetNext();
397 node
= m_Handlers
.GetFirst();
400 m_FindFileHandler
= (wxFileSystemHandler
*) node
-> GetData();
401 if (m_FindFileHandler
-> CanOpen(spec2
))
402 return m_FindFileHandler
-> FindFirst(spec2
, flags
);
403 node
= node
->GetNext();
406 return wxEmptyString
;
411 wxString
wxFileSystem::FindNext()
413 if (m_FindFileHandler
== NULL
) return wxEmptyString
;
414 else return m_FindFileHandler
-> FindNext();
419 void wxFileSystem::AddHandler(wxFileSystemHandler
*handler
)
421 m_Handlers
.Append(handler
);
425 void wxFileSystem::CleanUpHandlers()
427 m_Handlers
.DeleteContents(TRUE
);
431 const static wxString
g_unixPathString(wxT("/"));
432 const static wxString
g_nativePathString(wxFILE_SEP_PATH
);
434 // Returns the native path for a file URL
435 wxFileName
wxFileSystem::URLToFileName(const wxString
& url
)
439 if ( path
.Find(wxT("file://")) == 0 )
443 else if ( path
.Find(wxT("file:")) == 0 )
447 // Remove preceding double slash on Mac Classic
448 #if defined(__WXMAC__) && !defined(__UNIX__)
449 else if ( path
.Find(wxT("//")) == 0 )
453 path
.Replace(wxT("%25"), wxT("%"));
454 path
.Replace(wxT("%3A"), wxT(":"));
457 // file urls either start with a forward slash (local harddisk),
458 // otherwise they have a servername/sharename notation,
459 // which only exists on msw and corresponds to a unc
460 if ( path
[0u] == wxT('/') && path
[1u] != wxT('/'))
464 else if ( (url
.Find(wxT("file://")) == 0) &&
465 (path
.Find(wxT('/')) != wxNOT_FOUND
) &&
466 (path
.Length() > 1) && (path
[1u] != wxT(':')) )
468 path
= wxT("//") + path
;
472 path
.Replace(g_unixPathString
, g_nativePathString
);
474 return wxFileName(path
, wxPATH_NATIVE
);
477 // Returns the file URL for a native path
478 wxString
wxFileSystem::FileNameToURL(const wxFileName
& filename
)
480 wxFileName fn
= filename
;
481 fn
.Normalize(wxPATH_NORM_DOTS
| wxPATH_NORM_TILDE
| wxPATH_NORM_ABSOLUTE
);
482 wxString url
= fn
.GetFullPath(wxPATH_NATIVE
);
485 // unc notation, wxMSW
486 if ( url
.Find(wxT("\\\\")) == 0 )
492 url
= wxT("/") + url
;
494 url
= wxT("/") + url
;
500 url
.Replace(g_nativePathString
, g_unixPathString
);
501 url
.Replace(wxT("%"), wxT("%25"));
502 url
.Replace(wxT(":"), wxT("%3A"));
503 url
= wxT("file:") + url
;
510 class wxFileSystemModule
: public wxModule
512 DECLARE_DYNAMIC_CLASS(wxFileSystemModule
)
515 virtual bool OnInit()
517 wxFileSystem::AddHandler(new wxLocalFSHandler
);
520 gs_FSMimeFallbacks
= new wxFileTypeInfo
[6];
521 gs_FSMimeFallbacks
[0] =
522 wxFileTypeInfo(_T("image/jpeg"),
525 _T("JPEG image (from fallback)"),
526 _T("jpg"), _T("jpeg"), NULL
);
527 gs_FSMimeFallbacks
[1] =
528 wxFileTypeInfo(_T("image/gif"),
531 _T("GIF image (from fallback)"),
533 gs_FSMimeFallbacks
[2] =
534 wxFileTypeInfo(_T("image/png"),
537 _T("PNG image (from fallback)"),
539 gs_FSMimeFallbacks
[3] =
540 wxFileTypeInfo(_T("image/bmp"),
543 _T("windows bitmap image (from fallback)"),
545 gs_FSMimeFallbacks
[4] =
546 wxFileTypeInfo(_T("text/html"),
549 _T("HTML document (from fallback)"),
550 _T("htm"), _T("html"), NULL
);
551 gs_FSMimeFallbacks
[5] =
552 // must terminate the table with this!
557 virtual void OnExit()
560 delete [] gs_FSMimeFallbacks
;
562 wxFileSystem::CleanUpHandlers();
566 IMPLEMENT_DYNAMIC_CLASS(wxFileSystemModule
, wxModule
)