xref: /trunk/main/shell/source/all/zipfile/zipfile.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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         unzGetCurrentFileInfo(
200             m_uzFile, 0, szFileName, lmax, 0, 0, 0, 0);
201 
202         dir->push_back(szFileName);
203 
204         rc = unzGoToNextFile(m_uzFile);
205     }
206 
207     if (UNZ_OK != rc && UNZ_END_OF_LIST_OF_FILE != rc)
208         throw ZipException(rc);
209 
210     return dir;
211 }
212 
213 /** Convinience query function may even realized with
214     iterating over a ZipFileDirectory returned by
215     GetDirectory */
216 bool ZipFile::HasContent(const std::string& ContentName) const
217 {
218     //#i34314# we need to compare package content names
219     //case in-sensitive as it is not defined that such
220     //names must be handled case sensitive
221     DirectoryPtr_t dir = GetDirectory();
222     Directory_t::iterator iter =
223         std::find_if(dir->begin(), dir->end(), internal::stricmp(ContentName));
224 
225     return (iter != dir->end());
226 }
227 
228 
229 /** Returns the length of the longest file name
230         in the current zip file
231 */
232 long ZipFile::GetFileLongestFileNameLength() const
233 {
234     long lmax = 0;
235     unz_file_info finfo;
236 
237     int rc = unzGoToFirstFile(m_uzFile);
238 
239     while (UNZ_OK == rc && UNZ_END_OF_LIST_OF_FILE != rc)
240     {
241         unzGetCurrentFileInfo(m_uzFile, &finfo, 0, 0, 0, 0, 0, 0);
242         lmax = std::max<long>(lmax, finfo.size_filename);
243         rc = unzGoToNextFile(m_uzFile);
244     }
245 
246     if (UNZ_OK != rc && UNZ_END_OF_LIST_OF_FILE != rc)
247         throw ZipException(rc);
248 
249     return lmax;
250 }
251 
252