]>
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 /////////////////////////////////////////////////////////////////////////////
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "fs_zip.h"
16 #include "wx/wxprec.h"
22 #if wxUSE_FILESYSTEM && wxUSE_FS_ZIP && wxUSE_ZIPSTREAM && wxUSE_ZLIB
29 #include "wx/filesys.h"
30 #include "wx/wfstream.h"
31 #include "wx/zipstrm.h"
32 #include "wx/fs_zip.h"
35 //----------------------------------------------------------------------------
37 //----------------------------------------------------------------------------
41 wxZipFSHandler::wxZipFSHandler() : wxFileSystemHandler()
44 m_ZipFile
= m_Pattern
= m_BaseDir
= wxEmptyString
;
45 m_AllowDirs
= m_AllowFiles
= true;
51 wxZipFSHandler::~wxZipFSHandler()
54 CloseArchive(m_Archive
);
61 void wxZipFSHandler::CloseArchive(wxZipInputStream
*archive
)
63 wxInputStream
*stream
= archive
->GetFilterInputStream();
70 bool wxZipFSHandler::CanOpen(const wxString
& location
)
72 wxString p
= GetProtocol(location
);
73 return (p
== wxT("zip")) &&
74 (GetProtocol(GetLeftLocation(location
)) == wxT("file"));
80 wxFSFile
* wxZipFSHandler::OpenFile(wxFileSystem
& WXUNUSED(fs
), const wxString
& location
)
82 wxString right
= GetRightLocation(location
);
83 wxString left
= GetLeftLocation(location
);
86 if (GetProtocol(left
) != wxT("file"))
88 wxLogError(_("ZIP handler currently supports only local files!"));
92 if (right
.Contains(wxT("./")))
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
);
100 if (right
.GetChar(0) == wxT('/')) right
= right
.Mid(1);
102 wxFileName leftFilename
= wxFileSystem::URLToFileName(left
);
104 s
= new wxZipInputStream(leftFilename
.GetFullPath(), right
);
107 return new wxFSFile(s
,
108 left
+ wxT("#zip:") + right
,
109 GetMimeTypeFromExt(location
),
112 , wxDateTime(wxFileModificationTime(left
))
113 #endif // wxUSE_DATETIME
123 wxString
wxZipFSHandler::FindFirst(const wxString
& spec
, int flags
)
125 wxString right
= GetRightLocation(spec
);
126 wxString left
= GetLeftLocation(spec
);
128 if (right
.Last() == wxT('/')) right
.RemoveLast();
132 CloseArchive(m_Archive
);
136 if (GetProtocol(left
) != wxT("file"))
138 wxLogError(_("ZIP handler currently supports only local files!"));
139 return wxEmptyString
;
145 m_AllowDirs
= false, m_AllowFiles
= true; break;
147 m_AllowDirs
= true, m_AllowFiles
= false; break;
149 m_AllowDirs
= m_AllowFiles
= true; break;
153 wxString nativename
= wxFileSystem::URLToFileName(m_ZipFile
).GetFullPath();
155 wxFFileInputStream
*fs
= new wxFFileInputStream(nativename
);
157 m_Archive
= new wxZipInputStream(*fs
);
161 m_Pattern
= right
.AfterLast(wxT('/'));
162 m_BaseDir
= right
.BeforeLast(wxT('/'));
169 m_DirsFound
= new wxLongToLongHashMap();
173 return wxEmptyString
;
178 wxString
wxZipFSHandler::FindNext()
180 if (!m_Archive
) return wxEmptyString
;
186 wxString
wxZipFSHandler::DoFind()
188 wxString namestr
, dir
, filename
;
189 wxString match
= wxEmptyString
;
191 while (match
== wxEmptyString
)
193 wxZipEntry
*entry
= m_Archive
->GetNextEntry();
196 CloseArchive(m_Archive
);
200 namestr
= entry
->GetName(wxPATH_UNIX
);
205 dir
= namestr
.BeforeLast(wxT('/'));
206 while (!dir
.IsEmpty())
209 for (size_t i
= 0; i
< dir
.Length(); i
++) key
+= (wxUChar
)dir
[i
];
210 wxLongToLongHashMap::iterator it
= m_DirsFound
->find(key
);
211 if (it
== m_DirsFound
->end())
213 (*m_DirsFound
)[key
] = 1;
214 filename
= dir
.AfterLast(wxT('/'));
215 dir
= dir
.BeforeLast(wxT('/'));
216 if (!filename
.IsEmpty() && m_BaseDir
== dir
&&
217 wxMatchWild(m_Pattern
, filename
, false))
218 match
= m_ZipFile
+ wxT("#zip:") + dir
+ wxT("/") + filename
;
221 break; // already tranversed
225 filename
= namestr
.AfterLast(wxT('/'));
226 dir
= namestr
.BeforeLast(wxT('/'));
227 if (m_AllowFiles
&& !filename
.IsEmpty() && m_BaseDir
== dir
&&
228 wxMatchWild(m_Pattern
, filename
, false))
229 match
= m_ZipFile
+ wxT("#zip:") + namestr
;
238 //wxUSE_FILESYSTEM && wxUSE_FS_ZIP && wxUSE_ZIPSTREAM