1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: zipfile.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_shell.hxx"
33 #include "zipexcptn.hxx"
34 #include "internal/zipfile.hxx"
35 #include "internal/global.hxx"
45 #define _alloca alloca
46 #define ERROR_NOT_ENOUGH_MEMORY 8
51 /* for case in-sensitive string comparison */
52 struct stricmp
: public std::unary_function
<std::string
, bool>
54 stricmp(const std::string
& str
) : str_(str
)
57 bool operator() (const std::string
& other
)
58 { return (0 == _stricmp(str_
.c_str(), other
.c_str())); }
62 } // namespace internal
64 /** Checks whether a file is a zip file or not
66 @precond The given parameter must be a string with length > 0
68 The file must be readable for the current user
70 @returns true if the file is a zip file
71 false if the file is not a zip file
73 @throws ParameterException if the given file name is empty
74 IOException if the specified file doesn't exist
75 AccessViolationException if read access to the file is denied
77 bool ZipFile::IsZipFile(const std::string
& /*FileName*/)
82 bool ZipFile::IsZipFile(void* /*stream*/)
88 /** Returns wheter the version of the specified zip file may be uncompressed with the
89 currently used zlib version or not
91 @precond The given parameter must be a string with length > 0
93 The file must be readable for the current user
94 The file must be a valid zip file
96 @returns true if the file may be uncompressed with the currently used zlib
97 false if the file may not be uncompressed with the currently used zlib
99 @throws ParameterException if the given file name is empty
100 IOException if the specified file doesn't exist or is no zip file
101 AccessViolationException if read access to the file is denied
103 bool ZipFile::IsValidZipFileVersionNumber(const std::string
& /*FileName*/)
108 bool ZipFile::IsValidZipFileVersionNumber(void* /* stream*/)
114 /** Constructs a zip file from a zip file
116 @precond The given parameter must be a string with length > 0
118 The file must be readable for the current user
120 @throws ParameterException if the given file name is empty
121 IOException if the specified file doesn't exist or is no valid zip file
122 AccessViolationException if read access to the file is denied
123 WrongZipVersionException if the zip file cannot be uncompressed
124 with the used zlib version
126 ZipFile::ZipFile(const std::string
& FileName
)
128 m_uzFile
= unzOpen(FileName
.c_str());
131 throw IOException(-1);
134 ZipFile::ZipFile(void* stream
, zlib_filefunc_def
* fa
)
137 m_uzFile
= unzOpen2((const char *)NULL
, fa
);
140 throw IOException(-1);
144 /** Destroys a zip file
151 /** Provides an interface to read the uncompressed data of a content of the zip file
153 @precond The specified content must exist in this file
154 ppstm must not be NULL
156 void ZipFile::GetUncompressedContent(
157 const std::string
& ContentName
, /*inout*/ ZipContentBuffer_t
& ContentBuffer
)
159 int rc
= unzLocateFile(m_uzFile
, ContentName
.c_str(), 0);
161 if (UNZ_END_OF_LIST_OF_FILE
== rc
)
162 throw ZipContentMissException(rc
);
165 unzGetCurrentFileInfo(m_uzFile
, &finfo
, 0, 0, 0, 0, 0, 0);
167 ContentBuffer
.resize(finfo
.uncompressed_size
);
169 rc
= unzOpenCurrentFile(m_uzFile
);
172 throw ZipException(rc
);
174 rc
= unzReadCurrentFile(m_uzFile
, &ContentBuffer
[0], finfo
.uncompressed_size
);
177 throw ZipException(rc
);
179 rc
= unzCloseCurrentFile(m_uzFile
);
182 throw ZipException(rc
);
185 /** Returns a list with the content names contained within this file
188 ZipFile::DirectoryPtr_t
ZipFile::GetDirectory() const
190 DirectoryPtr_t
dir(new Directory_t());
192 long lmax
= GetFileLongestFileNameLength() + 1;
193 char* szFileName
= reinterpret_cast<char*>(_alloca(lmax
));
196 throw ZipException(ERROR_NOT_ENOUGH_MEMORY
);
198 int rc
= unzGoToFirstFile(m_uzFile
);
200 while (UNZ_OK
== rc
&& UNZ_END_OF_LIST_OF_FILE
!= rc
)
202 unzGetCurrentFileInfo(
203 m_uzFile
, 0, szFileName
, lmax
, 0, 0, 0, 0);
205 dir
->push_back(szFileName
);
207 rc
= unzGoToNextFile(m_uzFile
);
210 if (UNZ_OK
!= rc
&& UNZ_END_OF_LIST_OF_FILE
!= rc
)
211 throw ZipException(rc
);
216 /** Convinience query function may even realized with
217 iterating over a ZipFileDirectory returned by
219 bool ZipFile::HasContent(const std::string
& ContentName
) const
221 //#i34314# we need to compare package content names
222 //case in-sensitive as it is not defined that such
223 //names must be handled case sensitive
224 DirectoryPtr_t dir
= GetDirectory();
225 Directory_t::iterator iter
=
226 std::find_if(dir
->begin(), dir
->end(), internal::stricmp(ContentName
));
228 return (iter
!= dir
->end());
232 /** Returns the length of the longest file name
233 in the current zip file
235 long ZipFile::GetFileLongestFileNameLength() const
240 int rc
= unzGoToFirstFile(m_uzFile
);
242 while (UNZ_OK
== rc
&& UNZ_END_OF_LIST_OF_FILE
!= rc
)
244 unzGetCurrentFileInfo(m_uzFile
, &finfo
, 0, 0, 0, 0, 0, 0);
245 lmax
= std::max
<long>(lmax
, finfo
.size_filename
);
246 rc
= unzGoToNextFile(m_uzFile
);
249 if (UNZ_OK
!= rc
&& UNZ_END_OF_LIST_OF_FILE
!= rc
)
250 throw ZipException(rc
);