xref: /aoo41x/main/shell/source/all/zipfile/zipfile.cxx (revision 5448f169)
1cdf0e10cSrcweir /*************************************************************************
2cdf0e10cSrcweir  *
3cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4cdf0e10cSrcweir  *
5cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6cdf0e10cSrcweir  *
7cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8cdf0e10cSrcweir  *
9cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10cdf0e10cSrcweir  *
11cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14cdf0e10cSrcweir  *
15cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20cdf0e10cSrcweir  *
21cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25cdf0e10cSrcweir  *
26cdf0e10cSrcweir  ************************************************************************/
27cdf0e10cSrcweir 
28cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29cdf0e10cSrcweir #include "precompiled_shell.hxx"
30cdf0e10cSrcweir #include "zipexcptn.hxx"
31cdf0e10cSrcweir #include "internal/zipfile.hxx"
32cdf0e10cSrcweir #include "internal/global.hxx"
33cdf0e10cSrcweir 
34cdf0e10cSrcweir #include <malloc.h>
35cdf0e10cSrcweir #include <algorithm>
36cdf0e10cSrcweir #include <functional>
37cdf0e10cSrcweir 
38cdf0e10cSrcweir #include <string.h>
39cdf0e10cSrcweir 
40cdf0e10cSrcweir #ifdef OS2
41cdf0e10cSrcweir #include <alloca.h>
42cdf0e10cSrcweir #define _alloca alloca
43cdf0e10cSrcweir #define ERROR_NOT_ENOUGH_MEMORY 8
44cdf0e10cSrcweir #endif
45cdf0e10cSrcweir 
46cdf0e10cSrcweir namespace internal
47cdf0e10cSrcweir {
48cdf0e10cSrcweir     /* for case in-sensitive string comparison */
49cdf0e10cSrcweir     struct stricmp : public std::unary_function<std::string, bool>
50cdf0e10cSrcweir     {
51cdf0e10cSrcweir         stricmp(const std::string& str) : str_(str)
52cdf0e10cSrcweir         {}
53cdf0e10cSrcweir 
54cdf0e10cSrcweir         bool operator() (const std::string& other)
55cdf0e10cSrcweir         { return (0 == _stricmp(str_.c_str(), other.c_str())); }
56cdf0e10cSrcweir 
57cdf0e10cSrcweir         std::string str_;
58cdf0e10cSrcweir     };
59cdf0e10cSrcweir } // namespace internal
60cdf0e10cSrcweir 
61cdf0e10cSrcweir /** Checks whether a file is a zip file or not
62cdf0e10cSrcweir 
63cdf0e10cSrcweir 	@precond	The given parameter must be a string with length > 0
64cdf0e10cSrcweir 			The file must exist
65cdf0e10cSrcweir 			The file must be readable for the current user
66cdf0e10cSrcweir 
67cdf0e10cSrcweir 	@returns	true if the file is a zip file
68cdf0e10cSrcweir 			false if the file is not a zip file
69cdf0e10cSrcweir 
70cdf0e10cSrcweir 	@throws	ParameterException if the given file name is empty
71cdf0e10cSrcweir 			IOException if the specified file doesn't exist
72cdf0e10cSrcweir 			AccessViolationException if read access to the file is denied
73cdf0e10cSrcweir */
74cdf0e10cSrcweir bool ZipFile::IsZipFile(const std::string& /*FileName*/)
75cdf0e10cSrcweir {
76cdf0e10cSrcweir 	return true;
77cdf0e10cSrcweir }
78cdf0e10cSrcweir 
79cdf0e10cSrcweir bool ZipFile::IsZipFile(void* /*stream*/)
80cdf0e10cSrcweir {
81cdf0e10cSrcweir 	return true;
82cdf0e10cSrcweir }
83cdf0e10cSrcweir 
84cdf0e10cSrcweir 
85cdf0e10cSrcweir /** Returns wheter the version of the specified zip file may be uncompressed with the
86cdf0e10cSrcweir 	      currently used zlib version or not
87cdf0e10cSrcweir 
88cdf0e10cSrcweir 	@precond	The given parameter must be a string with length > 0
89cdf0e10cSrcweir 			The file must exist
90cdf0e10cSrcweir 			The file must be readable for the current user
91cdf0e10cSrcweir 			The file must be a valid zip file
92cdf0e10cSrcweir 
93cdf0e10cSrcweir 	@returns	true if the file may be uncompressed with the currently used zlib
94cdf0e10cSrcweir 			false if the file may not be uncompressed with the currently used zlib
95cdf0e10cSrcweir 
96cdf0e10cSrcweir 	@throws	ParameterException if the given file name is empty
97cdf0e10cSrcweir 			IOException if the specified file doesn't exist or is no zip file
98cdf0e10cSrcweir 			AccessViolationException if read access to the file is denied
99cdf0e10cSrcweir */
100cdf0e10cSrcweir bool ZipFile::IsValidZipFileVersionNumber(const std::string& /*FileName*/)
101cdf0e10cSrcweir {
102cdf0e10cSrcweir 	return true;
103cdf0e10cSrcweir }
104cdf0e10cSrcweir 
105cdf0e10cSrcweir bool ZipFile::IsValidZipFileVersionNumber(void* /* stream*/)
106cdf0e10cSrcweir {
107cdf0e10cSrcweir 	return true;
108cdf0e10cSrcweir }
109cdf0e10cSrcweir 
110cdf0e10cSrcweir 
111cdf0e10cSrcweir /** Constructs a zip file from a zip file
112cdf0e10cSrcweir 
113cdf0e10cSrcweir 	@precond	The given parameter must be a string with length > 0
114cdf0e10cSrcweir 			The file must exist
115cdf0e10cSrcweir 			The file must be readable for the current user
116cdf0e10cSrcweir 
117cdf0e10cSrcweir 	@throws	ParameterException if the given file name is empty
118cdf0e10cSrcweir 			IOException if the specified file doesn't exist or is no valid zip file
119cdf0e10cSrcweir 			AccessViolationException if read access to the file is denied
120cdf0e10cSrcweir 			WrongZipVersionException if the zip file cannot be uncompressed
121cdf0e10cSrcweir 			with the used zlib version
122cdf0e10cSrcweir */
123cdf0e10cSrcweir ZipFile::ZipFile(const std::string& FileName)
124cdf0e10cSrcweir {
125cdf0e10cSrcweir 	m_uzFile = unzOpen(FileName.c_str());
126cdf0e10cSrcweir 
127cdf0e10cSrcweir 	if (0 == m_uzFile)
128cdf0e10cSrcweir 		throw IOException(-1);
129cdf0e10cSrcweir }
130cdf0e10cSrcweir 
131cdf0e10cSrcweir ZipFile::ZipFile(void* stream, zlib_filefunc_def* fa)
132cdf0e10cSrcweir {
133cdf0e10cSrcweir 	fa->opaque = stream;
134cdf0e10cSrcweir 	m_uzFile = unzOpen2((const char *)NULL, fa);
135cdf0e10cSrcweir 
136cdf0e10cSrcweir 	if (0 == m_uzFile)
137cdf0e10cSrcweir 		throw IOException(-1);
138cdf0e10cSrcweir }
139cdf0e10cSrcweir 
140cdf0e10cSrcweir 
141cdf0e10cSrcweir /** Destroys a zip file
142cdf0e10cSrcweir */
143cdf0e10cSrcweir ZipFile::~ZipFile()
144cdf0e10cSrcweir {
145cdf0e10cSrcweir 	unzClose(m_uzFile);
146cdf0e10cSrcweir }
147cdf0e10cSrcweir 
148cdf0e10cSrcweir /** Provides an interface to read the uncompressed data of a content of the zip file
149cdf0e10cSrcweir 
150cdf0e10cSrcweir 	@precond	The specified content must exist in this file
151cdf0e10cSrcweir 			ppstm must not be NULL
152cdf0e10cSrcweir */
153cdf0e10cSrcweir void ZipFile::GetUncompressedContent(
154cdf0e10cSrcweir 	const std::string& ContentName, /*inout*/ ZipContentBuffer_t& ContentBuffer)
155cdf0e10cSrcweir {
156cdf0e10cSrcweir 	int rc = unzLocateFile(m_uzFile, ContentName.c_str(), 0);
157cdf0e10cSrcweir 
158cdf0e10cSrcweir 	if (UNZ_END_OF_LIST_OF_FILE == rc)
159cdf0e10cSrcweir 		throw ZipContentMissException(rc);
160cdf0e10cSrcweir 
161cdf0e10cSrcweir 	unz_file_info finfo;
162cdf0e10cSrcweir 	unzGetCurrentFileInfo(m_uzFile, &finfo, 0, 0, 0, 0, 0, 0);
163cdf0e10cSrcweir 
164cdf0e10cSrcweir 	ContentBuffer.resize(finfo.uncompressed_size);
165cdf0e10cSrcweir 
166cdf0e10cSrcweir 	rc = unzOpenCurrentFile(m_uzFile);
167cdf0e10cSrcweir 
168cdf0e10cSrcweir 	if (UNZ_OK != rc)
169cdf0e10cSrcweir 		throw ZipException(rc);
170cdf0e10cSrcweir 
171cdf0e10cSrcweir 	rc = unzReadCurrentFile(m_uzFile, &ContentBuffer[0], finfo.uncompressed_size);
172cdf0e10cSrcweir 
173cdf0e10cSrcweir 	if (rc < 0)
174cdf0e10cSrcweir 		throw ZipException(rc);
175cdf0e10cSrcweir 
176cdf0e10cSrcweir 	rc = unzCloseCurrentFile(m_uzFile);
177cdf0e10cSrcweir 
178cdf0e10cSrcweir 	if (rc < 0)
179cdf0e10cSrcweir 		throw ZipException(rc);
180cdf0e10cSrcweir }
181cdf0e10cSrcweir 
182cdf0e10cSrcweir /** Returns a list with the content names contained within this file
183cdf0e10cSrcweir 
184cdf0e10cSrcweir */
185cdf0e10cSrcweir ZipFile::DirectoryPtr_t ZipFile::GetDirectory() const
186cdf0e10cSrcweir {
187cdf0e10cSrcweir 	DirectoryPtr_t dir(new Directory_t());
188cdf0e10cSrcweir 
189cdf0e10cSrcweir 	long lmax = GetFileLongestFileNameLength() + 1;
190cdf0e10cSrcweir 	char* szFileName = reinterpret_cast<char*>(_alloca(lmax));
191cdf0e10cSrcweir 
192cdf0e10cSrcweir 	if (!szFileName)
193cdf0e10cSrcweir 		throw ZipException(ERROR_NOT_ENOUGH_MEMORY);
194cdf0e10cSrcweir 
195cdf0e10cSrcweir 	int rc = unzGoToFirstFile(m_uzFile);
196cdf0e10cSrcweir 
197cdf0e10cSrcweir 	while (UNZ_OK == rc && UNZ_END_OF_LIST_OF_FILE != rc)
198cdf0e10cSrcweir 	{
199*5448f169SMichael Stahl 		unz_file_info finfo;
200cdf0e10cSrcweir 		unzGetCurrentFileInfo(
201*5448f169SMichael Stahl 			m_uzFile, &finfo, szFileName, lmax, 0, 0, 0, 0);
202cdf0e10cSrcweir 
203cdf0e10cSrcweir 		dir->push_back(szFileName);
204cdf0e10cSrcweir 
205cdf0e10cSrcweir 		rc = unzGoToNextFile(m_uzFile);
206cdf0e10cSrcweir 	}
207cdf0e10cSrcweir 
208cdf0e10cSrcweir 	if (UNZ_OK != rc && UNZ_END_OF_LIST_OF_FILE != rc)
209cdf0e10cSrcweir 		throw ZipException(rc);
210cdf0e10cSrcweir 
211cdf0e10cSrcweir 	return dir;
212cdf0e10cSrcweir }
213cdf0e10cSrcweir 
214cdf0e10cSrcweir /** Convinience query function may even realized with
215cdf0e10cSrcweir 	iterating over a ZipFileDirectory returned by
216cdf0e10cSrcweir 	GetDirectory */
217cdf0e10cSrcweir bool ZipFile::HasContent(const std::string& ContentName) const
218cdf0e10cSrcweir {
219cdf0e10cSrcweir     //#i34314# we need to compare package content names
220cdf0e10cSrcweir     //case in-sensitive as it is not defined that such
221cdf0e10cSrcweir     //names must be handled case sensitive
222cdf0e10cSrcweir 	DirectoryPtr_t dir = GetDirectory();
223cdf0e10cSrcweir 	Directory_t::iterator iter =
224cdf0e10cSrcweir         std::find_if(dir->begin(), dir->end(), internal::stricmp(ContentName));
225cdf0e10cSrcweir 
226cdf0e10cSrcweir 	return (iter != dir->end());
227cdf0e10cSrcweir }
228cdf0e10cSrcweir 
229cdf0e10cSrcweir 
230cdf0e10cSrcweir /** Returns the length of the longest file name
231cdf0e10cSrcweir 		in the current zip file
232cdf0e10cSrcweir */
233cdf0e10cSrcweir long ZipFile::GetFileLongestFileNameLength() const
234cdf0e10cSrcweir {
235cdf0e10cSrcweir 	long lmax = 0;
236cdf0e10cSrcweir 	unz_file_info finfo;
237cdf0e10cSrcweir 
238cdf0e10cSrcweir 	int rc = unzGoToFirstFile(m_uzFile);
239cdf0e10cSrcweir 
240cdf0e10cSrcweir 	while (UNZ_OK == rc && UNZ_END_OF_LIST_OF_FILE != rc)
241cdf0e10cSrcweir 	{
242cdf0e10cSrcweir 		unzGetCurrentFileInfo(m_uzFile,	&finfo, 0, 0, 0, 0, 0, 0);
243cdf0e10cSrcweir 		lmax = std::max<long>(lmax, finfo.size_filename);
244cdf0e10cSrcweir 		rc = unzGoToNextFile(m_uzFile);
245cdf0e10cSrcweir 	}
246cdf0e10cSrcweir 
247cdf0e10cSrcweir 	if (UNZ_OK != rc && UNZ_END_OF_LIST_OF_FILE != rc)
248cdf0e10cSrcweir 		throw ZipException(rc);
249cdf0e10cSrcweir 
250cdf0e10cSrcweir 	return lmax;
251cdf0e10cSrcweir }
252cdf0e10cSrcweir 
253