~ubuntu-branches/ubuntu/quantal/poco/quantal

« back to all changes in this revision

Viewing changes to Zip/src/ZipLocalFileHeader.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Krzysztof Burghardt
  • Date: 2008-11-15 11:39:15 UTC
  • mfrom: (3.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20081115113915-7kauhm2c3m2i7oid
Tags: 1.3.3p1-2
* Fixed FTBFS with GCC 4.4 due to missing #include (Closes: #505619)
* Renamed 20_gcc43-missing-include.dpatch to 20_gcc44-missing-include.dpatch
* Downgraded dependencies on -dbg packages (Closes: #504342)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// ZipLocalFileHeader.cpp
 
3
//
 
4
// $Id: //poco/1.3/Zip/src/ZipLocalFileHeader.cpp#4 $
 
5
//
 
6
// Library: Zip
 
7
// Package: Zip
 
8
// Module:  ZipLocalFileHeader
 
9
//
 
10
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
 
11
// and Contributors.
 
12
//
 
13
// Permission is hereby granted, free of charge, to any person or organization
 
14
// obtaining a copy of the software and accompanying documentation covered by
 
15
// this license (the "Software") to use, reproduce, display, distribute,
 
16
// execute, and transmit the Software, and to prepare derivative works of the
 
17
// Software, and to permit third-parties to whom the Software is furnished to
 
18
// do so, all subject to the following:
 
19
// 
 
20
// The copyright notices in the Software and this entire statement, including
 
21
// the above license grant, this restriction and the following disclaimer,
 
22
// must be included in all copies of the Software, in whole or in part, and
 
23
// all derivative works of the Software, unless such copies or derivative
 
24
// works are solely in the form of machine-executable object code generated by
 
25
// a source language processor.
 
26
// 
 
27
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
28
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
29
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 
30
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 
31
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 
32
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
33
// DEALINGS IN THE SOFTWARE.
 
34
//
 
35
 
 
36
 
 
37
#include "Poco/Zip/ZipLocalFileHeader.h"
 
38
#include "Poco/Zip/ZipDataInfo.h"
 
39
#include "Poco/Zip/ParseCallback.h"
 
40
#include "Poco/Buffer.h"
 
41
#include "Poco/Exception.h"
 
42
#include "Poco/File.h"
 
43
#include <cstring>
 
44
 
 
45
 
 
46
namespace Poco {
 
47
namespace Zip {
 
48
 
 
49
 
 
50
const char ZipLocalFileHeader::HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x03', '\x04'};
 
51
 
 
52
 
 
53
ZipLocalFileHeader::ZipLocalFileHeader(const Poco::Path& fileName, 
 
54
        const Poco::DateTime& lastModifiedAt,
 
55
        ZipCommon::CompressionMethod cm, 
 
56
        ZipCommon::CompressionLevel cl):
 
57
        _rawHeader(),
 
58
        _startPos(-1),
 
59
        _endPos(-1),
 
60
        _fileName(),
 
61
        _lastModifiedAt(),
 
62
        _extraField(),
 
63
        _crc32(0),
 
64
        _compressedSize(0),
 
65
        _uncompressedSize(0)
 
66
{
 
67
        std::memcpy(_rawHeader, HEADER, ZipCommon::HEADER_SIZE);
 
68
        std::memset(_rawHeader+ZipCommon::HEADER_SIZE, 0, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE);
 
69
        ZipCommon::HostSystem hs = ZipCommon::HS_FAT;
 
70
 
 
71
#if (POCO_OS == POCO_OS_CYGWIN)
 
72
        hs = ZipCommon::HS_UNIX;
 
73
#endif
 
74
#if (POCO_OS == POCO_OS_VMS)
 
75
        hs = ZipCommon::HS_VMS;
 
76
#endif
 
77
#if defined(POCO_OS_FAMILY_UNIX)
 
78
        hs = ZipCommon::HS_UNIX;
 
79
#endif
 
80
        setHostSystem(hs);
 
81
        setEncryption(false);
 
82
        setExtraFieldSize(0);
 
83
        setLastModifiedAt(lastModifiedAt);
 
84
        init(fileName, cm, cl);
 
85
}
 
86
 
 
87
 
 
88
ZipLocalFileHeader::ZipLocalFileHeader(std::istream& inp, bool assumeHeaderRead, ParseCallback& callback):
 
89
        _rawHeader(),
 
90
        _startPos(inp.tellg()),
 
91
        _endPos(-1),
 
92
        _fileName(),
 
93
        _lastModifiedAt(),
 
94
        _extraField(),
 
95
        _crc32(0),
 
96
        _compressedSize(0),
 
97
        _uncompressedSize(0)
 
98
{
 
99
        poco_assert_dbg( (EXTRAFIELD_POS+EXTRAFIELD_LENGTH) == FULLHEADER_SIZE);
 
100
 
 
101
        if (assumeHeaderRead)
 
102
                _startPos -= ZipCommon::HEADER_SIZE;
 
103
 
 
104
        parse(inp, assumeHeaderRead);
 
105
 
 
106
        bool ok = callback.handleZipEntry(inp, *this);
 
107
 
 
108
        if (ok)
 
109
        {
 
110
                if (searchCRCAndSizesAfterData())
 
111
                {
 
112
                        ZipDataInfo nfo(inp, false);
 
113
                        setCRC(nfo.getCRC32());
 
114
                        setCompressedSize(nfo.getCompressedSize());
 
115
                        setUncompressedSize(nfo.getUncompressedSize());
 
116
                }
 
117
        }
 
118
        else
 
119
        {
 
120
                poco_assert_dbg(!searchCRCAndSizesAfterData());
 
121
                ZipUtil::sync(inp);
 
122
        }
 
123
        _endPos = _startPos + getHeaderSize() + _compressedSize; // exclude the data block!
 
124
}
 
125
 
 
126
 
 
127
ZipLocalFileHeader::~ZipLocalFileHeader()
 
128
{
 
129
}
 
130
 
 
131
 
 
132
void ZipLocalFileHeader::parse(std::istream& inp, bool assumeHeaderRead)
 
133
{
 
134
        if (!assumeHeaderRead)
 
135
        {
 
136
                inp.read(_rawHeader, ZipCommon::HEADER_SIZE);
 
137
        }
 
138
        else
 
139
        {
 
140
                std::memcpy(_rawHeader, HEADER, ZipCommon::HEADER_SIZE);
 
141
        }
 
142
        poco_assert (std::memcmp(_rawHeader, HEADER, ZipCommon::HEADER_SIZE) == 0);
 
143
        // read the rest of the header
 
144
        inp.read(_rawHeader + ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE);
 
145
        poco_assert (_rawHeader[VERSION_POS + 1]>= ZipCommon::HS_FAT && _rawHeader[VERSION_POS + 1] < ZipCommon::HS_UNUSED);
 
146
        poco_assert (getMajorVersionNumber() <= 2);
 
147
        poco_assert (ZipUtil::get16BitValue(_rawHeader, COMPR_METHOD_POS) < ZipCommon::CM_UNUSED);
 
148
        parseDateTime();
 
149
        Poco::UInt16 len = getFileNameLength();
 
150
        Poco::Buffer<char> buf(len);
 
151
        inp.read(buf.begin(), len);
 
152
        _fileName = std::string(buf.begin(), len);
 
153
        if (hasExtraField())
 
154
        {
 
155
                len = getExtraFieldLength();
 
156
                Poco::Buffer<char> xtra(len);
 
157
                inp.read(xtra.begin(), len);
 
158
                _extraField = std::string(xtra.begin(), len);
 
159
        }
 
160
        if (!searchCRCAndSizesAfterData())
 
161
        {
 
162
                _crc32 = getCRCFromHeader();
 
163
                _compressedSize = getCompressedSizeFromHeader();
 
164
                _uncompressedSize = getUncompressedSizeFromHeader();
 
165
        }
 
166
}
 
167
 
 
168
 
 
169
bool ZipLocalFileHeader::searchCRCAndSizesAfterData() const
 
170
{
 
171
        if (getCompressionMethod() == ZipCommon::CM_DEFLATE)
 
172
        {
 
173
                // check bit 3
 
174
                return ((ZipUtil::get16BitValue(_rawHeader, GENERAL_PURPOSE_POS) & 0x0008) != 0);
 
175
        }
 
176
        return false;
 
177
}
 
178
 
 
179
 
 
180
void ZipLocalFileHeader::setFileName(const std::string& fileName, bool isDirectory)
 
181
{
 
182
        poco_assert (!fileName.empty());
 
183
        Poco::Path aPath(fileName);
 
184
 
 
185
        if (isDirectory)
 
186
        {
 
187
                aPath.makeDirectory();
 
188
                setCRC(0);
 
189
                setCompressedSize(0);
 
190
                setUncompressedSize(0);
 
191
                setCompressionMethod(ZipCommon::CM_STORE);
 
192
                setCompressionLevel(ZipCommon::CL_NORMAL);
 
193
        }
 
194
        else
 
195
        {
 
196
                aPath.makeFile();
 
197
        }
 
198
        _fileName = aPath.toString(Poco::Path::PATH_UNIX);
 
199
        if (_fileName[0] == '/')
 
200
                _fileName = _fileName.substr(1);
 
201
        if (isDirectory)
 
202
        {
 
203
                poco_assert_dbg (_fileName[_fileName.size()-1] == '/');
 
204
        }
 
205
        setFileNameLength(static_cast<Poco::UInt16>(_fileName.size()));
 
206
}
 
207
 
 
208
 
 
209
void ZipLocalFileHeader::init(  const Poco::Path& fName, 
 
210
                                                                ZipCommon::CompressionMethod cm, 
 
211
                                                                ZipCommon::CompressionLevel cl)
 
212
{
 
213
        poco_assert (_fileName.empty());
 
214
        setSearchCRCAndSizesAfterData(false);
 
215
        Poco::Path fileName(fName);
 
216
        fileName.setDevice(""); // clear device!
 
217
        setFileName(fileName.toString(Poco::Path::PATH_UNIX), fileName.isDirectory());
 
218
        setRequiredVersion(2, 0);
 
219
        if (fileName.isFile())
 
220
        {
 
221
                setCompressionMethod(cm);
 
222
                setCompressionLevel(cl);
 
223
        }
 
224
        else
 
225
                setCompressionMethod(ZipCommon::CM_STORE);
 
226
}
 
227
 
 
228
 
 
229
std::string ZipLocalFileHeader::createHeader() const
 
230
{
 
231
        std::string result(_rawHeader, FULLHEADER_SIZE);
 
232
        result.append(_fileName);
 
233
        result.append(_extraField);
 
234
        return result;
 
235
}
 
236
 
 
237
 
 
238
} } // namespace Poco::Zip