/[pcsx2_0.9.7]/trunk/3rdparty/wxWidgets/src/common/filesys.cpp
ViewVC logotype

Contents of /trunk/3rdparty/wxWidgets/src/common/filesys.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (10 years, 2 months ago) by william
File size: 18878 byte(s)
committing r3113 initial commit again...
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/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 55271 2008-08-26 00:03:04Z VZ $
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #include "wx/wxprec.h"
11
12 #ifdef __BORLANDC__
13 #pragma hdrstop
14 #endif
15
16
17 #if wxUSE_FILESYSTEM
18
19 #include "wx/filesys.h"
20
21 #ifndef WX_PRECOMP
22 #include "wx/log.h"
23 #include "wx/module.h"
24 #endif
25
26 #include "wx/sysopt.h"
27 #include "wx/wfstream.h"
28 #include "wx/mimetype.h"
29 #include "wx/filename.h"
30 #include "wx/tokenzr.h"
31 #include "wx/uri.h"
32 #include "wx/private/fileback.h"
33
34
35 //--------------------------------------------------------------------------------
36 // wxFileSystemHandler
37 //--------------------------------------------------------------------------------
38
39 IMPLEMENT_ABSTRACT_CLASS(wxFileSystemHandler, wxObject)
40
41
42 wxString wxFileSystemHandler::GetMimeTypeFromExt(const wxString& location)
43 {
44 wxString ext, mime;
45 wxString loc = GetRightLocation(location);
46 wxChar c;
47 int l = loc.length(), l2;
48
49 l2 = l;
50 for (int i = l-1; i >= 0; i--)
51 {
52 c = loc[(unsigned int) i];
53 if ( c == wxT('#') )
54 l2 = i + 1;
55 if ( c == wxT('.') )
56 {
57 ext = loc.Right(l2-i-1);
58 break;
59 }
60 if ( (c == wxT('/')) || (c == wxT('\\')) || (c == wxT(':')) )
61 return wxEmptyString;
62 }
63
64 #if wxUSE_MIMETYPE
65 static bool s_MinimalMimeEnsured = false;
66
67 // Don't use mime types manager if the application doesn't need it and it would be
68 // cause an unacceptable delay, especially on startup.
69 bool useMimeTypesManager = true;
70 #if wxUSE_SYSTEM_OPTIONS
71 useMimeTypesManager = (wxSystemOptions::GetOptionInt(wxT("filesys.no-mimetypesmanager")) == 0);
72 #endif
73
74 if (useMimeTypesManager)
75 {
76 if (!s_MinimalMimeEnsured)
77 {
78 static const wxFileTypeInfo fallbacks[] =
79 {
80 wxFileTypeInfo(_T("image/jpeg"),
81 wxEmptyString,
82 wxEmptyString,
83 _T("JPEG image (from fallback)"),
84 _T("jpg"), _T("jpeg"), _T("JPG"), _T("JPEG"), NULL),
85 wxFileTypeInfo(_T("image/gif"),
86 wxEmptyString,
87 wxEmptyString,
88 _T("GIF image (from fallback)"),
89 _T("gif"), _T("GIF"), NULL),
90 wxFileTypeInfo(_T("image/png"),
91 wxEmptyString,
92 wxEmptyString,
93 _T("PNG image (from fallback)"),
94 _T("png"), _T("PNG"), NULL),
95 wxFileTypeInfo(_T("image/bmp"),
96 wxEmptyString,
97 wxEmptyString,
98 _T("windows bitmap image (from fallback)"),
99 _T("bmp"), _T("BMP"), NULL),
100 wxFileTypeInfo(_T("text/html"),
101 wxEmptyString,
102 wxEmptyString,
103 _T("HTML document (from fallback)"),
104 _T("htm"), _T("html"), _T("HTM"), _T("HTML"), NULL),
105 // must terminate the table with this!
106 wxFileTypeInfo()
107 };
108 wxTheMimeTypesManager->AddFallbacks(fallbacks);
109 s_MinimalMimeEnsured = true;
110 }
111
112 wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(ext);
113 if ( !ft || !ft -> GetMimeType(&mime) )
114 {
115 mime = wxEmptyString;
116 }
117
118 delete ft;
119
120 return mime;
121 }
122 else
123 #endif
124 {
125 if ( ext.IsSameAs(wxT("htm"), false) || ext.IsSameAs(_T("html"), false) )
126 return wxT("text/html");
127 if ( ext.IsSameAs(wxT("jpg"), false) || ext.IsSameAs(_T("jpeg"), false) )
128 return wxT("image/jpeg");
129 if ( ext.IsSameAs(wxT("gif"), false) )
130 return wxT("image/gif");
131 if ( ext.IsSameAs(wxT("png"), false) )
132 return wxT("image/png");
133 if ( ext.IsSameAs(wxT("bmp"), false) )
134 return wxT("image/bmp");
135 return wxEmptyString;
136 }
137 }
138
139
140
141 wxString wxFileSystemHandler::GetProtocol(const wxString& location) const
142 {
143 wxString s = wxEmptyString;
144 int i, l = location.length();
145 bool fnd = false;
146
147 for (i = l-1; (i >= 0) && ((location[i] != wxT('#')) || (!fnd)); i--) {
148 if ((location[i] == wxT(':')) && (i != 1 /*win: C:\path*/)) fnd = true;
149 }
150 if (!fnd) return wxT("file");
151 for (++i; (i < l) && (location[i] != wxT(':')); i++) s << location[i];
152 return s;
153 }
154
155
156 wxString wxFileSystemHandler::GetLeftLocation(const wxString& location) const
157 {
158 int i;
159 bool fnd = false;
160
161 for (i = location.length()-1; i >= 0; i--) {
162 if ((location[i] == wxT(':')) && (i != 1 /*win: C:\path*/)) fnd = true;
163 else if (fnd && (location[i] == wxT('#'))) return location.Left(i);
164 }
165 return wxEmptyString;
166 }
167
168 wxString wxFileSystemHandler::GetRightLocation(const wxString& location) const
169 {
170 int i, l = location.length();
171 int l2 = l + 1;
172
173 for (i = l-1;
174 (i >= 0) &&
175 ((location[i] != wxT(':')) || (i == 1) || (location[i-2] == wxT(':')));
176 i--)
177 {
178 if (location[i] == wxT('#')) l2 = i + 1;
179 }
180 if (i == 0) return wxEmptyString;
181 else return location.Mid(i + 1, l2 - i - 2);
182 }
183
184 wxString wxFileSystemHandler::GetAnchor(const wxString& location) const
185 {
186 wxChar c;
187 int l = location.length();
188
189 for (int i = l-1; i >= 0; i--) {
190 c = location[i];
191 if (c == wxT('#'))
192 return location.Right(l-i-1);
193 else if ((c == wxT('/')) || (c == wxT('\\')) || (c == wxT(':')))
194 return wxEmptyString;
195 }
196 return wxEmptyString;
197 }
198
199
200 wxString wxFileSystemHandler::FindFirst(const wxString& WXUNUSED(spec),
201 int WXUNUSED(flags))
202 {
203 return wxEmptyString;
204 }
205
206 wxString wxFileSystemHandler::FindNext()
207 {
208 return wxEmptyString;
209 }
210
211 //--------------------------------------------------------------------------------
212 // wxLocalFSHandler
213 //--------------------------------------------------------------------------------
214
215
216 wxString wxLocalFSHandler::ms_root;
217
218 bool wxLocalFSHandler::CanOpen(const wxString& location)
219 {
220 return GetProtocol(location) == wxT("file");
221 }
222
223 wxFSFile* wxLocalFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString& location)
224 {
225 // location has Unix path separators
226 wxString right = GetRightLocation(location);
227 wxFileName fn = wxFileSystem::URLToFileName(right);
228 wxString fullpath = ms_root + fn.GetFullPath();
229
230 if (!wxFileExists(fullpath))
231 return (wxFSFile*) NULL;
232
233 // we need to check whether we can really read from this file, otherwise
234 // wxFSFile is not going to work
235 #if wxUSE_FFILE
236 wxFFileInputStream *is = new wxFFileInputStream(fullpath);
237 #elif wxUSE_FILE
238 wxFileInputStream *is = new wxFileInputStream(fullpath);
239 #else
240 #error One of wxUSE_FILE or wxUSE_FFILE must be set to 1 for wxFSHandler to work
241 #endif
242 if ( !is->Ok() )
243 {
244 delete is;
245 return (wxFSFile*) NULL;
246 }
247
248 return new wxFSFile(is,
249 right,
250 GetMimeTypeFromExt(location),
251 GetAnchor(location)
252 #if wxUSE_DATETIME
253 ,wxDateTime(wxFileModificationTime(fullpath))
254 #endif // wxUSE_DATETIME
255 );
256 }
257
258 wxString wxLocalFSHandler::FindFirst(const wxString& spec, int flags)
259 {
260 wxFileName fn = wxFileSystem::URLToFileName(GetRightLocation(spec));
261 return wxFindFirstFile(ms_root + fn.GetFullPath(), flags);
262 }
263
264 wxString wxLocalFSHandler::FindNext()
265 {
266 return wxFindNextFile();
267 }
268
269
270
271 //-----------------------------------------------------------------------------
272 // wxFileSystem
273 //-----------------------------------------------------------------------------
274
275 IMPLEMENT_DYNAMIC_CLASS(wxFileSystem, wxObject)
276 IMPLEMENT_ABSTRACT_CLASS(wxFSFile, wxObject)
277
278
279 wxList wxFileSystem::m_Handlers;
280
281
282 wxFileSystem::~wxFileSystem()
283 {
284 WX_CLEAR_HASH_MAP(wxFSHandlerHash, m_LocalHandlers)
285 }
286
287
288 static wxString MakeCorrectPath(const wxString& path)
289 {
290 wxString p(path);
291 wxString r;
292 int i, j, cnt;
293
294 cnt = p.length();
295 for (i = 0; i < cnt; i++)
296 if (p.GetChar(i) == wxT('\\')) p.GetWritableChar(i) = wxT('/'); // Want to be windows-safe
297
298 if (p.Left(2) == wxT("./")) { p = p.Mid(2); cnt -= 2; }
299
300 if (cnt < 3) return p;
301
302 r << p.GetChar(0) << p.GetChar(1);
303
304 // skip trailing ../.., if any
305 for (i = 2; i < cnt && (p.GetChar(i) == wxT('/') || p.GetChar(i) == wxT('.')); i++) r << p.GetChar(i);
306
307 // remove back references: translate dir1/../dir2 to dir2
308 for (; i < cnt; i++)
309 {
310 r << p.GetChar(i);
311 if (p.GetChar(i) == wxT('/') && p.GetChar(i-1) == wxT('.') && p.GetChar(i-2) == wxT('.'))
312 {
313 for (j = r.length() - 2; j >= 0 && r.GetChar(j) != wxT('/') && r.GetChar(j) != wxT(':'); j--) {}
314 if (j >= 0 && r.GetChar(j) != wxT(':'))
315 {
316 for (j = j - 1; j >= 0 && r.GetChar(j) != wxT('/') && r.GetChar(j) != wxT(':'); j--) {}
317 r.Remove(j + 1);
318 }
319 }
320 }
321
322 for (; i < cnt; i++) r << p.GetChar(i);
323
324 return r;
325 }
326
327
328 void wxFileSystem::ChangePathTo(const wxString& location, bool is_dir)
329 {
330 int i, pathpos = -1;
331
332 m_Path = MakeCorrectPath(location);
333
334 if (is_dir)
335 {
336 if (m_Path.length() > 0 && m_Path.Last() != wxT('/') && m_Path.Last() != wxT(':'))
337 m_Path << wxT('/');
338 }
339
340 else
341 {
342 for (i = m_Path.length()-1; i >= 0; i--)
343 {
344 if (m_Path[(unsigned int) i] == wxT('/'))
345 {
346 if ((i > 1) && (m_Path[(unsigned int) (i-1)] == wxT('/')) && (m_Path[(unsigned int) (i-2)] == wxT(':')))
347 {
348 i -= 2;
349 continue;
350 }
351 else
352 {
353 pathpos = i;
354 break;
355 }
356 }
357 else if (m_Path[(unsigned int) i] == wxT(':')) {
358 pathpos = i;
359 break;
360 }
361 }
362 if (pathpos == -1)
363 {
364 for (i = 0; i < (int) m_Path.length(); i++)
365 {
366 if (m_Path[(unsigned int) i] == wxT(':'))
367 {
368 m_Path.Remove(i+1);
369 break;
370 }
371 }
372 if (i == (int) m_Path.length())
373 m_Path = wxEmptyString;
374 }
375 else
376 {
377 m_Path.Remove(pathpos+1);
378 }
379 }
380 }
381
382
383
384 wxFileSystemHandler *wxFileSystem::MakeLocal(wxFileSystemHandler *h)
385 {
386 wxClassInfo *classinfo = h->GetClassInfo();
387
388 if (classinfo->IsDynamic())
389 {
390 wxFileSystemHandler*& local = m_LocalHandlers[classinfo];
391 if (!local)
392 local = (wxFileSystemHandler*)classinfo->CreateObject();
393 return local;
394 }
395 else
396 {
397 return h;
398 }
399 }
400
401
402
403 wxFSFile* wxFileSystem::OpenFile(const wxString& location, int flags)
404 {
405 if ((flags & wxFS_READ) == 0)
406 return NULL;
407
408 wxString loc = MakeCorrectPath(location);
409 unsigned i, ln;
410 wxChar meta;
411 wxFSFile *s = NULL;
412 wxList::compatibility_iterator node;
413
414 ln = loc.length();
415 meta = 0;
416 for (i = 0; i < ln; i++)
417 {
418 switch (loc[i])
419 {
420 case wxT('/') : case wxT(':') : case wxT('#') :
421 meta = loc[i];
422 break;
423 }
424 if (meta != 0) break;
425 }
426 m_LastName = wxEmptyString;
427
428 // try relative paths first :
429 if (meta != wxT(':'))
430 {
431 node = m_Handlers.GetFirst();
432 while (node)
433 {
434 wxFileSystemHandler *h = (wxFileSystemHandler*) node -> GetData();
435 if (h->CanOpen(m_Path + loc))
436 {
437 s = MakeLocal(h)->OpenFile(*this, m_Path + loc);
438 if (s) { m_LastName = m_Path + loc; break; }
439 }
440 node = node->GetNext();
441 }
442 }
443
444 // if failed, try absolute paths :
445 if (s == NULL)
446 {
447 node = m_Handlers.GetFirst();
448 while (node)
449 {
450 wxFileSystemHandler *h = (wxFileSystemHandler*) node->GetData();
451 if (h->CanOpen(loc))
452 {
453 s = MakeLocal(h)->OpenFile(*this, loc);
454 if (s) { m_LastName = loc; break; }
455 }
456 node = node->GetNext();
457 }
458 }
459
460 if (s && (flags & wxFS_SEEKABLE) != 0 && !s->GetStream()->IsSeekable())
461 {
462 wxBackedInputStream *stream;
463 stream = new wxBackedInputStream(s->DetachStream());
464 stream->FindLength();
465 s->SetStream(stream);
466 }
467
468 return (s);
469 }
470
471
472
473 wxString wxFileSystem::FindFirst(const wxString& spec, int flags)
474 {
475 wxList::compatibility_iterator node;
476 wxString spec2(spec);
477
478 m_FindFileHandler = NULL;
479
480 for (int i = spec2.length()-1; i >= 0; i--)
481 if (spec2[(unsigned int) i] == wxT('\\')) spec2.GetWritableChar(i) = wxT('/'); // Want to be windows-safe
482
483 node = m_Handlers.GetFirst();
484 while (node)
485 {
486 wxFileSystemHandler *h = (wxFileSystemHandler*) node -> GetData();
487 if (h -> CanOpen(m_Path + spec2))
488 {
489 m_FindFileHandler = MakeLocal(h);
490 return m_FindFileHandler -> FindFirst(m_Path + spec2, flags);
491 }
492 node = node->GetNext();
493 }
494
495 node = m_Handlers.GetFirst();
496 while (node)
497 {
498 wxFileSystemHandler *h = (wxFileSystemHandler*) node -> GetData();
499 if (h -> CanOpen(spec2))
500 {
501 m_FindFileHandler = MakeLocal(h);
502 return m_FindFileHandler -> FindFirst(spec2, flags);
503 }
504 node = node->GetNext();
505 }
506
507 return wxEmptyString;
508 }
509
510
511
512 wxString wxFileSystem::FindNext()
513 {
514 if (m_FindFileHandler == NULL) return wxEmptyString;
515 else return m_FindFileHandler -> FindNext();
516 }
517
518 bool wxFileSystem::FindFileInPath(wxString *pStr,
519 const wxChar *path,
520 const wxChar *basename)
521 {
522 // we assume that it's not empty
523 wxCHECK_MSG( !wxIsEmpty(basename), false,
524 _T("empty file name in wxFileSystem::FindFileInPath"));
525
526 // skip path separator in the beginning of the file name if present
527 if ( wxIsPathSeparator(*basename) )
528 basename++;
529
530 wxStringTokenizer tokenizer(path, wxPATH_SEP);
531 while ( tokenizer.HasMoreTokens() )
532 {
533 wxString strFile = tokenizer.GetNextToken();
534 if ( !wxEndsWithPathSeparator(strFile) )
535 strFile += wxFILE_SEP_PATH;
536 strFile += basename;
537
538 wxFSFile *file = OpenFile(strFile);
539 if ( file )
540 {
541 delete file;
542 *pStr = strFile;
543 return true;
544 }
545 }
546
547 return false;
548 }
549
550 void wxFileSystem::AddHandler(wxFileSystemHandler *handler)
551 {
552 // prepend the handler to the beginning of the list because handlers added
553 // last should have the highest priority to allow overriding them
554 m_Handlers.Insert((size_t)0, handler);
555 }
556
557 wxFileSystemHandler* wxFileSystem::RemoveHandler(wxFileSystemHandler *handler)
558 {
559 // if handler has already been removed (or deleted)
560 // we return NULL. This is by design in case
561 // CleanUpHandlers() is called before RemoveHandler
562 // is called, as we cannot control the order
563 // which modules are unloaded
564 if (!m_Handlers.DeleteObject(handler))
565 return NULL;
566
567 return handler;
568 }
569
570
571 bool wxFileSystem::HasHandlerForPath(const wxString &location)
572 {
573 for ( wxList::compatibility_iterator node = m_Handlers.GetFirst();
574 node; node = node->GetNext() )
575 {
576 wxFileSystemHandler *h = (wxFileSystemHandler*) node->GetData();
577 if (h->CanOpen(location))
578 return true;
579 }
580
581 return false;
582 }
583
584 void wxFileSystem::CleanUpHandlers()
585 {
586 WX_CLEAR_LIST(wxList, m_Handlers);
587 }
588
589 static const wxString g_unixPathString(wxT("/"));
590 static const wxString g_nativePathString(wxFILE_SEP_PATH);
591
592 // Returns the native path for a file URL
593 wxFileName wxFileSystem::URLToFileName(const wxString& url)
594 {
595 wxString path = url;
596
597 if ( path.Find(wxT("file://")) == 0 )
598 {
599 path = path.Mid(7);
600 }
601 else if ( path.Find(wxT("file:")) == 0 )
602 {
603 path = path.Mid(5);
604 }
605 // Remove preceding double slash on Mac Classic
606 #if defined(__WXMAC__) && !defined(__UNIX__)
607 else if ( path.Find(wxT("//")) == 0 )
608 path = path.Mid(2);
609 #endif
610
611 path = wxURI::Unescape(path);
612
613 #ifdef __WXMSW__
614 // file urls either start with a forward slash (local harddisk),
615 // otherwise they have a servername/sharename notation,
616 // which only exists on msw and corresponds to a unc
617 if ( path[0u] == wxT('/') && path [1u] != wxT('/'))
618 {
619 path = path.Mid(1);
620 }
621 else if ( (url.Find(wxT("file://")) == 0) &&
622 (path.Find(wxT('/')) != wxNOT_FOUND) &&
623 (path.length() > 1) && (path[1u] != wxT(':')) )
624 {
625 path = wxT("//") + path;
626 }
627 #endif
628
629 path.Replace(g_unixPathString, g_nativePathString);
630
631 return wxFileName(path, wxPATH_NATIVE);
632 }
633
634 // Returns the file URL for a native path
635 wxString wxFileSystem::FileNameToURL(const wxFileName& filename)
636 {
637 wxFileName fn = filename;
638 fn.Normalize(wxPATH_NORM_DOTS | wxPATH_NORM_TILDE | wxPATH_NORM_ABSOLUTE);
639 wxString url = fn.GetFullPath(wxPATH_NATIVE);
640
641 #ifndef __UNIX__
642 // unc notation, wxMSW
643 if ( url.Find(wxT("\\\\")) == 0 )
644 {
645 url = wxT("//") + url.Mid(2);
646 }
647 else
648 {
649 url = wxT("/") + url;
650 #ifdef __WXMAC__
651 url = wxT("/") + url;
652 #endif
653
654 }
655 #endif
656
657 url.Replace(g_nativePathString, g_unixPathString);
658 url.Replace(wxT("%"), wxT("%25")); // '%'s must be replaced first!
659 url.Replace(wxT("#"), wxT("%23"));
660 url.Replace(wxT(":"), wxT("%3A"));
661 url = wxT("file:") + url;
662 return url;
663 }
664
665
666 ///// Module:
667
668 class wxFileSystemModule : public wxModule
669 {
670 DECLARE_DYNAMIC_CLASS(wxFileSystemModule)
671
672 public:
673 wxFileSystemModule() :
674 wxModule(),
675 m_handler(NULL)
676 {
677 }
678
679 virtual bool OnInit()
680 {
681 m_handler = new wxLocalFSHandler;
682 wxFileSystem::AddHandler(m_handler);
683 return true;
684 }
685 virtual void OnExit()
686 {
687 delete wxFileSystem::RemoveHandler(m_handler);
688
689 wxFileSystem::CleanUpHandlers();
690 }
691
692 private:
693 wxFileSystemHandler* m_handler;
694
695 };
696
697 IMPLEMENT_DYNAMIC_CLASS(wxFileSystemModule, wxModule)
698
699 #endif
700 // wxUSE_FILESYSTEM

  ViewVC Help
Powered by ViewVC 1.1.22