]>
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"
31 //--------------------------------------------------------------------------------
32 // wxFileSystemHandler
33 //--------------------------------------------------------------------------------
35 IMPLEMENT_ABSTRACT_CLASS(wxFileSystemHandler
, wxObject
)
39 static wxFileTypeInfo
*gs_FSMimeFallbacks
= NULL
;
42 wxString
wxFileSystemHandler::GetMimeTypeFromExt(const wxString
& location
)
45 wxString loc
= GetRightLocation(location
);
47 int l
= loc
.Length(), l2
;
50 for (int i
= l
-1; i
>= 0; i
--)
52 c
= loc
[(unsigned int) i
];
57 ext
= loc
.Right(l2
-i
-1);
60 if ( (c
== wxT('/')) || (c
== wxT('\\')) || (c
== wxT(':')) )
65 static bool s_MinimalMimeEnsured
= FALSE
;
66 if (!s_MinimalMimeEnsured
) {
67 wxTheMimeTypesManager
->AddFallbacks(gs_FSMimeFallbacks
);
68 s_MinimalMimeEnsured
= TRUE
;
71 wxFileType
*ft
= wxTheMimeTypesManager
->GetFileTypeFromExtension(ext
);
72 if ( !ft
|| !ft
-> GetMimeType(&mime
) )
81 if ( ext
.IsSameAs(wxT("htm"), FALSE
) || ext
.IsSameAs(_T("html"), FALSE
) )
82 return wxT("text/html");
83 if ( ext
.IsSameAs(wxT("jpg"), FALSE
) || ext
.IsSameAs(_T("jpeg"), FALSE
) )
84 return wxT("image/jpeg");
85 if ( ext
.IsSameAs(wxT("gif"), FALSE
) )
86 return wxT("image/gif");
87 if ( ext
.IsSameAs(wxT("png"), FALSE
) )
88 return wxT("image/png");
89 if ( ext
.IsSameAs(wxT("bmp"), FALSE
) )
90 return wxT("image/bmp");
97 wxString
wxFileSystemHandler::GetProtocol(const wxString
& location
) const
99 wxString s
= wxEmptyString
;
100 int i
, l
= location
.Length();
104 for (i
= l
-1; (i
>= 0) && ((location
[i
] != wxT('#')) || (!fnd
)); i
--) {
105 if ((location
[i
] == wxT(':')) && (i
!= 1 /*win: C:\path*/)) fnd
= TRUE
;
107 if (!fnd
) return wxT("file");
108 for (++i
; (i
< l
) && (location
[i
] != wxT(':')); i
++) s
<< location
[i
];
113 wxString
wxFileSystemHandler::GetLeftLocation(const wxString
& location
) const
119 for (i
= location
.Length()-1; i
>= 0; i
--) {
120 if ((location
[i
] == wxT(':')) && (i
!= 1 /*win: C:\path*/)) fnd
= TRUE
;
121 else if (fnd
&& (location
[i
] == wxT('#'))) return location
.Left(i
);
123 return wxEmptyString
;
126 wxString
wxFileSystemHandler::GetRightLocation(const wxString
& location
) const
128 int i
, l
= location
.Length();
130 for (i
= l
-1; (i
>= 0) && ((location
[i
] != wxT(':')) || (i
== 1) || (location
[i
-2] == wxT(':'))); i
--) {if (location
[i
] == wxT('#')) l2
= i
+ 1;}
131 if (i
== 0) return wxEmptyString
;
132 else return location
.Mid(i
+ 1, l2
- i
- 2);
135 wxString
wxFileSystemHandler::GetAnchor(const wxString
& location
) const
138 int l
= location
.Length();
140 for (int i
= l
-1; i
>= 0; i
--) {
142 if (c
== wxT('#')) return location
.Right(l
-i
-1);
143 else if ((c
== wxT('.')) || (c
== wxT('/')) || (c
== wxT('\\')) || (c
== wxT(':'))) return wxEmptyString
;
145 return wxEmptyString
;
149 wxString
wxFileSystemHandler::FindFirst(const wxString
& WXUNUSED(spec
),
152 return wxEmptyString
;
155 wxString
wxFileSystemHandler::FindNext()
157 return wxEmptyString
;
160 //--------------------------------------------------------------------------------
162 //--------------------------------------------------------------------------------
165 wxString
wxLocalFSHandler::ms_root
;
167 bool wxLocalFSHandler::CanOpen(const wxString
& location
)
169 return GetProtocol(location
) == wxT("file");
172 wxFSFile
* wxLocalFSHandler::OpenFile(wxFileSystem
& WXUNUSED(fs
), const wxString
& location
)
174 // location has Unix path separators
175 wxString right
= ms_root
+ GetRightLocation(location
);
176 wxString nativePath
= wxFileSystem::URLToNativePath(right
);
177 wxFileName
fn(nativePath
, wxPATH_UNIX
);
179 if (!wxFileExists(fn
.GetFullPath()))
180 return (wxFSFile
*) NULL
;
182 return new wxFSFile(new wxFFileInputStream(fn
.GetFullPath()),
184 GetMimeTypeFromExt(location
),
186 wxDateTime(wxFileModificationTime(fn
.GetFullPath())));
190 wxString
wxLocalFSHandler::FindFirst(const wxString
& spec
, int flags
)
192 wxString right
= ms_root
+ GetRightLocation(spec
);
193 return wxFindFirstFile(right
, flags
);
196 wxString
wxLocalFSHandler::FindNext()
198 return wxFindNextFile();
203 //-----------------------------------------------------------------------------
205 //-----------------------------------------------------------------------------
207 IMPLEMENT_DYNAMIC_CLASS(wxFileSystem
, wxObject
)
208 IMPLEMENT_ABSTRACT_CLASS(wxFSFile
, wxObject
)
211 wxList
wxFileSystem::m_Handlers
;
214 static wxString
MakeCorrectPath(const wxString
& path
)
221 for (i
= 0; i
< cnt
; i
++)
222 if (p
.GetChar(i
) == wxT('\\')) p
.GetWritableChar(i
) = wxT('/'); // Want to be windows-safe
224 if (p
.Left(2) == wxT("./")) { p
= p
.Mid(2); cnt
-= 2; }
226 if (cnt
< 3) return p
;
228 r
<< p
.GetChar(0) << p
.GetChar(1);
230 // skip trailing ../.., if any
231 for (i
= 2; i
< cnt
&& (p
.GetChar(i
) == wxT('/') || p
.GetChar(i
) == wxT('.')); i
++) r
<< p
.GetChar(i
);
233 // remove back references: translate dir1/../dir2 to dir2
237 if (p
.GetChar(i
) == wxT('/') && p
.GetChar(i
-1) == wxT('.') && p
.GetChar(i
-2) == wxT('.'))
239 for (j
= r
.Length() - 2; j
>= 0 && r
.GetChar(j
) != wxT('/') && r
.GetChar(j
) != wxT(':'); j
--) {}
240 if (j
>= 0 && r
.GetChar(j
) != wxT(':'))
242 for (j
= j
- 1; j
>= 0 && r
.GetChar(j
) != wxT('/') && r
.GetChar(j
) != wxT(':'); j
--) {}
248 for (; i
< cnt
; i
++) r
<< p
.GetChar(i
);
254 void wxFileSystem::ChangePathTo(const wxString
& location
, bool is_dir
)
258 m_Path
= MakeCorrectPath(location
);
262 if (m_Path
.Length() > 0 && m_Path
.Last() != wxT('/') && m_Path
.Last() != wxT(':'))
268 for (i
= m_Path
.Length()-1; i
>= 0; i
--)
270 if (m_Path
[(unsigned int) i
] == wxT('/'))
272 if ((i
> 1) && (m_Path
[(unsigned int) (i
-1)] == wxT('/')) && (m_Path
[(unsigned int) (i
-2)] == wxT(':')))
283 else if (m_Path
[(unsigned int) i
] == wxT(':')) {
290 for (i
= 0; i
< (int) m_Path
.Length(); i
++)
292 if (m_Path
[(unsigned int) i
] == wxT(':'))
298 if (i
== (int) m_Path
.Length())
299 m_Path
= wxEmptyString
;
303 m_Path
.Remove(pathpos
+1);
310 wxFSFile
* wxFileSystem::OpenFile(const wxString
& location
)
312 wxString loc
= MakeCorrectPath(location
);
320 for (i
= 0; i
< ln
; i
++)
324 case wxT('/') : case wxT(':') : case wxT('#') :
328 if (meta
!= 0) break;
330 m_LastName
= wxEmptyString
;
332 // try relative paths first :
333 if (meta
!= wxT(':'))
335 node
= m_Handlers
.GetFirst();
338 wxFileSystemHandler
*h
= (wxFileSystemHandler
*) node
-> GetData();
339 if (h
->CanOpen(m_Path
+ loc
))
341 s
= h
->OpenFile(*this, m_Path
+ loc
);
342 if (s
) { m_LastName
= m_Path
+ loc
; break; }
344 node
= node
->GetNext();
348 // if failed, try absolute paths :
351 node
= m_Handlers
.GetFirst();
354 wxFileSystemHandler
*h
= (wxFileSystemHandler
*) node
->GetData();
357 s
= h
->OpenFile(*this, loc
);
358 if (s
) { m_LastName
= loc
; break; }
360 node
= node
->GetNext();
368 wxString
wxFileSystem::FindFirst(const wxString
& spec
, int flags
)
371 wxString
spec2(spec
);
373 m_FindFileHandler
= NULL
;
375 for (int i
= spec2
.Length()-1; i
>= 0; i
--)
376 if (spec2
[(unsigned int) i
] == wxT('\\')) spec2
.GetWritableChar(i
) = wxT('/'); // Want to be windows-safe
378 node
= m_Handlers
.GetFirst();
381 m_FindFileHandler
= (wxFileSystemHandler
*) node
-> GetData();
382 if (m_FindFileHandler
-> CanOpen(m_Path
+ spec2
))
383 return m_FindFileHandler
-> FindFirst(m_Path
+ spec2
, flags
);
384 node
= node
->GetNext();
387 node
= m_Handlers
.GetFirst();
390 m_FindFileHandler
= (wxFileSystemHandler
*) node
-> GetData();
391 if (m_FindFileHandler
-> CanOpen(spec2
))
392 return m_FindFileHandler
-> FindFirst(spec2
, flags
);
393 node
= node
->GetNext();
396 return wxEmptyString
;
401 wxString
wxFileSystem::FindNext()
403 if (m_FindFileHandler
== NULL
) return wxEmptyString
;
404 else return m_FindFileHandler
-> FindNext();
409 void wxFileSystem::AddHandler(wxFileSystemHandler
*handler
)
411 m_Handlers
.Append(handler
);
415 void wxFileSystem::CleanUpHandlers()
417 m_Handlers
.DeleteContents(TRUE
);
421 const static wxString
g_unixPathString(wxT("/"));
422 const static wxString
g_nativePathString(wxFILE_SEP_PATH
);
424 // Returns the native path for a file URL
425 wxString
wxFileSystem::URLToNativePath( const wxString
& url
)
427 wxString path
= url
;
429 if ( path
.Find(wxT("file://")) == 0 )
435 // file urls either start with a forward slash (local harddisk),
436 // otherwise they have a servername/sharename notation,
437 // which only exists on msw and corresponds to a unc
438 if ( path[0u] == wxT('/') && path [1u] != wxT('/'))
443 else if ( (url.Find(wxT("file://")) == 0) &&
444 (path.Find(wxT('/')) != wxNOT_FOUND) &&
445 (path.Length() > 1) && (path[1u] != wxT(':')) )
447 path = wxT("\\\\") + path ;
452 path
.Replace(g_unixPathString
, g_nativePathString
) ;
457 // Returns the file URL for a native path
458 wxString
wxFileSystem::NativePathToURL( const wxString
& path
)
460 wxString url
= path
;
465 if ( url.Find(wxT("\\\\")) == 0 )
472 url = wxT("/") + url ;
476 url
.Replace(g_nativePathString
, g_unixPathString
) ;
477 url
= wxT("file://") + url
;
484 class wxFileSystemModule
: public wxModule
486 DECLARE_DYNAMIC_CLASS(wxFileSystemModule
)
489 virtual bool OnInit()
491 wxFileSystem::AddHandler(new wxLocalFSHandler
);
494 gs_FSMimeFallbacks
= new wxFileTypeInfo
[6];
495 gs_FSMimeFallbacks
[0] =
496 wxFileTypeInfo(_T("image/jpeg"),
499 _T("JPEG image (from fallback)"),
500 _T("jpg"), _T("jpeg"), NULL
);
501 gs_FSMimeFallbacks
[1] =
502 wxFileTypeInfo(_T("image/gif"),
505 _T("GIF image (from fallback)"),
507 gs_FSMimeFallbacks
[2] =
508 wxFileTypeInfo(_T("image/png"),
511 _T("PNG image (from fallback)"),
513 gs_FSMimeFallbacks
[3] =
514 wxFileTypeInfo(_T("image/bmp"),
517 _T("windows bitmap image (from fallback)"),
519 gs_FSMimeFallbacks
[4] =
520 wxFileTypeInfo(_T("text/html"),
523 _T("HTML document (from fallback)"),
524 _T("htm"), _T("html"), NULL
);
525 gs_FSMimeFallbacks
[5] =
526 // must terminate the table with this!
531 virtual void OnExit()
534 delete [] gs_FSMimeFallbacks
;
536 wxFileSystem::CleanUpHandlers();
540 IMPLEMENT_DYNAMIC_CLASS(wxFileSystemModule
, wxModule
)