summaryrefslogtreecommitdiffstats
path: root/tdeio/tdeio/kzip.h
blob: 333736e2192026d36f1f5281dbf81c479c1ae5d4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
/* This file is part of the KDE libraries
   Copyright (C) 2002 Holger Schroeder <holger-kde@holgis.net>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/
#ifndef __kzip_h
#define __kzip_h

#include <sys/stat.h>
#include <sys/types.h>

#include <tqdatetime.h>
#include <tqstring.h>
#include <tqstringlist.h>
#include <tqdict.h>
#include <tqvaluelist.h>
#include <karchive.h>

class KZipFileEntry;
/**
 *   This class implements a tdeioslave to access zip files from KDE.
 *   You can use it in IO_ReadOnly or in IO_WriteOnly mode, and it
 *   behaves just as expected.
 *   It can also be used in IO_ReadWrite mode, in this case one can
 *   append files to an existing zip archive. When you append new files, which
 *   are not yet in the zip, it works as expected, i.e. the files are appended at the end.
 *   When you append a file, which is already in the file, the reference to the
 *   old file is dropped and the new one is added to the zip - but the
 *   old data from the file itself is not deleted, it is still in the
 *   zipfile. so when you want to have a small and garbage-free zipfile,
 *   just read the contents of the appended zip file and write it to a new one
 *   in IO_WriteOnly mode. This is especially important when you don't want
 *   to leak information of how intermediate versions of files in the zip
 *   were looking.
 *   For more information on the zip fileformat go to
 *   http://www.pkware.com/products/enterprise/white_papers/appnote.html
 * @short A class for reading/writing zip archives.
 * @author Holger Schroeder <holger-kde@holgis.net>
 * @since 3.1
 */
class TDEIO_EXPORT KZip : public KArchive
{
public:
    /**
     * Creates an instance that operates on the given filename.
     * using the compression filter associated to given mimetype.
     *
     * @param filename is a local path (e.g. "/home/holger/myfile.zip")
     */
    KZip( const TQString& filename );

    /**
     * Creates an instance that operates on the given device.
     * The device can be compressed (KFilterDev) or not (TQFile, etc.).
     * @warning Do not assume that giving a TQFile here will decompress the file,
     * in case it's compressed!
     * @param dev the device to access
     */
    KZip( TQIODevice * dev );

    /**
     * If the zip file is still opened, then it will be
     * closed automatically by the destructor.
     */
    virtual ~KZip();

    /**
     * The name of the zip file, as passed to the constructor.
     * Null if you used the TQIODevice constructor.
     * @return the zip's file name, or null if a TQIODevice is used
     */
    TQString fileName() { return m_filename; }

    /**
     * Describes the contents of the "extra field" for a given file in the Zip archive.
     */
    enum ExtraField { NoExtraField = 0,      ///< No extra field
                      ModificationTime = 1,  ///< Modification time ("extended timestamp" header)
                      DefaultExtraField = 1
    };

    /**
     * Call this before writeFile or prepareWriting, to define what the next
     * file to be written should have in its extra field.
     * @param ef the type of "extra field"
     * @see extraField()
     */
    void setExtraField( ExtraField ef );

    /**
     * The current type of "extra field" that will be used for new files.
     * @return the current type of "extra field"
     * @see setExtraField()
     */
    ExtraField extraField() const;

    /**
     * Describes the compression type for a given file in the Zip archive.
     */
    enum Compression { NoCompression = 0,     ///< Uncompressed.
		       DeflateCompression = 1 ///< Deflate compression method.
    };


    /**
     * Call this before writeFile or prepareWriting, to define whether the next
     * files to be written should be compressed or not.
     * @param c the new compression mode
     * @see compression()
     */
    void setCompression( Compression c );

    /**
     * The current compression mode that will be used for new files.
     * @return the current compression mode
     * @see setCompression()
     */
    Compression compression() const;

    /**
     * If an archive is opened for writing then you can add a new file
     * using this function.
     * This method takes the whole data at once.
     * @param name can include subdirs e.g. path/to/the/file
     * @param user the user owning the file
     * @param group the group owning the file
     * @param size the size of the file
     * @param data a pointer to the data
     * @return true if successful, false otherwise
     */
    virtual bool writeFile( const TQString& name, const TQString& user, const TQString& group, uint size, const char* data ); // BC: remove reimplementation for KDE-4.0

    /**
     * Alternative method for writing: call prepareWriting(), then feed the data
     * in small chunks using writeData(), and call doneWriting() when done.
     * @param name can include subdirs e.g. path/to/the/file
     * @param user the user owning the file
     * @param group the group owning the file
     * @param size unused argument
     * @return true if successful, false otherwise
     */
    virtual bool prepareWriting( const TQString& name, const TQString& user, const TQString& group, uint size );

