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