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