1/* This file is part of the KDE libraries
2 Copyright (C) 2002 Holger Schroeder <holger-kde@holgis.net>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
17*/
18#ifndef KZIP_H
19#define KZIP_H
20
21#include <karchive.h>
22
23class KZipFileEntry;
24/**
25 * A class for reading / writing zip archives.
26 *
27 * You can use it in QIODevice::ReadOnly or in QIODevice::WriteOnly mode, and it
28 * behaves just as expected.
29 * It can also be used in QIODevice::ReadWrite mode, in this case one can
30 * append files to an existing zip archive. When you append new files, which
31 * are not yet in the zip, it works as expected, i.e. the files are appended at the end.
32 * When you append a file, which is already in the file, the reference to the
33 * old file is dropped and the new one is added to the zip - but the
34 * old data from the file itself is not deleted, it is still in the
35 * zipfile. So when you want to have a small and garbage-free zipfile,
36 * just read the contents of the appended zip file and write it to a new one
37 * in QIODevice::WriteOnly mode. This is especially important when you don't want
38 * to leak information of how intermediate versions of files in the zip
39 * were looking.
40 *
41 * For more information on the zip fileformat go to
42 * http://www.pkware.com/products/enterprise/white_papers/appnote.html
43 * @author Holger Schroeder <holger-kde@holgis.net>
44 */
45class KDECORE_EXPORT KZip : public KArchive
46{
47public:
48 /**
49 * Creates an instance that operates on the given filename.
50 * using the compression filter associated to given mimetype.
51 *
52 * @param filename is a local path (e.g. "/home/holger/myfile.zip")
53 */
54 KZip( const QString& filename );
55
56 /**
57 * Creates an instance that operates on the given device.
58 * The device can be compressed (KFilterDev) or not (QFile, etc.).
59 * @warning Do not assume that giving a QFile here will decompress the file,
60 * in case it's compressed!
61 * @param dev the device to access
62 */
63 KZip( QIODevice * dev );
64
65 /**
66 * If the zip file is still opened, then it will be
67 * closed automatically by the destructor.
68 */
69 virtual ~KZip();
70
71 /**
72 * Describes the contents of the "extra field" for a given file in the Zip archive.
73 */
74 enum ExtraField { NoExtraField = 0, ///< No extra field
75 ModificationTime = 1, ///< Modification time ("extended timestamp" header)
76 DefaultExtraField = 1
77 };
78
79 /**
80 * Call this before writeFile or prepareWriting, to define what the next
81 * file to be written should have in its extra field.
82 * @param ef the type of "extra field"
83 * @see extraField()
84 */
85 void setExtraField( ExtraField ef );
86
87 /**
88 * The current type of "extra field" that will be used for new files.
89 * @return the current type of "extra field"
90 * @see setExtraField()
91 */
92 ExtraField extraField() const;
93
94 /**
95 * Describes the compression type for a given file in the Zip archive.
96 */
97 enum Compression { NoCompression = 0, ///< Uncompressed.
98 DeflateCompression = 1 ///< Deflate compression method.
99 };
100
101
102 /**
103 * Call this before writeFile or prepareWriting, to define whether the next
104 * files to be written should be compressed or not.
105 * @param c the new compression mode
106 * @see compression()
107 */
108 void setCompression( Compression c );
109
110 /**
111 * The current compression mode that will be used for new files.
112 * @return the current compression mode
113 * @see setCompression()
114 */
115 Compression compression() const;
116
117 /**
118 * Write data to a file that has been created using prepareWriting().
119 * @param data a pointer to the data
120 * @param size the size of the chunk
121 * @return true if successful, false otherwise
122 */
123 virtual bool writeData( const char* data, qint64 size );
124
125protected:
126 /// Reimplemented from KArchive
127 virtual bool doWriteSymLink(const QString &name, const QString &target,
128 const QString &user, const QString &group,
129 mode_t perm, time_t atime, time_t mtime, time_t ctime);
130 /// Reimplemented from KArchive
131 virtual bool doPrepareWriting( const QString& name, const QString& user,
132 const QString& group, qint64 size, mode_t perm,
133 time_t atime, time_t mtime, time_t ctime );
134
135 /**
136 * Write data to a file that has been created using prepareWriting().
137 * @param size the size of the file
138 * @return true if successful, false otherwise
139 */
140 virtual bool doFinishWriting( qint64 size );
141
142 /**
143 * Opens the archive for reading.
144 * Parses the directory listing of the archive
145 * and creates the KArchiveDirectory/KArchiveFile entries.
146 * @param mode the mode of the file
147 */
148 virtual bool openArchive( QIODevice::OpenMode mode );
149
150 /// Closes the archive
151 virtual bool closeArchive();
152
153 /// Reimplemented from KArchive
154 virtual bool doWriteDir( const QString& name, const QString& user,
155 const QString& group, mode_t perm, time_t atime,
156 time_t mtime, time_t ctime );
157
158protected:
159 virtual void virtual_hook( int id, void* data );
160
161private:
162 class KZipPrivate;
163 KZipPrivate * const d;
164};
165
166
167/**
168 * A KZipFileEntry represents an file in a zip archive.
169 */
170class KDECORE_EXPORT KZipFileEntry : public KArchiveFile
171{
172public:
173 /**
174 * Creates a new zip file entry. Do not call this, KZip takes care of it.
175 */
176 KZipFileEntry( KZip* zip, const QString& name, int access, int date,
177 const QString& user, const QString& group, const QString& symlink,
178 const QString& path, qint64 start, qint64 uncompressedSize,
179 int encoding, qint64 compressedSize);
180
181 /**
182 * Destructor. Do not call this.
183 */
184 ~KZipFileEntry();
185
186 int encoding() const;
187 qint64 compressedSize() const;
188
189 /// Only used when writing
190 void setCompressedSize(qint64 compressedSize);
191
192 /// Header start: only used when writing
193 void setHeaderStart(qint64 headerstart);
194 qint64 headerStart() const;
195
196 /// CRC: only used when writing
197 unsigned long crc32() const;
198 void setCRC32(unsigned long crc32);
199
200 /// Name with complete path - KArchiveFile::name() is the filename only (no path)
201 const QString &path() const;
202
203 /**
204 * @return the content of this file.
205 * Call data() with care (only once per file), this data isn't cached.
206 */
207 virtual QByteArray data() const;
208
209 /**
210 * This method returns a QIODevice to read the file contents.
211 * This is obviously for reading only.
212 * Note that the ownership of the device is being transferred to the caller,
213 * who will have to delete it.
214 * The returned device auto-opens (in readonly mode), no need to open it.
215 */
216 virtual QIODevice* createDevice() const;
217
218private:
219 class KZipFileEntryPrivate;
220 KZipFileEntryPrivate * const d;
221};
222
223#endif
224