]>
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
29 #include "wx/filesys.h"
30 #include "wx/zipstrm.h"
31 #include "wx/fs_zip.h"
33 /* Not the right solution (paths in makefiles) but... */
35 #include "../common/unzip.h"
40 //----------------------------------------------------------------------------
42 //----------------------------------------------------------------------------
46 wxZipFSHandler::wxZipFSHandler() : wxFileSystemHandler()
49 m_ZipFile
= m_Pattern
= m_BaseDir
= wxEmptyString
;
50 m_AllowDirs
= m_AllowFiles
= TRUE
;
56 wxZipFSHandler::~wxZipFSHandler()
59 unzClose((unzFile
)m_Archive
);
66 bool wxZipFSHandler::CanOpen(const wxString
& location
)
68 wxString p
= GetProtocol(location
);
69 return (p
== wxT("zip")) &&
70 (GetProtocol(GetLeftLocation(location
)) == wxT("file"));
76 wxFSFile
* wxZipFSHandler::OpenFile(wxFileSystem
& WXUNUSED(fs
), const wxString
& location
)
78 wxString right
= GetRightLocation(location
);
79 wxString left
= GetLeftLocation(location
);
82 if (GetProtocol(left
) != wxT("file"))
84 wxLogError(_("ZIP handler currently supports only local files!"));
88 if (right
.Contains(wxT("./")))
90 if (right
.GetChar(0) != wxT('/')) right
= wxT('/') + right
;
91 wxFileName
rightPart(right
, wxPATH_UNIX
);
92 rightPart
.Normalize(wxPATH_NORM_DOTS
, wxT("/"), wxPATH_UNIX
);
93 right
= rightPart
.GetFullPath(wxPATH_UNIX
);
96 if (right
.GetChar(0) == wxT('/')) right
= right
.Mid(1);
98 wxFileName leftFilename
= wxFileSystem::URLToFileName(left
);
100 s
= new wxZipInputStream(leftFilename
.GetFullPath(), right
);
103 return new wxFSFile(s
,
104 left
+ wxT("#zip:") + right
,
105 GetMimeTypeFromExt(location
),
108 , wxDateTime(wxFileModificationTime(left
))
109 #endif // wxUSE_DATETIME
119 wxString
wxZipFSHandler::FindFirst(const wxString
& spec
, int flags
)
121 wxString right
= GetRightLocation(spec
);
122 wxString left
= GetLeftLocation(spec
);
124 if (right
.Last() == wxT('/')) right
.RemoveLast();
128 unzClose((unzFile
)m_Archive
);
132 if (GetProtocol(left
) != wxT("file"))
134 wxLogError(_("ZIP handler currently supports only local files!"));
135 return wxEmptyString
;
141 m_AllowDirs
= FALSE
, m_AllowFiles
= TRUE
; break;
143 m_AllowDirs
= TRUE
, m_AllowFiles
= FALSE
; break;
145 m_AllowDirs
= m_AllowFiles
= TRUE
; break;
149 wxString nativename
= wxFileSystem::URLToFileName(m_ZipFile
).GetFullPath();
150 m_Archive
= (void*) unzOpen(nativename
.mb_str(wxConvFile
));
151 m_Pattern
= right
.AfterLast(wxT('/'));
152 m_BaseDir
= right
.BeforeLast(wxT('/'));
156 if (unzGoToFirstFile((unzFile
)m_Archive
) != UNZ_OK
)
158 unzClose((unzFile
)m_Archive
);
166 m_DirsFound
= new wxLongToLongHashMap();
171 return wxEmptyString
;
176 wxString
wxZipFSHandler::FindNext()
178 if (!m_Archive
) return wxEmptyString
;
184 wxString
wxZipFSHandler::DoFind()
186 static char namebuf
[1024]; // char, not wxChar!
188 wxString namestr
, dir
, filename
;
189 wxString match
= wxEmptyString
;
191 while (match
== wxEmptyString
)
193 unzGetCurrentFileInfo((unzFile
)m_Archive
, NULL
, namebuf
, 1024, NULL
, 0, NULL
, 0);
194 for (c
= namebuf
; *c
; c
++) if (*c
== '\\') *c
= '/';
195 namestr
= wxString::FromAscii(namebuf
); // TODO what encoding does ZIP use?
199 dir
= namestr
.BeforeLast(wxT('/'));
200 while (!dir
.IsEmpty())
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())
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
;
215 break; // already tranversed
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
;
225 if (unzGoToNextFile((unzFile
)m_Archive
) != UNZ_OK
)
227 unzClose((unzFile
)m_Archive
);
239 //wxUSE_FILESYSTEM && wxUSE_FS_ZIP && wxUSE_ZIPSTREAM