]>
git.saurik.com Git - wxWidgets.git/blob - src/common/fs_zip.cpp
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: ZIP file system
4 // Author: Vaclav Slavik
5 // Copyright: (c) 1999 Vaclav Slavik
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 #include "wx/wxprec.h"
16 #if wxUSE_FILESYSTEM && wxUSE_FS_ZIP && wxUSE_ZIPSTREAM && wxUSE_ZLIB
23 #include "wx/filesys.h"
24 #include "wx/wfstream.h"
25 #include "wx/zipstrm.h"
26 #include "wx/fs_zip.h"
29 //---------------------------------------------------------------------------
31 //---------------------------------------------------------------------------
32 // Helper class for wxZipFSHandler
34 class wxZipFSInputStream
: public wxZipInputStream
37 wxZipFSInputStream(wxFSFile
*file
)
38 : wxZipInputStream(*file
->GetStream())
41 #if WXWIN_COMPATIBILITY_2_6
42 m_allowSeeking
= true;
46 virtual ~wxZipFSInputStream() { delete m_file
; }
52 //----------------------------------------------------------------------------
54 //----------------------------------------------------------------------------
56 wxZipFSHandler::wxZipFSHandler() : wxFileSystemHandler()
59 m_ZipFile
= m_Pattern
= m_BaseDir
= wxEmptyString
;
60 m_AllowDirs
= m_AllowFiles
= true;
66 wxZipFSHandler::~wxZipFSHandler()
72 void wxZipFSHandler::Cleanup()
75 wxDELETE(m_DirsFound
);
80 bool wxZipFSHandler::CanOpen(const wxString
& location
)
82 wxString p
= GetProtocol(location
);
83 return (p
== wxT("zip"));
87 wxFSFile
* wxZipFSHandler::OpenFile(wxFileSystem
& WXUNUSED(fs
), const wxString
& location
)
89 wxString right
= GetRightLocation(location
);
90 wxString left
= GetLeftLocation(location
);
93 if (right
.Contains(wxT("./")))
95 if (right
.GetChar(0) != wxT('/')) right
= wxT('/') + right
;
96 wxFileName
rightPart(right
, wxPATH_UNIX
);
97 rightPart
.Normalize(wxPATH_NORM_DOTS
, wxT("/"), wxPATH_UNIX
);
98 right
= rightPart
.GetFullPath(wxPATH_UNIX
);
101 if (right
.GetChar(0) == wxT('/')) right
= right
.Mid(1);
103 // a new wxFileSystem object is needed here to avoid infinite recursion
104 wxFSFile
*leftFile
= wxFileSystem().OpenFile(left
);
108 s
= new wxZipFSInputStream(leftFile
);
113 #endif // wxUSE_DATETIME
118 wxZipEntry
*ent
= s
->GetNextEntry();
122 if (ent
->GetInternalName() == right
)
125 dtMod
= ent
->GetDateTime();
132 return new wxFSFile(s
,
133 left
+ wxT("#zip:") + right
,
134 GetMimeTypeFromExt(location
),
138 #endif // wxUSE_DATETIME
149 wxString
wxZipFSHandler::FindFirst(const wxString
& spec
, int flags
)
151 wxString right
= GetRightLocation(spec
);
152 wxString left
= GetLeftLocation(spec
);
154 if (!right
.empty() && right
.Last() == wxT('/')) right
.RemoveLast();
165 m_AllowDirs
= false, m_AllowFiles
= true; break;
167 m_AllowDirs
= true, m_AllowFiles
= false; break;
169 m_AllowDirs
= m_AllowFiles
= true; break;
174 wxFSFile
*leftFile
= wxFileSystem().OpenFile(left
);
176 m_Archive
= new wxZipFSInputStream(leftFile
);
178 m_Pattern
= right
.AfterLast(wxT('/'));
179 m_BaseDir
= right
.BeforeLast(wxT('/'));
180 if (m_BaseDir
.StartsWith(wxT("/")))
181 m_BaseDir
= m_BaseDir
.Mid(1);
188 m_DirsFound
= new wxZipFilenameHashMap();
189 if (right
.empty()) // allow "/" to match the archive root
194 return wxEmptyString
;
199 wxString
wxZipFSHandler::FindNext()
201 if (!m_Archive
) return wxEmptyString
;
207 wxString
wxZipFSHandler::DoFind()
209 wxString namestr
, dir
, filename
;
210 wxString match
= wxEmptyString
;
212 while (match
== wxEmptyString
)
214 wxZipEntry
*entry
= m_Archive
->GetNextEntry();
221 namestr
= entry
->GetName(wxPATH_UNIX
);
226 dir
= namestr
.BeforeLast(wxT('/'));
229 if( m_DirsFound
->find(dir
) == m_DirsFound
->end() )
231 (*m_DirsFound
)[dir
] = 1;
232 filename
= dir
.AfterLast(wxT('/'));
233 dir
= dir
.BeforeLast(wxT('/'));
234 if (!filename
.empty() && m_BaseDir
== dir
&&
235 wxMatchWild(m_Pattern
, filename
, false))
236 match
= m_ZipFile
+ wxT("#zip:") + dir
+ wxT("/") + filename
;
239 break; // already tranversed
243 filename
= namestr
.AfterLast(wxT('/'));
244 dir
= namestr
.BeforeLast(wxT('/'));
245 if (m_AllowFiles
&& !filename
.empty() && m_BaseDir
== dir
&&
246 wxMatchWild(m_Pattern
, filename
, false))
247 match
= m_ZipFile
+ wxT("#zip:") + namestr
;
256 //wxUSE_FILESYSTEM && wxUSE_FS_ZIP && wxUSE_ZIPSTREAM