]> git.saurik.com Git - wxWidgets.git/blob - src/common/filesys.cpp
made unzip.c accept / and \ in filenames as equal
[wxWidgets.git] / src / common / filesys.cpp
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$
7 // Licence: wxWindows Licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation
12 #endif
13
14 #include "wx/wxprec.h"
15
16 #ifdef __BORDLANDC__
17 #pragma hdrstop
18 #endif
19
20 #if !wxUSE_SOCKETS
21 #undef wxUSE_FS_INET
22 #define wxUSE_FS_INET 0
23 #endif
24
25 #if (wxUSE_HTML || wxUSE_FS_INET || wxUSE_FS_ZIP) && wxUSE_STREAMS
26
27 #include "wx/wfstream.h"
28 #include "wx/module.h"
29 #include "wx/filesys.h"
30 #include "wx/mimetype.h"
31
32
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 = wxEmptyString, mime = wxEmptyString;
45 wxString loc = GetRightLocation(location);
46 char c;
47 int l = loc.Length(), l2;
48 wxFileType *ft;
49
50 l2 = l;
51 for (int i = l-1; i >= 0; i--) {
52 c = loc[(unsigned int) i];
53 if (c == wxT('#')) l2 = i + 1;
54 if (c == wxT('.')) {ext = loc.Right(l2-i-1); break;}
55 if ((c == wxT('/')) || (c == wxT('\\')) || (c == wxT(':'))) {return wxEmptyString;}
56 }
57
58 static bool s_MinimalMimeEnsured = FALSE;
59 if (!s_MinimalMimeEnsured) {
60 static const wxFileTypeInfo fallbacks[] =
61 {
62 wxFileTypeInfo("image/jpeg",
63 "",
64 "",
65 "JPEG image (from fallback)",
66 "jpg", "jpeg", NULL),
67 wxFileTypeInfo("image/gif",
68 "",
69 "",
70 "GIF image (from fallback)",
71 "gif", NULL),
72 wxFileTypeInfo("image/png",
73 "",
74 "",
75 "PNG image (from fallback)",
76 "png", NULL),
77 wxFileTypeInfo("image/bmp",
78 "",
79 "",
80 "windows bitmap image (from fallback)",
81 "bmp", NULL),
82 wxFileTypeInfo("text/html",
83 "",
84 "",
85 "HTML document (from fallback)",
86 "htm", "html", NULL),
87
88 // must terminate the table with this!
89 wxFileTypeInfo()
90 };
91
92 wxTheMimeTypesManager -> AddFallbacks(fallbacks);
93 }
94
95 ft = wxTheMimeTypesManager -> GetFileTypeFromExtension(ext);
96 if (ft && (ft -> GetMimeType(&mime))) {
97 delete ft;
98 return mime;
99 }
100 else {
101 delete ft;
102 return wxEmptyString;
103 }
104 }
105
106
107
108 wxString wxFileSystemHandler::GetProtocol(const wxString& location) const
109 {
110 wxString s = wxEmptyString;
111 int i, l = location.Length();
112 bool fnd;
113
114 fnd = FALSE;
115 for (i = l-1; (i >= 0) && ((location[i] != wxT('#')) || (!fnd)); i--) {
116 if ((location[i] == wxT(':')) && (i != 1 /*win: C:\path*/)) fnd = TRUE;
117 }
118 if (!fnd) return wxT("file");
119 for (++i; (i < l) && (location[i] != wxT(':')); i++) s << location[i];
120 return s;
121 }
122
123
124 wxString wxFileSystemHandler::GetLeftLocation(const wxString& location) const
125 {
126 int i;
127 bool fnd;
128
129 fnd = FALSE;
130 for (i = location.Length()-1; i >= 0; i--) {
131 if ((location[i] == wxT(':')) && (i != 1 /*win: C:\path*/)) fnd = TRUE;
132 else if (fnd && (location[i] == wxT('#'))) return location.Left(i);
133 }
134 return wxEmptyString;
135 }
136
137 wxString wxFileSystemHandler::GetRightLocation(const wxString& location) const
138 {
139 int i, l = location.Length();
140 int l2 = l + 1;
141 for (i = l-1; (i >= 0) && ((location[i] != wxT(':')) || (i == 1) || (location[i-2] == wxT(':'))); i--) {if (location[i] == wxT('#')) l2 = i + 1;}
142 if (i == 0) return wxEmptyString;
143 else return location.Mid(i + 1, l2 - i - 2);
144 }
145
146 wxString wxFileSystemHandler::GetAnchor(const wxString& location) const
147 {
148 char c;
149 int l = location.Length();
150
151 for (int i = l-1; i >= 0; i--) {
152 c = location[i];
153 if (c == wxT('#')) return location.Right(l-i-1);
154 else if ((c == wxT('.')) || (c == wxT('/')) || (c == wxT('\\')) || (c == wxT(':'))) return wxEmptyString;
155 }
156 return wxEmptyString;
157 }
158
159
160 wxString wxFileSystemHandler::FindFirst(const wxString& WXUNUSED(spec),
161 int WXUNUSED(flags))
162 {
163 return wxEmptyString;
164 }
165
166 wxString wxFileSystemHandler::FindNext()
167 {
168 return wxEmptyString;
169 }
170
171 //--------------------------------------------------------------------------------
172 // wxLocalFSHandler
173 //--------------------------------------------------------------------------------
174
175 class wxLocalFSHandler : public wxFileSystemHandler
176 {
177 public:
178 virtual bool CanOpen(const wxString& location);
179 virtual wxFSFile* OpenFile(wxFileSystem& fs, const wxString& location);
180 virtual wxString FindFirst(const wxString& spec, int flags = 0);
181 virtual wxString FindNext();
182 };
183
184
185 bool wxLocalFSHandler::CanOpen(const wxString& location)
186 {
187 return GetProtocol(location) == wxT("file");
188 }
189
190 wxFSFile* wxLocalFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString& location)
191 {
192 wxString right = GetRightLocation(location);
193 if (wxFileExists(right))
194 return new wxFSFile(new wxFileInputStream(right),
195 right,
196 GetMimeTypeFromExt(location),
197 GetAnchor(location),
198 wxDateTime(wxFileModificationTime(right)));
199 else return (wxFSFile*) NULL;
200 }
201
202 wxString wxLocalFSHandler::FindFirst(const wxString& spec, int flags)
203 {
204 wxString right = GetRightLocation(spec);
205 return wxFindFirstFile(right, flags);
206 }
207
208 wxString wxLocalFSHandler::FindNext()
209 {
210 return wxFindNextFile();
211 }
212
213
214
215 //-----------------------------------------------------------------------------
216 // wxFileSystem
217 //-----------------------------------------------------------------------------
218
219 IMPLEMENT_DYNAMIC_CLASS(wxFileSystem, wxObject)
220
221
222 wxList wxFileSystem::m_Handlers;
223
224
225 static wxString MakeCorrectPath(const wxString& path)
226 {
227 wxString p(path);
228 wxString r;
229 int i, j, cnt;
230
231 cnt = p.Length();
232 for (i = 0; i < cnt; i++)
233 if (p[i] == wxT('\\')) p.GetWritableChar(i) = wxT('/'); // wanna be windows-safe
234
235 if (p.Left(2) == wxT("./")) { p = p.Mid(2); cnt -= 2; }
236
237 if (cnt < 3) return p;
238
239 r << p[0] << p[1];
240
241 // skip trailing ../.., if any
242 for (i = 2; i < cnt && (p[i] == wxT('/') || p[i] == wxT('.')); i++) r << p[i];
243
244 // remove back references: translate dir1/../dir2 to dir2
245 for (; i < cnt; i++)
246 {
247 r << p[i];
248 if (p[i] == wxT('/') && p[i-1] == wxT('.') && p[i-2] == wxT('.'))
249 {
250 for (j = r.Length() - 2; j >= 0 && r[j] != wxT('/') && r[j] != wxT(':'); j--) {}
251 if (j >= 0 && r[j] != wxT(':'))
252 {
253 for (j = j - 1; j >= 0 && r[j] != wxT('/') && r[j] != wxT(':'); j--) {}
254 r.Remove(j + 1);
255 }
256 }
257 }
258
259 for (; i < cnt; i++) r << p[i];
260
261 return r;
262 }
263
264
265 void wxFileSystem::ChangePathTo(const wxString& location, bool is_dir)
266 {
267 int i, pathpos = -1;
268
269 m_Path = MakeCorrectPath(location);
270
271 if (is_dir)
272 {
273 if (m_Path.Length() > 0 && m_Path.Last() != wxT('/') && m_Path.Last() != wxT(':'))
274 m_Path << wxT('/');
275 }
276
277 else
278 {
279 for (i = m_Path.Length()-1; i >= 0; i--)
280 {
281 if (m_Path[(unsigned int) i] == wxT('/'))
282 {
283 if ((i > 1) && (m_Path[(unsigned int) (i-1)] == wxT('/')) && (m_Path[(unsigned int) (i-2)] == wxT(':')))
284 {
285 i -= 2;
286 continue;
287 }
288 else
289 {
290 pathpos = i;
291 break;
292 }
293 }
294 else if (m_Path[(unsigned int) i] == wxT(':')) {
295 pathpos = i;
296 break;
297 }
298 }
299 if (pathpos == -1)
300 {
301 for (i = 0; i < (int) m_Path.Length(); i++)
302 {
303 if (m_Path[(unsigned int) i] == wxT(':'))
304 {
305 m_Path.Remove(i+1);
306 break;
307 }
308 }
309 if (i == (int) m_Path.Length())
310 m_Path = wxEmptyString;
311 }
312 else
313 {
314 m_Path.Remove(pathpos+1);
315 }
316 }
317 }
318
319
320
321 wxFSFile* wxFileSystem::OpenFile(const wxString& location)
322 {
323 wxString loc = MakeCorrectPath(location);
324 unsigned i, ln;
325 char meta;
326 wxFSFile *s = NULL;
327 wxNode *node;
328
329 ln = loc.Length();
330 meta = 0;
331 for (i = 0; i < ln; i++)
332 {
333 if (!meta)
334 switch (loc[i])
335 {
336 case wxT('/') : case wxT(':') : case wxT('#') : meta = loc[i];
337 }
338 }
339 m_LastName = wxEmptyString;
340
341 // try relative paths first :
342 if (meta != wxT(':'))
343 {
344 node = m_Handlers.GetFirst();
345 while (node)
346 {
347 wxFileSystemHandler *h = (wxFileSystemHandler*) node -> GetData();
348 if (h->CanOpen(m_Path + loc))
349 {
350 s = h->OpenFile(*this, m_Path + loc);
351 if (s) { m_LastName = m_Path + loc; break; }
352 }
353 node = node->GetNext();
354 }
355 }
356
357 // if failed, try absolute paths :
358 if (s == NULL)
359 {
360 node = m_Handlers.GetFirst();
361 while (node)
362 {
363 wxFileSystemHandler *h = (wxFileSystemHandler*) node->GetData();
364 if (h->CanOpen(loc))
365 {
366 s = h->OpenFile(*this, loc);
367 if (s) { m_LastName = loc; break; }
368 }
369 node = node->GetNext();
370 }
371 }
372 return (s);
373 }
374
375
376
377 wxString wxFileSystem::FindFirst(const wxString& spec, int flags)
378 {
379 wxNode *node;
380 wxString spec2(spec);
381
382 m_FindFileHandler = NULL;
383
384 for (int i = spec2.Length()-1; i >= 0; i--)
385 if (spec2[(unsigned int) i] == wxT('\\')) spec2.GetWritableChar(i) = wxT('/'); // wanna be windows-safe
386
387 node = m_Handlers.GetFirst();
388 while (node)
389 {
390 m_FindFileHandler = (wxFileSystemHandler*) node -> GetData();
391 if (m_FindFileHandler -> CanOpen(m_Path + spec2))
392 return m_FindFileHandler -> FindFirst(m_Path + spec2, flags);
393 node = node->GetNext();
394 }
395
396 node = m_Handlers.GetFirst();
397 while (node)
398 {
399 m_FindFileHandler = (wxFileSystemHandler*) node -> GetData();
400 if (m_FindFileHandler -> CanOpen(spec2))
401 return m_FindFileHandler -> FindFirst(spec2, flags);
402 node = node->GetNext();
403 }
404
405 return wxEmptyString;
406 }
407
408
409
410 wxString wxFileSystem::FindNext()
411 {
412 if (m_FindFileHandler == NULL) return wxEmptyString;
413 else return m_FindFileHandler -> FindNext();
414 }
415
416
417
418 void wxFileSystem::AddHandler(wxFileSystemHandler *handler)
419 {
420 m_Handlers.Append(handler);
421 }
422
423
424 void wxFileSystem::CleanUpHandlers()
425 {
426 m_Handlers.DeleteContents(TRUE);
427 m_Handlers.Clear();
428 }
429
430
431
432
433 ///// Module:
434
435 class wxFileSystemModule : public wxModule
436 {
437 DECLARE_DYNAMIC_CLASS(wxFileSystemModule)
438
439 public:
440 virtual bool OnInit()
441 {
442 wxFileSystem::AddHandler(new wxLocalFSHandler);
443 return TRUE;
444 }
445 virtual void OnExit()
446 {
447 wxFileSystem::CleanUpHandlers();
448 }
449 };
450
451 IMPLEMENT_DYNAMIC_CLASS(wxFileSystemModule, wxModule)
452
453 #endif
454 // (wxUSE_FS_INET || wxUSE_FS_ZIP) && wxUSE_STREAMS
455
456
457