xref: /trunk/main/shell/source/all/zipfile/zipfile.cxx (revision a5b190bfa3e1bed4623e2958a8877664a3b5506c)
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