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