]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/fs_zip.cpp
more wxPostEvent MT fixes
[wxWidgets.git] / src / common / fs_zip.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: fs_zip.cpp
3// Purpose: ZIP file system
4// Author: Vaclav Slavik
5// Copyright: (c) 1999 Vaclav Slavik
6// CVS-ID: $Id$
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
10
11
12#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13#pragma implementation "fs_zip.h"
14#endif
15
16#include "wx/wxprec.h"
17
18#ifdef __BORLANDC__
19#pragma hdrstop
20#endif
21
22#if wxUSE_FILESYSTEM && wxUSE_FS_ZIP && wxUSE_ZIPSTREAM && wxUSE_ZLIB
23
24#ifndef WXPRECOMP
25 #include "wx/intl.h"
26 #include "wx/log.h"
27#endif
28
29#include "wx/filesys.h"
30#include "wx/wfstream.h"
31#include "wx/zipstrm.h"
32#include "wx/fs_zip.h"
33
34
35//----------------------------------------------------------------------------
36// wxZipFSHandler
37//----------------------------------------------------------------------------
38
39
40
41wxZipFSHandler::wxZipFSHandler() : wxFileSystemHandler()
42{
43 m_Archive = NULL;
44 m_ZipFile = m_Pattern = m_BaseDir = wxEmptyString;
45 m_AllowDirs = m_AllowFiles = true;
46 m_DirsFound = NULL;
47}
48
49
50
51wxZipFSHandler::~wxZipFSHandler()
52{
53 if (m_Archive)
54 CloseArchive(m_Archive);
55 if (m_DirsFound)
56 delete m_DirsFound;
57}
58
59
60
61void wxZipFSHandler::CloseArchive(wxZipInputStream *archive)
62{
63 wxInputStream *stream = archive->GetFilterInputStream();
64 delete archive;
65 delete stream;
66}
67
68
69
70bool wxZipFSHandler::CanOpen(const wxString& location)
71{
72 wxString p = GetProtocol(location);
73 return (p == wxT("zip")) &&
74 (GetProtocol(GetLeftLocation(location)) == wxT("file"));
75}
76
77
78
79
80wxFSFile* wxZipFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString& location)
81{
82 wxString right = GetRightLocation(location);
83 wxString left = GetLeftLocation(location);
84 wxInputStream *s;
85
86 if (GetProtocol(left) != wxT("file"))
87 {
88 wxLogError(_("ZIP handler currently supports only local files!"));
89 return NULL;
90 }
91
92 if (right.Contains(wxT("./")))
93 {
94 if (right.GetChar(0) != wxT('/')) right = wxT('/') + right;
95 wxFileName rightPart(right, wxPATH_UNIX);
96 rightPart.Normalize(wxPATH_NORM_DOTS, wxT("/"), wxPATH_UNIX);
97 right = rightPart.GetFullPath(wxPATH_UNIX);
98 }
99
100 if (right.GetChar(0) == wxT('/')) right = right.Mid(1);
101
102 wxFileName leftFilename = wxFileSystem::URLToFileName(left);
103
104 s = new wxZipInputStream(leftFilename.GetFullPath(), right);
105 if (s && s->IsOk() )
106 {
107 return new wxFSFile(s,
108 left + wxT("#zip:") + right,
109 GetMimeTypeFromExt(location),
110 GetAnchor(location)
111#if wxUSE_DATETIME
112 , wxDateTime(wxFileModificationTime(left))
113#endif // wxUSE_DATETIME
114 );
115 }
116
117 delete s;
118 return NULL;
119}
120
121
122
123wxString wxZipFSHandler::FindFirst(const wxString& spec, int flags)
124{
125 wxString right = GetRightLocation(spec);
126 wxString left = GetLeftLocation(spec);
127
128 if (right.Last() == wxT('/')) right.RemoveLast();
129
130 if (m_Archive)
131 {
132 CloseArchive(m_Archive);
133 m_Archive = NULL;
134 }
135
136 if (GetProtocol(left) != wxT("file"))
137 {
138 wxLogError(_("ZIP handler currently supports only local files!"));
139 return wxEmptyString;
140 }
141
142 switch (flags)
143 {
144 case wxFILE:
145 m_AllowDirs = false, m_AllowFiles = true; break;
146 case wxDIR:
147 m_AllowDirs = true, m_AllowFiles = false; break;
148 default:
149 m_AllowDirs = m_AllowFiles = true; break;
150 }
151
152 m_ZipFile = left;
153 wxString nativename = wxFileSystem::URLToFileName(m_ZipFile).GetFullPath();
154 m_Archive = new wxZipInputStream(*new wxFFileInputStream(nativename));
155 m_Pattern = right.AfterLast(wxT('/'));
156 m_BaseDir = right.BeforeLast(wxT('/'));
157
158 if (m_Archive)
159 {
160 if (m_AllowDirs)
161 {
162 delete m_DirsFound;
163 m_DirsFound = new wxLongToLongHashMap();
164 }
165 return DoFind();
166 }
167 return wxEmptyString;
168}
169
170
171
172wxString wxZipFSHandler::FindNext()
173{
174 if (!m_Archive) return wxEmptyString;
175 return DoFind();
176}
177
178
179
180wxString wxZipFSHandler::DoFind()
181{
182 wxString namestr, dir, filename;
183 wxString match = wxEmptyString;
184
185 while (match == wxEmptyString)
186 {
187 wxZipEntry *entry = m_Archive->GetNextEntry();
188 if (!entry)
189 {
190 CloseArchive(m_Archive);
191 m_Archive = NULL;
192 break;
193 }
194 namestr = entry->GetName(wxPATH_UNIX);
195 delete entry;
196
197 if (m_AllowDirs)
198 {
199 dir = namestr.BeforeLast(wxT('/'));
200 while (!dir.IsEmpty())
201 {
202 long key = 0;
203 for (size_t i = 0; i < dir.Length(); i++) key += (wxUChar)dir[i];
204 wxLongToLongHashMap::iterator it = m_DirsFound->find(key);
205 if (it == m_DirsFound->end())
206 {
207 (*m_DirsFound)[key] = 1;
208 filename = dir.AfterLast(wxT('/'));
209 dir = dir.BeforeLast(wxT('/'));
210 if (!filename.IsEmpty() && m_BaseDir == dir &&
211 wxMatchWild(m_Pattern, filename, false))
212 match = m_ZipFile + wxT("#zip:") + dir + wxT("/") + filename;
213 }
214 else
215 break; // already tranversed
216 }
217 }
218
219 filename = namestr.AfterLast(wxT('/'));
220 dir = namestr.BeforeLast(wxT('/'));
221 if (m_AllowFiles && !filename.IsEmpty() && m_BaseDir == dir &&
222 wxMatchWild(m_Pattern, filename, false))
223 match = m_ZipFile + wxT("#zip:") + namestr;
224 }
225
226 return match;
227}
228
229
230
231#endif
232 //wxUSE_FILESYSTEM && wxUSE_FS_ZIP && wxUSE_ZIPSTREAM