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