    // TODO(BIC) make virtual. For now it must be implemented by virtual_hook.
    bool writeSymLink(const TQString &name, const TQString &target,
                        const TQString &user, const TQString &group,
                        mode_t perm, time_t atime, time_t mtime, time_t ctime);
    // TODO(BIC) make virtual. For now it must be implemented by virtual_hook.
    bool prepareWriting( const TQString& name, const TQString& user,
                        const TQString& group, uint size, mode_t perm,
                        time_t atime, time_t mtime, time_t ctime );
    // TODO(BIC) make virtual. For now it must be implemented by virtual_hook.
    bool writeFile( const TQString& name, const TQString& user, const TQString& group,
                        uint size, mode_t perm, time_t atime, time_t mtime,
                        time_t ctime, const char* data );
    /**
     * Write data to a file that has been created using prepareWriting().
     * @param data a pointer to the data
     * @param size the size of the chunk
     * @return true if successful, false otherwise
     */
    bool writeData( const char* data, uint size ); // TODO make virtual

    /**
     * Write data to a file that has been created using prepareWriting().
     * @param size the size of the file
     * @return true if successful, false otherwise
     */
    virtual bool doneWriting( uint size );

protected:
    /**
     * Opens the archive for reading.
     * Parses the directory listing of the archive
     * and creates the KArchiveDirectory/KArchiveFile entries.
     * @param mode the mode of the file
     */
    virtual bool openArchive( int mode );
    /// Closes the archive
    virtual bool closeArchive();

    /**
     * @internal Not needed for zip
     */
    virtual bool writeDir( const TQString& name, const TQString& user, const TQString& group) { Q_UNUSED(name); Q_UNUSED(user); Q_UNUSED(group); return true; }
    // TODO(BIC) uncomment and make virtual for KDE 4.
//    bool writeDir( const TQString& name, const TQString& user, const TQString& group,
//                        mode_t perm, time_t atime, time_t mtime, time_t ctime );

protected:
    virtual void virtual_hook( int id, void* data );
    /** @internal for virtual_hook */
    // from KArchive
    bool writeData_impl( const char* data, uint size );
    bool prepareWriting_impl(const TQString& name, const TQString& user,
                        const TQString& group, uint size, mode_t perm,
                        time_t atime, time_t mtime, time_t ctime);
    bool writeSymLink_impl(const TQString &name, const TQString &target,
                        const TQString &user, const TQString &group,
                        mode_t perm, time_t atime, time_t mtime, time_t ctime);
private:
    void abort();

private:
    TQString m_filename;
    class KZipPrivate;
    KZipPrivate * d;
};


/**
 * @internal
 */
class TDEIO_EXPORT KZipFileEntry : public KArchiveFile
{
public:
    /*KZipFileEntry() : st(-1)
      {}*/
    KZipFileEntry( KZip* zip, const TQString& name, int access, int date,
                   const TQString& user, const TQString& group, const TQString& symlink,
                   const TQString& path, TQ_LONG start, TQ_LONG uncompressedSize,
                   int encoding, TQ_LONG compressedSize) :
        KArchiveFile( zip, name, access, date, user, group, symlink,
                      start, uncompressedSize ),
        m_crc(0),
        m_compressedSize(compressedSize),
        m_headerStart(0),
        m_encoding(encoding),
        m_path( path )
    {}
    int encoding() const { return m_encoding; }
    TQ_LONG compressedSize() const { return m_compressedSize; }

    /// Only used when writing
    void setCompressedSize(TQ_LONG compressedSize) { m_compressedSize = compressedSize; }

    /// Header start: only used when writing
    void setHeaderStart(TQ_LONG headerstart) { m_headerStart = headerstart; }
    TQ_LONG headerStart() const {return m_headerStart; }

    /// CRC: only used when writing
    unsigned long crc32() const { return m_crc; }
    void setCRC32(unsigned long crc32) { m_crc=crc32; }

    /// Name with complete path - KArchiveFile::name() is the filename only (no path)
    TQString path() const { return m_path; }

    /**
     * @return the content of this file.
     * Call data() with care (only once per file), this data isn't cached.
     */
    virtual TQByteArray data() const;

    /**
     * This method returns a TQIODevice to read the file contents.
     * This is obviously for reading only.
     * Note that the ownership of the device is being transferred to the caller,
     * who will have to delete it.
     * The returned device auto-opens (in readonly mode), no need to open it.
     */
    TQIODevice* device() const; // WARNING, not virtual!

private:
    unsigned long m_crc;
    TQ_LONG m_compressedSize;
    TQ_LONG m_headerStart;
    int m_encoding;
    TQString m_path;
    // KDE4: d pointer or at least some int for future extensions
};

#endif